[SCM] Samba Shared Repository - branch master updated
Amitay Isaacs
amitay at samba.org
Tue Mar 6 20:58:02 MST 2012
The branch, master has been updated
via 8ad1986 lib/tdb2: add --valgrind, --valgrind-log options.
via 74d5222 lib/tdb2: wire up unit tests.
via 9d897b0 lib/tdb2: adapt unit tests to SAMBA environment.
via 361f3ea lib/ccan: import failtest and required ccan modules for TDB2 unit tests.
from 4f5412d s3:selftest: ask smbtorture4 for smb2 tests
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 8ad1986a9666670a0e979751795340820768a4b2
Author: Rusty Russell <rusty at rustcorp.com.au>
Date: Wed Feb 22 17:21:13 2012 +1030
lib/tdb2: add --valgrind, --valgrind-log options.
Not used by default, since it slows down testing (on my laptop) from
22 seconds to 2 minutes 30 seconds.
Signed-off-by: Rusty Russell <rusty at rustcorp.com.au>
Autobuild-User: Amitay Isaacs <amitay at samba.org>
Autobuild-Date: Wed Mar 7 04:57:21 CET 2012 on sn-devel-104
commit 74d522237e6fc63e1e9331c82c04a809b3df3a65
Author: Rusty Russell <rusty at rustcorp.com.au>
Date: Wed Feb 22 17:21:04 2012 +1030
lib/tdb2: wire up unit tests.
The tests are ccan-style, so the names tell how to link them. This
logic is generic, and could be moved to wafsamba, cleaned up, and used
elsewhere.
Signed-off-by: Rusty Russell <rusty at rustcorp.com.au>
commit 9d897b0951e73a4717ae133d5b6b2493334fbf22
Author: Rusty Russell <rusty at rustcorp.com.au>
Date: Wed Feb 22 15:03:37 2012 +1030
lib/tdb2: adapt unit tests to SAMBA environment.
This means changing headers, implementing a simple tap-like wrapper,
and also splitting out the helpers into those which are linked with
the api* tests (which can't use non-public tdb2 functions) and those
linked with the run* tests (which can).
Signed-off-by: Rusty Russell <rusty at rustcorp.com.au>
commit 361f3ea9ee577c5a3e2fed687a0b417b257c31de
Author: Rusty Russell <rusty at rustcorp.com.au>
Date: Wed Feb 22 14:59:32 2012 +1030
lib/ccan: import failtest and required ccan modules for TDB2 unit tests.
New modules: failtest, list, time, read_write_all and tlist.
Signed-off-by: Rusty Russell <rusty at rustcorp.com.au>
-----------------------------------------------------------------------
Summary of changes:
lib/ccan/check_type/_info | 33 +
lib/ccan/check_type/check_type.h | 63 +
lib/ccan/check_type/test/compile_fail-check_type.c | 9 +
.../test/compile_fail-check_type_unsigned.c | 14 +
.../test/compile_fail-check_types_match.c | 10 +
lib/ccan/check_type/test/run.c | 22 +
lib/ccan/container_of/_info | 63 +
lib/ccan/container_of/container_of.h | 108 ++
lib/ccan/container_of/test/compile_fail-bad-type.c | 22 +
lib/ccan/container_of/test/compile_fail-types.c | 22 +
.../container_of/test/compile_fail-var-types.c | 25 +
lib/ccan/container_of/test/run.c | 26 +
lib/ccan/{compiler => failtest}/LICENSE | 0
lib/ccan/failtest/_info | 76 +
lib/ccan/failtest/failtest.c | 1713 ++++++++++++++++++++
lib/ccan/failtest/failtest.d | 70 +
lib/ccan/failtest/failtest.h | 258 +++
lib/ccan/failtest/failtest_override.h | 81 +
lib/ccan/failtest/failtest_proto.h | 31 +
lib/ccan/failtest/failtest_undo.h | 49 +
lib/ccan/failtest/test/run-failpath.c | 39 +
lib/ccan/failtest/test/run-history.c | 183 +++
lib/ccan/failtest/test/run-locking.c | 134 ++
lib/ccan/failtest/test/run-malloc.c | 116 ++
lib/ccan/failtest/test/run-open.c | 72 +
lib/ccan/failtest/test/run-write.c | 51 +
lib/ccan/{asearch => list}/LICENSE | 0
lib/ccan/list/_info | 70 +
lib/ccan/list/list.c | 43 +
lib/ccan/list/list.d | 27 +
lib/ccan/list/list.h | 469 ++++++
lib/ccan/list/test/compile_ok-constant.c | 49 +
lib/ccan/list/test/helper.c | 54 +
lib/ccan/list/test/helper.h | 7 +
lib/ccan/list/test/run-check-corrupt.c | 89 +
lib/ccan/list/test/run-list_del_from-assert.c | 36 +
lib/ccan/list/test/run-single-eval.c | 168 ++
lib/ccan/list/test/run-with-debug.c | 3 +
lib/ccan/list/test/run.c | 200 +++
lib/ccan/{asearch => read_write_all}/LICENSE | 0
lib/ccan/read_write_all/_info | 44 +
lib/ccan/read_write_all/read_write_all.c | 38 +
lib/ccan/read_write_all/read_write_all.d | 19 +
lib/ccan/read_write_all/read_write_all.h | 10 +
lib/ccan/read_write_all/test/run-read_all.c | 76 +
lib/ccan/read_write_all/test/run-write_all.c | 68 +
lib/ccan/tcon/_info | 74 +
lib/ccan/tcon/tcon.h | 115 ++
lib/ccan/tcon/test/compile_fail-tcon_cast.c | 29 +
lib/ccan/tcon/test/compile_fail.c | 25 +
lib/ccan/tcon/test/compile_ok-void.c | 21 +
lib/ccan/tcon/test/compile_ok.c | 27 +
lib/ccan/time/LICENSE | 17 +
lib/ccan/time/_info | 47 +
lib/ccan/time/test/run.c | 111 ++
lib/ccan/time/time.c | 108 ++
lib/ccan/time/time.d | 25 +
lib/ccan/time/time.h | 184 +++
lib/ccan/{compiler => tlist}/LICENSE | 0
lib/ccan/tlist/_info | 74 +
lib/ccan/tlist/test/compile_fail-tlist_add.c | 35 +
lib/ccan/tlist/test/compile_fail-tlist_add_tail.c | 35 +
lib/ccan/tlist/test/compile_fail-tlist_del_from.c | 34 +
lib/ccan/tlist/test/compile_fail-tlist_for_each.c | 34 +
.../tlist/test/compile_fail-tlist_for_each_safe.c | 33 +
lib/ccan/tlist/test/compile_fail-tlist_tail.c | 31 +
lib/ccan/tlist/test/compile_fail-tlist_top.c | 31 +
lib/ccan/tlist/test/run.c | 147 ++
lib/ccan/tlist/tlist.h | 265 +++
lib/tdb2/Makefile | 1 +
lib/tdb2/test/api-12-store.c | 5 +-
lib/tdb2/test/api-13-delete.c | 6 +-
lib/tdb2/test/api-14-exists.c | 5 +-
lib/tdb2/test/api-16-wipe_all.c | 5 +-
lib/tdb2/test/api-21-parse_record.c | 5 +-
lib/tdb2/test/api-55-transaction.c | 6 +-
lib/tdb2/test/api-80-tdb_fd.c | 5 +-
lib/tdb2/test/api-81-seqnum.c | 5 +-
lib/tdb2/test/api-82-lockattr.c | 6 +-
lib/tdb2/test/api-83-openhook.c | 5 +-
lib/tdb2/test/api-91-get-stats.c | 5 +-
lib/tdb2/test/api-92-get-set-readonly.c | 5 +-
lib/tdb2/test/api-93-repack.c | 5 +-
lib/tdb2/test/api-add-remove-flags.c | 6 +-
lib/tdb2/test/api-check-callback.c | 5 +-
lib/tdb2/test/api-firstkey-nextkey.c | 5 +-
lib/tdb2/test/api-fork-test.c | 5 +-
lib/tdb2/test/api-locktimeout.c | 6 +-
lib/tdb2/test/api-missing-entries.c | 5 +-
lib/tdb2/test/api-open-multiple-times.c | 5 +-
lib/tdb2/test/api-record-expand.c | 5 +-
lib/tdb2/test/api-simple-delete.c | 5 +-
lib/tdb2/test/api-summary.c | 5 +-
lib/tdb2/test/api-tdb1-flag-removal.c | 5 +-
lib/tdb2/test/external-agent.c | 12 +-
lib/tdb2/test/external-agent.h | 7 +-
lib/tdb2/test/failtest_helper.c | 2 +-
lib/tdb2/test/helpapi-external-agent.c | 8 +
lib/tdb2/test/helprun-external-agent.c | 10 +
lib/tdb2/test/{layout.c => helprun-layout.c} | 0
lib/tdb2/test/layout.h | 2 +-
lib/tdb2/test/lock-tracking.c | 4 +-
lib/tdb2/test/logging.c | 2 +-
lib/tdb2/test/logging.h | 2 +-
lib/tdb2/test/run-001-encode.c | 2 +-
lib/tdb2/test/run-001-fls.c | 2 +-
lib/tdb2/test/run-01-new_database.c | 2 +-
lib/tdb2/test/run-02-expand.c | 2 +-
lib/tdb2/test/run-03-coalesce.c | 2 +-
lib/tdb2/test/run-04-basichash.c | 2 +-
lib/tdb2/test/run-05-readonly-open.c | 2 +-
lib/tdb2/test/run-10-simple-store.c | 2 +-
lib/tdb2/test/run-11-simple-fetch.c | 2 +-
lib/tdb2/test/run-12-check.c | 4 +-
lib/tdb2/test/run-15-append.c | 2 +-
lib/tdb2/test/run-20-growhash.c | 2 +-
lib/tdb2/test/run-25-hashoverload.c | 2 +-
lib/tdb2/test/run-30-exhaust-before-expand.c | 2 +-
lib/tdb2/test/run-35-convert.c | 4 +-
lib/tdb2/test/run-50-multiple-freelists.c | 2 +-
lib/tdb2/test/run-56-open-during-transaction.c | 4 +-
lib/tdb2/test/run-57-die-during-transaction.c | 4 +-
lib/tdb2/test/run-64-bit-tdb.c | 2 +-
lib/tdb2/test/run-90-get-set-attributes.c | 2 +-
lib/tdb2/test/run-capabilities.c | 2 +-
lib/tdb2/test/run-expand-in-transaction.c | 2 +-
lib/tdb2/test/run-features.c | 2 +-
lib/tdb2/test/run-lockall.c | 4 +-
lib/tdb2/test/run-remap-in-read_traverse.c | 2 +-
lib/tdb2/test/run-seed.c | 2 +-
lib/tdb2/test/run-tdb1-3G-file.c | 2 +-
lib/tdb2/test/run-tdb1-bad-tdb-header.c | 2 +-
lib/tdb2/test/run-tdb1-check.c | 2 +-
lib/tdb2/test/run-tdb1-corrupt.c | 2 +-
lib/tdb2/test/run-tdb1-endian.c | 2 +-
lib/tdb2/test/run-tdb1-hashsize.c | 2 +-
lib/tdb2/test/run-tdb1-incompatible.c | 2 +-
lib/tdb2/test/run-tdb1-nested-transactions.c | 2 +-
lib/tdb2/test/run-tdb1-nested-traverse.c | 2 +-
lib/tdb2/test/run-tdb1-no-lock-during-traverse.c | 4 +-
lib/tdb2/test/run-tdb1-oldhash.c | 2 +-
lib/tdb2/test/run-tdb1-readonly-check.c | 2 +-
lib/tdb2/test/run-tdb1-rwlock-check.c | 2 +-
lib/tdb2/test/run-tdb1-seqnum-wrap.c | 2 +-
lib/tdb2/test/run-tdb1-summary.c | 2 +-
lib/tdb2/test/run-tdb1-traverse-in-transaction.c | 2 +-
lib/tdb2/test/run-tdb1-wronghash-fail.c | 2 +-
lib/tdb2/test/run-tdb1-zero-append.c | 2 +-
lib/tdb2/test/run-tdb1.c | 2 +-
lib/tdb2/test/run-tdb_errorstr.c | 2 +-
lib/tdb2/test/run-tdb_foreach.c | 2 +-
lib/tdb2/test/run-traverse.c | 2 +-
lib/tdb2/test/tap-interface.c | 3 +
lib/tdb2/test/tap-interface.h | 41 +
lib/tdb2/test/tdb1-external-agent.c | 6 +-
lib/tdb2/test/tdb1-external-agent.h | 3 +
lib/tdb2/test/tdb1-lock-tracking.c | 4 +-
lib/tdb2/test/tdb1-lock-tracking.h | 2 +-
lib/tdb2/test/tdb2-source.h | 40 +-
lib/tdb2/wscript | 93 ++-
160 files changed, 6589 insertions(+), 148 deletions(-)
create mode 100644 lib/ccan/check_type/_info
create mode 100644 lib/ccan/check_type/check_type.h
create mode 100644 lib/ccan/check_type/test/compile_fail-check_type.c
create mode 100644 lib/ccan/check_type/test/compile_fail-check_type_unsigned.c
create mode 100644 lib/ccan/check_type/test/compile_fail-check_types_match.c
create mode 100644 lib/ccan/check_type/test/run.c
create mode 100644 lib/ccan/container_of/_info
create mode 100644 lib/ccan/container_of/container_of.h
create mode 100644 lib/ccan/container_of/test/compile_fail-bad-type.c
create mode 100644 lib/ccan/container_of/test/compile_fail-types.c
create mode 100644 lib/ccan/container_of/test/compile_fail-var-types.c
create mode 100644 lib/ccan/container_of/test/run.c
copy lib/ccan/{compiler => failtest}/LICENSE (100%)
create mode 100644 lib/ccan/failtest/_info
create mode 100644 lib/ccan/failtest/failtest.c
create mode 100644 lib/ccan/failtest/failtest.d
create mode 100644 lib/ccan/failtest/failtest.h
create mode 100644 lib/ccan/failtest/failtest_override.h
create mode 100644 lib/ccan/failtest/failtest_proto.h
create mode 100644 lib/ccan/failtest/failtest_undo.h
create mode 100644 lib/ccan/failtest/test/run-failpath.c
create mode 100644 lib/ccan/failtest/test/run-history.c
create mode 100644 lib/ccan/failtest/test/run-locking.c
create mode 100644 lib/ccan/failtest/test/run-malloc.c
create mode 100644 lib/ccan/failtest/test/run-open.c
create mode 100644 lib/ccan/failtest/test/run-write.c
copy lib/ccan/{asearch => list}/LICENSE (100%)
create mode 100644 lib/ccan/list/_info
create mode 100644 lib/ccan/list/list.c
create mode 100644 lib/ccan/list/list.d
create mode 100644 lib/ccan/list/list.h
create mode 100644 lib/ccan/list/test/compile_ok-constant.c
create mode 100644 lib/ccan/list/test/helper.c
create mode 100644 lib/ccan/list/test/helper.h
create mode 100644 lib/ccan/list/test/run-check-corrupt.c
create mode 100644 lib/ccan/list/test/run-list_del_from-assert.c
create mode 100644 lib/ccan/list/test/run-single-eval.c
create mode 100644 lib/ccan/list/test/run-with-debug.c
create mode 100644 lib/ccan/list/test/run.c
copy lib/ccan/{asearch => read_write_all}/LICENSE (100%)
create mode 100644 lib/ccan/read_write_all/_info
create mode 100644 lib/ccan/read_write_all/read_write_all.c
create mode 100644 lib/ccan/read_write_all/read_write_all.d
create mode 100644 lib/ccan/read_write_all/read_write_all.h
create mode 100644 lib/ccan/read_write_all/test/run-read_all.c
create mode 100644 lib/ccan/read_write_all/test/run-write_all.c
create mode 100644 lib/ccan/tcon/_info
create mode 100644 lib/ccan/tcon/tcon.h
create mode 100644 lib/ccan/tcon/test/compile_fail-tcon_cast.c
create mode 100644 lib/ccan/tcon/test/compile_fail.c
create mode 100644 lib/ccan/tcon/test/compile_ok-void.c
create mode 100644 lib/ccan/tcon/test/compile_ok.c
create mode 100644 lib/ccan/time/LICENSE
create mode 100644 lib/ccan/time/_info
create mode 100644 lib/ccan/time/test/run.c
create mode 100644 lib/ccan/time/time.c
create mode 100644 lib/ccan/time/time.d
create mode 100644 lib/ccan/time/time.h
copy lib/ccan/{compiler => tlist}/LICENSE (100%)
create mode 100644 lib/ccan/tlist/_info
create mode 100644 lib/ccan/tlist/test/compile_fail-tlist_add.c
create mode 100644 lib/ccan/tlist/test/compile_fail-tlist_add_tail.c
create mode 100644 lib/ccan/tlist/test/compile_fail-tlist_del_from.c
create mode 100644 lib/ccan/tlist/test/compile_fail-tlist_for_each.c
create mode 100644 lib/ccan/tlist/test/compile_fail-tlist_for_each_safe.c
create mode 100644 lib/ccan/tlist/test/compile_fail-tlist_tail.c
create mode 100644 lib/ccan/tlist/test/compile_fail-tlist_top.c
create mode 100644 lib/ccan/tlist/test/run.c
create mode 100644 lib/ccan/tlist/tlist.h
create mode 100644 lib/tdb2/test/helpapi-external-agent.c
create mode 100644 lib/tdb2/test/helprun-external-agent.c
rename lib/tdb2/test/{layout.c => helprun-layout.c} (100%)
create mode 100644 lib/tdb2/test/tap-interface.c
create mode 100644 lib/tdb2/test/tap-interface.h
Changeset truncated at 500 lines:
diff --git a/lib/ccan/check_type/_info b/lib/ccan/check_type/_info
new file mode 100644
index 0000000..33448b4
--- /dev/null
+++ b/lib/ccan/check_type/_info
@@ -0,0 +1,33 @@
+#include <stdio.h>
+#include <string.h>
+#include "config.h"
+
+/**
+ * check_type - routines for compile time type checking
+ *
+ * C has fairly weak typing: ints get automatically converted to longs, signed
+ * to unsigned, etc. There are some cases where this is best avoided, and
+ * these macros provide methods for evoking warnings (or build errors) when
+ * a precise type isn't used.
+ *
+ * On compilers which don't support typeof() these routines are less effective,
+ * since they have to use sizeof() which can only distiguish between types of
+ * different size.
+ *
+ * License: Public domain
+ * Author: Rusty Russell <rusty at rustcorp.com.au>
+ */
+int main(int argc, char *argv[])
+{
+ if (argc != 2)
+ return 1;
+
+ if (strcmp(argv[1], "depends") == 0) {
+#if !HAVE_TYPEOF
+ printf("ccan/build_assert\n");
+#endif
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/lib/ccan/check_type/check_type.h b/lib/ccan/check_type/check_type.h
new file mode 100644
index 0000000..b199347
--- /dev/null
+++ b/lib/ccan/check_type/check_type.h
@@ -0,0 +1,63 @@
+#ifndef CCAN_CHECK_TYPE_H
+#define CCAN_CHECK_TYPE_H
+#include "config.h"
+
+/**
+ * check_type - issue a warning or build failure if type is not correct.
+ * @expr: the expression whose type we should check (not evaluated).
+ * @type: the exact type we expect the expression to be.
+ *
+ * This macro is usually used within other macros to try to ensure that a macro
+ * argument is of the expected type. No type promotion of the expression is
+ * done: an unsigned int is not the same as an int!
+ *
+ * check_type() always evaluates to 0.
+ *
+ * If your compiler does not support typeof, then the best we can do is fail
+ * to compile if the sizes of the types are unequal (a less complete check).
+ *
+ * Example:
+ * // They should always pass a 64-bit value to _set_some_value!
+ * #define set_some_value(expr) \
+ * _set_some_value((check_type((expr), uint64_t), (expr)))
+ */
+
+/**
+ * check_types_match - issue a warning or build failure if types are not same.
+ * @expr1: the first expression (not evaluated).
+ * @expr2: the second expression (not evaluated).
+ *
+ * This macro is usually used within other macros to try to ensure that
+ * arguments are of identical types. No type promotion of the expressions is
+ * done: an unsigned int is not the same as an int!
+ *
+ * check_types_match() always evaluates to 0.
+ *
+ * If your compiler does not support typeof, then the best we can do is fail
+ * to compile if the sizes of the types are unequal (a less complete check).
+ *
+ * Example:
+ * // Do subtraction to get to enclosing type, but make sure that
+ * // pointer is of correct type for that member.
+ * #define container_of(mbr_ptr, encl_type, mbr) \
+ * (check_types_match((mbr_ptr), &((encl_type *)0)->mbr), \
+ * ((encl_type *) \
+ * ((char *)(mbr_ptr) - offsetof(enclosing_type, mbr))))
+ */
+#if HAVE_TYPEOF
+#define check_type(expr, type) \
+ ((typeof(expr) *)0 != (type *)0)
+
+#define check_types_match(expr1, expr2) \
+ ((typeof(expr1) *)0 != (typeof(expr2) *)0)
+#else
+#include <ccan/build_assert/build_assert.h>
+/* Without typeof, we can only test the sizes. */
+#define check_type(expr, type) \
+ BUILD_ASSERT_OR_ZERO(sizeof(expr) == sizeof(type))
+
+#define check_types_match(expr1, expr2) \
+ BUILD_ASSERT_OR_ZERO(sizeof(expr1) == sizeof(expr2))
+#endif /* HAVE_TYPEOF */
+
+#endif /* CCAN_CHECK_TYPE_H */
diff --git a/lib/ccan/check_type/test/compile_fail-check_type.c b/lib/ccan/check_type/test/compile_fail-check_type.c
new file mode 100644
index 0000000..fe7d6a2
--- /dev/null
+++ b/lib/ccan/check_type/test/compile_fail-check_type.c
@@ -0,0 +1,9 @@
+#include <ccan/check_type/check_type.h>
+
+int main(int argc, char *argv[])
+{
+#ifdef FAIL
+ check_type(argc, char);
+#endif
+ return 0;
+}
diff --git a/lib/ccan/check_type/test/compile_fail-check_type_unsigned.c b/lib/ccan/check_type/test/compile_fail-check_type_unsigned.c
new file mode 100644
index 0000000..574d4ae
--- /dev/null
+++ b/lib/ccan/check_type/test/compile_fail-check_type_unsigned.c
@@ -0,0 +1,14 @@
+#include <ccan/check_type/check_type.h>
+
+int main(int argc, char *argv[])
+{
+#ifdef FAIL
+#if HAVE_TYPEOF
+ check_type(argc, unsigned int);
+#else
+ /* This doesn't work without typeof, so just fail */
+#error "Fail without typeof"
+#endif
+#endif
+ return 0;
+}
diff --git a/lib/ccan/check_type/test/compile_fail-check_types_match.c b/lib/ccan/check_type/test/compile_fail-check_types_match.c
new file mode 100644
index 0000000..cbd6e9b
--- /dev/null
+++ b/lib/ccan/check_type/test/compile_fail-check_types_match.c
@@ -0,0 +1,10 @@
+#include <ccan/check_type/check_type.h>
+
+int main(int argc, char *argv[])
+{
+ unsigned char x = argc;
+#ifdef FAIL
+ check_types_match(argc, x);
+#endif
+ return x;
+}
diff --git a/lib/ccan/check_type/test/run.c b/lib/ccan/check_type/test/run.c
new file mode 100644
index 0000000..83b903c
--- /dev/null
+++ b/lib/ccan/check_type/test/run.c
@@ -0,0 +1,22 @@
+#include <ccan/check_type/check_type.h>
+#include <ccan/tap/tap.h>
+
+int main(int argc, char *argv[])
+{
+ int x = 0, y = 0;
+
+ plan_tests(9);
+
+ ok1(check_type(argc, int) == 0);
+ ok1(check_type(&argc, int *) == 0);
+ ok1(check_types_match(argc, argc) == 0);
+ ok1(check_types_match(argc, x) == 0);
+ ok1(check_types_match(&argc, &x) == 0);
+
+ ok1(check_type(x++, int) == 0);
+ ok(x == 0, "check_type does not evaluate expression");
+ ok1(check_types_match(x++, y++) == 0);
+ ok(x == 0 && y == 0, "check_types_match does not evaluate expressions");
+
+ return exit_status();
+}
diff --git a/lib/ccan/container_of/_info b/lib/ccan/container_of/_info
new file mode 100644
index 0000000..2f45ca7
--- /dev/null
+++ b/lib/ccan/container_of/_info
@@ -0,0 +1,63 @@
+#include <stdio.h>
+#include <string.h>
+#include "config.h"
+
+/**
+ * container_of - routine for upcasting
+ *
+ * It is often convenient to create code where the caller registers a pointer
+ * to a generic structure and a callback. The callback might know that the
+ * pointer points to within a larger structure, and container_of gives a
+ * convenient and fairly type-safe way of returning to the enclosing structure.
+ *
+ * This idiom is an alternative to providing a void * pointer for every
+ * callback.
+ *
+ * Example:
+ * #include <stdio.h>
+ * #include <ccan/container_of/container_of.h>
+ *
+ * struct timer {
+ * void *members;
+ * };
+ *
+ * struct info {
+ * int my_stuff;
+ * struct timer timer;
+ * };
+ *
+ * static void register_timer(struct timer *timer)
+ * {
+ * //...
+ * }
+ *
+ * static void my_timer_callback(struct timer *timer)
+ * {
+ * struct info *info = container_of(timer, struct info, timer);
+ * printf("my_stuff is %u\n", info->my_stuff);
+ * }
+ *
+ * int main(void)
+ * {
+ * struct info info = { .my_stuff = 1 };
+ *
+ * register_timer(&info.timer);
+ * // ...
+ * return 0;
+ * }
+ *
+ * License: Public domain
+ * Author: Rusty Russell <rusty at rustcorp.com.au>
+ */
+int main(int argc, char *argv[])
+{
+ if (argc != 2)
+ return 1;
+
+ if (strcmp(argv[1], "depends") == 0) {
+ printf("ccan/check_type\n");
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/lib/ccan/container_of/container_of.h b/lib/ccan/container_of/container_of.h
new file mode 100644
index 0000000..1c9d147
--- /dev/null
+++ b/lib/ccan/container_of/container_of.h
@@ -0,0 +1,108 @@
+#ifndef CCAN_CONTAINER_OF_H
+#define CCAN_CONTAINER_OF_H
+#include <stddef.h>
+
+#include "config.h"
+#include <ccan/check_type/check_type.h>
+
+/**
+ * container_of - get pointer to enclosing structure
+ * @member_ptr: pointer to the structure member
+ * @containing_type: the type this member is within
+ * @member: the name of this member within the structure.
+ *
+ * Given a pointer to a member of a structure, this macro does pointer
+ * subtraction to return the pointer to the enclosing type.
+ *
+ * Example:
+ * struct foo {
+ * int fielda, fieldb;
+ * // ...
+ * };
+ * struct info {
+ * int some_other_field;
+ * struct foo my_foo;
+ * };
+ *
+ * static struct info *foo_to_info(struct foo *foo)
+ * {
+ * return container_of(foo, struct info, my_foo);
+ * }
+ */
+#define container_of(member_ptr, containing_type, member) \
+ ((containing_type *) \
+ ((char *)(member_ptr) \
+ - container_off(containing_type, member)) \
+ + check_types_match(*(member_ptr), ((containing_type *)0)->member))
+
+/**
+ * container_off - get offset to enclosing structure
+ * @containing_type: the type this member is within
+ * @member: the name of this member within the structure.
+ *
+ * Given a pointer to a member of a structure, this macro does
+ * typechecking and figures out the offset to the enclosing type.
+ *
+ * Example:
+ * struct foo {
+ * int fielda, fieldb;
+ * // ...
+ * };
+ * struct info {
+ * int some_other_field;
+ * struct foo my_foo;
+ * };
+ *
+ * static struct info *foo_to_info(struct foo *foo)
+ * {
+ * size_t off = container_off(struct info, my_foo);
+ * return (void *)((char *)foo - off);
+ * }
+ */
+#define container_off(containing_type, member) \
+ offsetof(containing_type, member)
+
+/**
+ * container_of_var - get pointer to enclosing structure using a variable
+ * @member_ptr: pointer to the structure member
+ * @container_var: a pointer of same type as this member's container
+ * @member: the name of this member within the structure.
+ *
+ * Given a pointer to a member of a structure, this macro does pointer
+ * subtraction to return the pointer to the enclosing type.
+ *
+ * Example:
+ * static struct info *foo_to_i(struct foo *foo)
+ * {
+ * struct info *i = container_of_var(foo, i, my_foo);
+ * return i;
+ * }
+ */
+#if HAVE_TYPEOF
+#define container_of_var(member_ptr, container_var, member) \
+ container_of(member_ptr, typeof(*container_var), member)
+#else
+#define container_of_var(member_ptr, container_var, member) \
+ ((void *)((char *)(member_ptr) - \
+ container_off_var(container_var, member)))
+#endif
+
+/**
+ * container_off_var - get offset of a field in enclosing structure
+ * @container_var: a pointer to a container structure
+ * @member: the name of a member within the structure.
+ *
+ * Given (any) pointer to a structure and a its member name, this
+ * macro does pointer subtraction to return offset of member in a
+ * structure memory layout.
+ *
+ */
+#if HAVE_TYPEOF
+#define container_off_var(var, member) \
+ container_off(typeof(*var), member)
+#else
+#define container_off_var(var, member) \
+ ((char *)&(var)->member - (char *)(var))
+#endif
+
+#endif /* CCAN_CONTAINER_OF_H */
diff --git a/lib/ccan/container_of/test/compile_fail-bad-type.c b/lib/ccan/container_of/test/compile_fail-bad-type.c
new file mode 100644
index 0000000..b7a1459
--- /dev/null
+++ b/lib/ccan/container_of/test/compile_fail-bad-type.c
@@ -0,0 +1,22 @@
+#include <ccan/container_of/container_of.h>
+#include <stdlib.h>
+
+struct foo {
+ int a;
+ char b;
+};
+
+int main(int argc, char *argv[])
+{
+ struct foo foo = { .a = 1, .b = 2 };
+ int *intp = &foo.a;
+ char *p;
+
+#ifdef FAIL
+ /* p is a char *, but this gives a struct foo * */
+ p = container_of(intp, struct foo, a);
+#else
+ p = (char *)intp;
+#endif
+ return p == NULL;
+}
diff --git a/lib/ccan/container_of/test/compile_fail-types.c b/lib/ccan/container_of/test/compile_fail-types.c
new file mode 100644
index 0000000..cae1c7a
--- /dev/null
+++ b/lib/ccan/container_of/test/compile_fail-types.c
@@ -0,0 +1,22 @@
+#include <ccan/container_of/container_of.h>
+#include <stdlib.h>
+
+struct foo {
+ int a;
+ char b;
+};
+
+int main(int argc, char *argv[])
+{
+ struct foo foo = { .a = 1, .b = 2 }, *foop;
+ int *intp = &foo.a;
+
+#ifdef FAIL
+ /* b is a char, but intp is an int * */
+ foop = container_of(intp, struct foo, b);
+#else
+ foop = NULL;
+#endif
+ (void) foop; /* Suppress unused-but-set-variable warning. */
+ return intp == NULL;
+}
diff --git a/lib/ccan/container_of/test/compile_fail-var-types.c b/lib/ccan/container_of/test/compile_fail-var-types.c
new file mode 100644
index 0000000..f254d92
--- /dev/null
+++ b/lib/ccan/container_of/test/compile_fail-var-types.c
@@ -0,0 +1,25 @@
+#include <ccan/container_of/container_of.h>
+#include <stdlib.h>
+
+struct foo {
+ int a;
+ char b;
+};
+
+int main(int argc, char *argv[])
+{
+ struct foo foo = { .a = 1, .b = 2 }, *foop;
+ int *intp = &foo.a;
+
+#ifdef FAIL
+ /* b is a char, but intp is an int * */
+ foop = container_of_var(intp, foop, b);
+#if !HAVE_TYPEOF
+#error "Unfortunately we don't fail if we don't have typeof."
+#endif
+#else
+ foop = NULL;
+#endif
+ (void) foop; /* Suppress unused-but-set-variable warning. */
+ return intp == NULL;
+}
diff --git a/lib/ccan/container_of/test/run.c b/lib/ccan/container_of/test/run.c
new file mode 100644
index 0000000..5da440a
--- /dev/null
+++ b/lib/ccan/container_of/test/run.c
@@ -0,0 +1,26 @@
+#include <ccan/container_of/container_of.h>
+#include <ccan/tap/tap.h>
+
+struct foo {
+ int a;
+ char b;
+};
+
+int main(int argc, char *argv[])
+{
+ struct foo foo = { .a = 1, .b = 2 };
+ int *intp = &foo.a;
+ char *charp = &foo.b;
+
+ plan_tests(8);
+ ok1(container_of(intp, struct foo, a) == &foo);
+ ok1(container_of(charp, struct foo, b) == &foo);
+ ok1(container_of_var(intp, &foo, a) == &foo);
+ ok1(container_of_var(charp, &foo, b) == &foo);
+
+ ok1(container_off(struct foo, a) == 0);
+ ok1(container_off(struct foo, b) == offsetof(struct foo, b));
+ ok1(container_off_var(&foo, a) == 0);
+ ok1(container_off_var(&foo, b) == offsetof(struct foo, b));
+ return exit_status();
+}
diff --git a/lib/ccan/compiler/LICENSE b/lib/ccan/failtest/LICENSE
similarity index 100%
copy from lib/ccan/compiler/LICENSE
copy to lib/ccan/failtest/LICENSE
diff --git a/lib/ccan/failtest/_info b/lib/ccan/failtest/_info
new file mode 100644
index 0000000..14dcb78
--- /dev/null
+++ b/lib/ccan/failtest/_info
@@ -0,0 +1,76 @@
+#include <stdio.h>
--
Samba Shared Repository
More information about the samba-cvs
mailing list