summaryrefslogtreecommitdiff
path: root/lib/ccan
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ccan')
-rw-r--r--lib/ccan/check_type/_info33
-rw-r--r--lib/ccan/check_type/check_type.h63
-rw-r--r--lib/ccan/check_type/test/compile_fail-check_type.c9
-rw-r--r--lib/ccan/check_type/test/compile_fail-check_type_unsigned.c14
-rw-r--r--lib/ccan/check_type/test/compile_fail-check_types_match.c10
-rw-r--r--lib/ccan/check_type/test/run.c22
-rw-r--r--lib/ccan/container_of/_info63
-rw-r--r--lib/ccan/container_of/container_of.h108
-rw-r--r--lib/ccan/container_of/test/compile_fail-bad-type.c22
-rw-r--r--lib/ccan/container_of/test/compile_fail-types.c22
-rw-r--r--lib/ccan/container_of/test/compile_fail-var-types.c25
-rw-r--r--lib/ccan/container_of/test/run.c26
-rw-r--r--lib/ccan/failtest/LICENSE165
-rw-r--r--lib/ccan/failtest/_info76
-rw-r--r--lib/ccan/failtest/failtest.c1713
-rw-r--r--lib/ccan/failtest/failtest.d70
-rw-r--r--lib/ccan/failtest/failtest.h258
-rw-r--r--lib/ccan/failtest/failtest_override.h81
-rw-r--r--lib/ccan/failtest/failtest_proto.h31
-rw-r--r--lib/ccan/failtest/failtest_undo.h49
-rw-r--r--lib/ccan/failtest/test/run-failpath.c39
-rw-r--r--lib/ccan/failtest/test/run-history.c183
-rw-r--r--lib/ccan/failtest/test/run-locking.c134
-rw-r--r--lib/ccan/failtest/test/run-malloc.c116
-rw-r--r--lib/ccan/failtest/test/run-open.c72
-rw-r--r--lib/ccan/failtest/test/run-write.c51
-rw-r--r--lib/ccan/list/LICENSE508
-rw-r--r--lib/ccan/list/_info70
-rw-r--r--lib/ccan/list/list.c43
-rw-r--r--lib/ccan/list/list.d27
-rw-r--r--lib/ccan/list/list.h469
-rw-r--r--lib/ccan/list/test/compile_ok-constant.c49
-rw-r--r--lib/ccan/list/test/helper.c54
-rw-r--r--lib/ccan/list/test/helper.h7
-rw-r--r--lib/ccan/list/test/run-check-corrupt.c89
-rw-r--r--lib/ccan/list/test/run-list_del_from-assert.c36
-rw-r--r--lib/ccan/list/test/run-single-eval.c168
-rw-r--r--lib/ccan/list/test/run-with-debug.c3
-rw-r--r--lib/ccan/list/test/run.c200
-rw-r--r--lib/ccan/read_write_all/LICENSE508
-rw-r--r--lib/ccan/read_write_all/_info44
-rw-r--r--lib/ccan/read_write_all/read_write_all.c38
-rw-r--r--lib/ccan/read_write_all/read_write_all.d19
-rw-r--r--lib/ccan/read_write_all/read_write_all.h10
-rw-r--r--lib/ccan/read_write_all/test/run-read_all.c76
-rw-r--r--lib/ccan/read_write_all/test/run-write_all.c68
-rw-r--r--lib/ccan/tcon/_info74
-rw-r--r--lib/ccan/tcon/tcon.h115
-rw-r--r--lib/ccan/tcon/test/compile_fail-tcon_cast.c29
-rw-r--r--lib/ccan/tcon/test/compile_fail.c25
-rw-r--r--lib/ccan/tcon/test/compile_ok-void.c21
-rw-r--r--lib/ccan/tcon/test/compile_ok.c27
-rw-r--r--lib/ccan/time/LICENSE17
-rw-r--r--lib/ccan/time/_info47
-rw-r--r--lib/ccan/time/test/run.c111
-rw-r--r--lib/ccan/time/time.c108
-rw-r--r--lib/ccan/time/time.d25
-rw-r--r--lib/ccan/time/time.h184
-rw-r--r--lib/ccan/tlist/LICENSE165
-rw-r--r--lib/ccan/tlist/_info74
-rw-r--r--lib/ccan/tlist/test/compile_fail-tlist_add.c35
-rw-r--r--lib/ccan/tlist/test/compile_fail-tlist_add_tail.c35
-rw-r--r--lib/ccan/tlist/test/compile_fail-tlist_del_from.c34
-rw-r--r--lib/ccan/tlist/test/compile_fail-tlist_for_each.c34
-rw-r--r--lib/ccan/tlist/test/compile_fail-tlist_for_each_safe.c33
-rw-r--r--lib/ccan/tlist/test/compile_fail-tlist_tail.c31
-rw-r--r--lib/ccan/tlist/test/compile_fail-tlist_top.c31
-rw-r--r--lib/ccan/tlist/test/run.c147
-rw-r--r--lib/ccan/tlist/tlist.h265
69 files changed, 7608 insertions, 0 deletions
diff --git a/lib/ccan/check_type/_info b/lib/ccan/check_type/_info
new file mode 100644
index 0000000000..33448b4f1f
--- /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@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 0000000000..b199347116
--- /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 0000000000..fe7d6a235c
--- /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 0000000000..574d4aeb24
--- /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 0000000000..cbd6e9bc5b
--- /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 0000000000..83b903c0b1
--- /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 0000000000..2f45ca7ccd
--- /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@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 0000000000..1c9d147ae0
--- /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 0000000000..b7a1459386
--- /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 0000000000..cae1c7abd2
--- /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 0000000000..f254d92102
--- /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 0000000000..5da440a1e5
--- /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/failtest/LICENSE b/lib/ccan/failtest/LICENSE
new file mode 100644
index 0000000000..cca7fc278f
--- /dev/null
+++ b/lib/ccan/failtest/LICENSE
@@ -0,0 +1,165 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/lib/ccan/failtest/_info b/lib/ccan/failtest/_info
new file mode 100644
index 0000000000..14dcb783be
--- /dev/null
+++ b/lib/ccan/failtest/_info
@@ -0,0 +1,76 @@
+#include <stdio.h>
+#include <string.h>
+#include "config.h"
+
+/**
+ * failtest - unit test helpers for testing malloc and other failures.
+ *
+ * The failtest module overrides various standard functions, and forks
+ * your unit test at those points to test failure paths. The failing
+ * child are expected to fail (eg. when malloc fails), but should not
+ * leak memory or crash. After including failtest_override.h, you can
+ * include failtest_restore.h to return to non-failing versions.
+ *
+ * The unit test is a normal CCAN tap-style test, except it should
+ * start by calling failtest_init() and end by calling
+ * failtest_exit().
+ *
+ * You can control what functions fail: see failtest_hook.
+ *
+ * Example:
+ * #include <stdio.h>
+ * #include <stdlib.h>
+ * #include <string.h>
+ * #include <ccan/tap/tap.h>
+ * #include <ccan/failtest/failtest_override.h>
+ * #include <ccan/failtest/failtest.h>
+ *
+ * int main(int argc, char *argv[])
+ * {
+ * char *a, *b;
+ *
+ * failtest_init(argc, argv);
+ * plan_tests(3);
+ *
+ * // Simple malloc test.
+ * a = malloc(100);
+ * if (ok1(a)) {
+ * // Fill the memory.
+ * memset(a, 'x', 100);
+ * b = realloc(a, 200);
+ * if (ok1(b)) {
+ * // Fill the rest of the memory.
+ * memset(b + 100, 'y', 100);
+ * // Check it got a copy of a as expected.
+ * ok1(strspn(b, "x") == 100);
+ * free(b);
+ * } else {
+ * // Easy to miss: free a on realloc failure!
+ * free(a);
+ * }
+ * }
+ * failtest_exit(exit_status());
+ * }
+ *
+ * License: LGPL
+ * Author: Rusty Russell <rusty@rustcorp.com.au>
+ */
+int main(int argc, char *argv[])
+{
+ if (argc != 2)
+ return 1;
+
+ if (strcmp(argv[1], "depends") == 0) {
+ printf("ccan/build_assert\n");
+ printf("ccan/compiler\n");
+ printf("ccan/hash\n");
+ printf("ccan/htable\n");
+ printf("ccan/read_write_all\n");
+ printf("ccan/str\n");
+ printf("ccan/time\n");
+ printf("ccan/tlist\n");
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/lib/ccan/failtest/failtest.c b/lib/ccan/failtest/failtest.c
new file mode 100644
index 0000000000..701586e9b8
--- /dev/null
+++ b/lib/ccan/failtest/failtest.c
@@ -0,0 +1,1713 @@
+/* Licensed under LGPL - see LICENSE file for details */
+#include <ccan/failtest/failtest.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <err.h>
+#include <unistd.h>
+#include <poll.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <signal.h>
+#include <assert.h>
+#include <ccan/time/time.h>
+#include <ccan/read_write_all/read_write_all.h>
+#include <ccan/failtest/failtest_proto.h>
+#include <ccan/build_assert/build_assert.h>
+#include <ccan/hash/hash.h>
+#include <ccan/htable/htable_type.h>
+#include <ccan/str/str.h>
+#include <ccan/compiler/compiler.h>
+
+enum failtest_result (*failtest_hook)(struct tlist_calls *);
+
+static FILE *tracef = NULL, *warnf;
+static int traceindent = 0;
+
+unsigned int failtest_timeout_ms = 20000;
+
+const char *failpath;
+const char *debugpath;
+
+enum info_type {
+ WRITE,
+ RELEASE_LOCKS,
+ FAILURE,
+ SUCCESS,
+ UNEXPECTED
+};
+
+struct lock_info {
+ int fd;
+ /* end is inclusive: you can't have a 0-byte lock. */
+ off_t start, end;
+ int type;
+};
+
+/* We hash the call location together with its backtrace. */
+static size_t hash_call(const struct failtest_call *call)
+{
+ return hash(call->file, strlen(call->file),
+ hash(&call->line, 1,
+ hash(call->backtrace, call->backtrace_num,
+ call->type)));
+}
+
+static bool call_eq(const struct failtest_call *call1,
+ const struct failtest_call *call2)
+{
+ unsigned int i;
+
+ if (strcmp(call1->file, call2->file) != 0
+ || call1->line != call2->line
+ || call1->type != call2->type
+ || call1->backtrace_num != call2->backtrace_num)
+ return false;
+
+ for (i = 0; i < call1->backtrace_num; i++)
+ if (call1->backtrace[i] != call2->backtrace[i])
+ return false;
+
+ return true;
+}
+
+/* Defines struct failtable. */
+HTABLE_DEFINE_TYPE(struct failtest_call, (struct failtest_call *), hash_call,
+ call_eq, failtable);
+
+bool (*failtest_exit_check)(struct tlist_calls *history);
+
+/* The entire history of all calls. */
+static struct tlist_calls history = TLIST_INIT(history);
+/* If we're a child, the fd two write control info to the parent. */
+static int control_fd = -1;
+/* If we're a child, this is the first call we did ourselves. */
+static struct failtest_call *our_history_start = NULL;
+/* For printing runtime with --trace. */
+static struct timeval start;
+/* Set when failtest_hook returns FAIL_PROBE */
+static bool probing = false;
+/* Table to track duplicates. */
+static struct failtable failtable;
+
+/* Array of writes which our child did. We report them on failure. */
+static struct write_call *child_writes = NULL;
+static unsigned int child_writes_num = 0;
+
+/* fcntl locking info. */
+static pid_t lock_owner;
+static struct lock_info *locks = NULL;
+static unsigned int lock_num = 0;
+
+/* Our original pid, which we return to anyone who asks. */
+static pid_t orig_pid;
+
+/* Mapping from failtest_type to char. */
+static const char info_to_arg[] = "mceoxprwfal";
+
+/* Dummy call used for failtest_undo wrappers. */
+static struct failtest_call unrecorded_call;
+
+struct contents_saved {
+ size_t count;
+ off_t off;
+ off_t old_len;
+ char contents[1];
+};
+
+/* File contents, saved in this child only. */
+struct saved_mmapped_file {
+ struct saved_mmapped_file *next;
+ struct failtest_call *opener;
+ struct contents_saved *s;
+};
+
+static struct saved_mmapped_file *saved_mmapped_files;
+
+#if HAVE_BACKTRACE
+#include <execinfo.h>
+
+static void **get_backtrace(unsigned int *num)
+{
+ static unsigned int max_back = 100;
+ void **ret;
+
+again:
+ ret = malloc(max_back * sizeof(void *));
+ *num = backtrace(ret, max_back);
+ if (*num == max_back) {
+ free(ret);
+ max_back *= 2;
+ goto again;
+ }
+ return ret;
+}
+#else
+/* This will test slightly less, since will consider all of the same
+ * calls as identical. But, it's slightly faster! */
+static void **get_backtrace(unsigned int *num)
+{
+ *num = 0;
+ return NULL;
+}
+#endif /* HAVE_BACKTRACE */
+
+static struct failtest_call *add_history_(enum failtest_call_type type,
+ bool can_leak,
+ const char *file,
+ unsigned int line,
+ const void *elem,
+ size_t elem_size)
+{
+ struct failtest_call *call;
+
+ /* NULL file is how we suppress failure. */
+ if (!file)
+ return &unrecorded_call;
+
+ call = malloc(sizeof *call);
+ call->type = type;
+ call->can_leak = can_leak;
+ call->file = file;
+ call->line = line;
+ call->cleanup = NULL;
+ call->backtrace = get_backtrace(&call->backtrace_num);
+ memcpy(&call->u, elem, elem_size);
+ tlist_add_tail(&history, call, list);
+ return call;
+}
+
+#define add_history(type, can_leak, file, line, elem) \
+ add_history_((type), (can_leak), (file), (line), (elem), sizeof(*(elem)))
+
+/* We do a fake call inside a sizeof(), to check types. */
+#define set_cleanup(call, clean, type) \
+ (call)->cleanup = (void *)((void)sizeof(clean((type *)NULL, false),1), (clean))
+
+/* Dup the fd to a high value (out of the way I hope!), and close the old fd. */
+static int move_fd_to_high(int fd)
+{
+ int i;
+
+ for (i = FD_SETSIZE - 1; i >= 0; i--) {
+ if (fcntl(i, F_GETFL) == -1 && errno == EBADF) {
+ if (dup2(fd, i) == -1)
+ err(1, "Failed to dup fd %i to %i", fd, i);
+ close(fd);
+ return i;
+ }
+ }
+ /* Nothing? Really? Er... ok? */
+ return fd;
+}
+
+static bool read_write_info(int fd)
+{
+ struct write_call *w;
+ char *buf;
+
+ /* We don't need all of this, but it's simple. */
+ child_writes = realloc(child_writes,
+ (child_writes_num+1) * sizeof(child_writes[0]));
+ w = &child_writes[child_writes_num];
+ if (!read_all(fd, w, sizeof(*w)))
+ return false;
+
+ w->buf = buf = malloc(w->count);
+ if (!read_all(fd, buf, w->count))
+ return false;
+
+ child_writes_num++;
+ return true;
+}
+
+static char *failpath_string(void)
+{
+ struct failtest_call *i;
+ char *ret = strdup("");
+ unsigned len = 0;
+
+ /* Inefficient, but who cares? */
+ tlist_for_each(&history, i, list) {
+ ret = realloc(ret, len + 2);
+ ret[len] = info_to_arg[i->type];
+ if (i->fail)
+ ret[len] = toupper(ret[len]);
+ ret[++len] = '\0';
+ }
+ return ret;
+}
+
+static void do_warn(int e, const char *fmt, va_list ap)
+{
+ char *p = failpath_string();
+
+ vfprintf(warnf, fmt, ap);
+ if (e != -1)
+ fprintf(warnf, ": %s", strerror(e));
+ fprintf(warnf, " [%s]\n", p);
+ free(p);
+}
+
+static void fwarn(const char *fmt, ...)
+{
+ va_list ap;
+ int e = errno;
+
+ va_start(ap, fmt);
+ do_warn(e, fmt, ap);
+ va_end(ap);
+}
+
+
+static void fwarnx(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ do_warn(-1, fmt, ap);
+ va_end(ap);
+}
+
+static void tell_parent(enum info_type type)
+{
+ if (control_fd != -1)
+ write_all(control_fd, &type, sizeof(type));
+}
+
+static void child_fail(const char *out, size_t outlen, const char *fmt, ...)
+{
+ va_list ap;
+ char *path = failpath_string();
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+
+ fprintf(stderr, "%.*s", (int)outlen, out);
+ printf("To reproduce: --failpath=%s\n", path);
+ free(path);
+ tell_parent(FAILURE);
+ exit(1);
+}
+
+static void PRINTF_FMT(1, 2) trace(const char *fmt, ...)
+{
+ va_list ap;
+ unsigned int i;
+ char *p;
+ static int idx;
+
+ if (!tracef)
+ return;
+
+ for (i = 0; i < traceindent; i++)
+ fprintf(tracef, " ");
+
+ p = failpath_string();
+ fprintf(tracef, "%i: %u: %s ", idx++, getpid(), p);
+ va_start(ap, fmt);
+ vfprintf(tracef, fmt, ap);
+ va_end(ap);
+ free(p);
+}
+
+static pid_t child;
+
+static void hand_down(int signum)
+{
+ kill(child, signum);
+}
+
+static void release_locks(void)
+{
+ /* Locks were never acquired/reacquired? */
+ if (lock_owner == 0)
+ return;
+
+ /* We own them? Release them all. */
+ if (lock_owner == getpid()) {
+ unsigned int i;
+ struct flock fl;
+ fl.l_type = F_UNLCK;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = 0;
+ fl.l_len = 0;
+
+ trace("Releasing %u locks\n", lock_num);
+ for (i = 0; i < lock_num; i++)
+ fcntl(locks[i].fd, F_SETLK, &fl);
+ } else {
+ /* Our parent must have them; pass request up. */
+ enum info_type type = RELEASE_LOCKS;
+ assert(control_fd != -1);
+ write_all(control_fd, &type, sizeof(type));
+ }
+ lock_owner = 0;
+}
+
+/* off_t is a signed type. Getting its max is non-trivial. */
+static off_t off_max(void)
+{
+ BUILD_ASSERT(sizeof(off_t) == 4 || sizeof(off_t) == 8);
+ if (sizeof(off_t) == 4)
+ return (off_t)0x7FFFFFF;
+ else
+ return (off_t)0x7FFFFFFFFFFFFFFULL;
+}
+
+static void get_locks(void)
+{
+ unsigned int i;
+ struct flock fl;
+
+ if (lock_owner == getpid())
+ return;
+
+ if (lock_owner != 0) {
+ enum info_type type = RELEASE_LOCKS;
+ assert(control_fd != -1);
+ trace("Asking parent to release locks\n");
+ write_all(control_fd, &type, sizeof(type));
+ }
+
+ fl.l_whence = SEEK_SET;
+
+ for (i = 0; i < lock_num; i++) {
+ fl.l_type = locks[i].type;
+ fl.l_start = locks[i].start;
+ if (locks[i].end == off_max())
+ fl.l_len = 0;
+ else
+ fl.l_len = locks[i].end - locks[i].start + 1;
+
+ if (fcntl(locks[i].fd, F_SETLKW, &fl) != 0)
+ abort();
+ }
+ trace("Acquired %u locks\n", lock_num);
+ lock_owner = getpid();
+}
+
+
+static struct contents_saved *save_contents(const char *filename,
+ int fd, size_t count, off_t off,
+ const char *why)
+{
+ struct contents_saved *s = malloc(sizeof(*s) + count);
+ ssize_t ret;
+
+ s->off = off;
+
+ ret = pread(fd, s->contents, count, off);
+ if (ret < 0) {
+ fwarn("failtest_write: failed to save old contents!");
+ s->count = 0;
+ } else
+ s->count = ret;
+
+ /* Use lseek to get the size of file, but we have to restore
+ * file offset */
+ off = lseek(fd, 0, SEEK_CUR);
+ s->old_len = lseek(fd, 0, SEEK_END);
+ lseek(fd, off, SEEK_SET);
+
+ trace("Saving %p %s %zu@%llu after %s (filelength %llu) via fd %i\n",
+ s, filename, s->count, (long long)s->off, why,
+ (long long)s->old_len, fd);
+ return s;
+}
+
+static void restore_contents(struct failtest_call *opener,
+ struct contents_saved *s,
+ bool restore_offset,
+ const char *caller)
+{
+ int fd;
+
+ /* The top parent doesn't need to restore. */
+ if (control_fd == -1)
+ return;
+
+ /* Has the fd been closed? */
+ if (opener->u.open.closed) {
+ /* Reopen, replace fd, close silently as we clean up. */
+ fd = open(opener->u.open.pathname, O_RDWR);
+ if (fd < 0) {
+ fwarn("failtest: could not reopen %s to clean up %s!",
+ opener->u.open.pathname, caller);
+ return;
+ }
+ /* Make it clearly distinguisable from a "normal" fd. */
+ fd = move_fd_to_high(fd);
+ trace("Reopening %s to restore it (was fd %i, now %i)\n",
+ opener->u.open.pathname, opener->u.open.ret, fd);
+ opener->u.open.ret = fd;
+ opener->u.open.closed = false;
+ }
+ fd = opener->u.open.ret;
+
+ trace("Restoring %p %s %zu@%llu after %s (filelength %llu) via fd %i\n",
+ s, opener->u.open.pathname, s->count, (long long)s->off, caller,
+ (long long)s->old_len, fd);
+ if (pwrite(fd, s->contents, s->count, s->off) != s->count) {
+ fwarn("failtest: write failed cleaning up %s for %s!",
+ opener->u.open.pathname, caller);
+ }
+
+ if (ftruncate(fd, s->old_len) != 0) {
+ fwarn("failtest_write: truncate failed cleaning up %s for %s!",
+ opener->u.open.pathname, caller);
+ }
+
+ if (restore_offset) {
+ trace("Restoring offset of fd %i to %llu\n",
+ fd, (long long)s->off);
+ lseek(fd, s->off, SEEK_SET);
+ }
+}
+
+/* We save/restore most things on demand, but always do mmaped files. */
+static void save_mmapped_files(void)
+{
+ struct failtest_call *i;
+ trace("Saving mmapped files in child\n");
+
+ tlist_for_each_rev(&history, i, list) {
+ struct mmap_call *m = &i->u.mmap;
+ struct saved_mmapped_file *s;
+
+ if (i->type != FAILTEST_MMAP)
+ continue;
+
+ /* FIXME: We only handle mmapped files where fd is still open. */
+ if (m->opener->u.open.closed)
+ continue;
+
+ s = malloc(sizeof *s);
+ s->s = save_contents(m->opener->u.open.pathname,
+ m->fd, m->length, m->offset,
+ "mmapped file before fork");
+ s->opener = m->opener;
+ s->next = saved_mmapped_files;
+ saved_mmapped_files = s;
+ }
+}
+
+static void free_mmapped_files(bool restore)
+{
+ trace("%s mmapped files in child\n",
+ restore ? "Restoring" : "Discarding");
+ while (saved_mmapped_files) {
+ struct saved_mmapped_file *next = saved_mmapped_files->next;
+ if (restore)
+ restore_contents(saved_mmapped_files->opener,
+ saved_mmapped_files->s, false,
+ "saved mmap");
+ free(saved_mmapped_files->s);
+ free(saved_mmapped_files);
+ saved_mmapped_files = next;
+ }
+}
+
+/* Returns a FAILTEST_OPEN, FAILTEST_PIPE or NULL. */
+static struct failtest_call *opener_of(int fd)
+{
+ struct failtest_call *i;
+
+ /* Don't get confused and match genuinely failed opens. */
+ if (fd < 0)
+ return NULL;
+
+ /* Figure out the set of live fds. */
+ tlist_for_each_rev(&history, i, list) {
+ if (i->fail)
+ continue;
+ switch (i->type) {
+ case FAILTEST_CLOSE:
+ if (i->u.close.fd == fd) {
+ return NULL;
+ }
+ break;
+ case FAILTEST_OPEN:
+ if (i->u.open.ret == fd) {
+ if (i->u.open.closed)
+ return NULL;
+ return i;
+ }
+ break;
+ case FAILTEST_PIPE:
+ if (i->u.pipe.fds[0] == fd || i->u.pipe.fds[1] == fd) {
+ return i;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* FIXME: socket, dup, etc are untracked! */
+ return NULL;
+}
+
+static void free_call(struct failtest_call *call)
+{
+ /* We don't do this in cleanup: needed even for failed opens. */
+ if (call->type == FAILTEST_OPEN)
+ free((char *)call->u.open.pathname);
+ free(call->backtrace);
+ tlist_del_from(&history, call, list);
+ free(call);
+}
+
+/* Free up memory, so valgrind doesn't report leaks. */
+static void free_everything(void)
+{
+ struct failtest_call *i;
+
+ while ((i = tlist_top(&history, list)) != NULL)
+ free_call(i);
+
+ failtable_clear(&failtable);
+}
+
+static NORETURN void failtest_cleanup(bool forced_cleanup, int status)
+{
+ struct failtest_call *i;
+ bool restore = true;
+
+ /* For children, we don't care if they "failed" the testing. */
+ if (control_fd != -1)
+ status = 0;
+ else
+ /* We don't restore contents for original parent. */
+ restore = false;
+
+ /* Cleanup everything, in reverse order. */
+ tlist_for_each_rev(&history, i, list) {
+ /* Don't restore things our parent did. */
+ if (i == our_history_start)
+ restore = false;
+
+ if (i->fail)
+ continue;
+
+ if (i->cleanup)
+ i->cleanup(&i->u, restore);
+
+ /* But their program shouldn't leak, even on failure. */
+ if (!forced_cleanup && i->can_leak) {
+ printf("Leak at %s:%u: --failpath=%s\n",
+ i->file, i->line, failpath_string());
+ status = 1;
+ }
+ }
+
+ /* Put back mmaped files the way our parent (if any) expects. */
+ free_mmapped_files(true);
+
+ free_everything();
+ if (status == 0)
+ tell_parent(SUCCESS);
+ else
+ tell_parent(FAILURE);
+ exit(status);
+}
+
+static bool following_path(void)
+{
+ if (!failpath)
+ return false;
+ /* + means continue after end, like normal. */
+ if (*failpath == '+') {
+ failpath = NULL;
+ return false;
+ }
+ return true;
+}
+
+static bool follow_path(struct failtest_call *call)
+{
+ if (*failpath == '\0') {
+ /* Continue, but don't inject errors. */
+ return call->fail = false;
+ }
+
+ if (tolower((unsigned char)*failpath) != info_to_arg[call->type])
+ errx(1, "Failpath expected '%s' got '%c'\n",
+ failpath, info_to_arg[call->type]);
+ call->fail = cisupper(*(failpath++));
+ if (call->fail)
+ call->can_leak = false;
+ return call->fail;
+}
+
+static bool should_fail(struct failtest_call *call)
+{
+ int status;
+ int control[2], output[2];
+ enum info_type type = UNEXPECTED;
+ char *out = NULL;
+ size_t outlen = 0;
+ struct failtest_call *dup;
+
+ if (call == &unrecorded_call)
+ return false;
+
+ if (following_path())
+ return follow_path(call);
+
+ /* Attach debugger if they asked for it. */
+ if (debugpath) {
+ char *path;
+
+ /* Pretend this last call matches whatever path wanted:
+ * keeps valgrind happy. */
+ call->fail = cisupper(debugpath[strlen(debugpath)-1]);
+ path = failpath_string();
+
+ if (streq(path, debugpath)) {
+ char str[80];
+
+ /* Don't timeout. */
+ signal(SIGUSR1, SIG_IGN);
+ sprintf(str, "xterm -e gdb /proc/%d/exe %d &",
+ getpid(), getpid());
+ if (system(str) == 0)
+ sleep(5);
+ } else {
+ /* Ignore last character: could be upper or lower. */
+ path[strlen(path)-1] = '\0';
+ if (!strstarts(debugpath, path)) {
+ fprintf(stderr,
+ "--debugpath not followed: %s\n", path);
+ debugpath = NULL;
+ }
+ }
+ free(path);
+ }
+
+ /* Are we probing? If so, we never fail twice. */
+ if (probing) {
+ trace("Not failing %c due to FAIL_PROBE return\n",
+ info_to_arg[call->type]);
+ return call->fail = false;
+ }
+
+ /* Don't fail more than once in the same place. */
+ dup = failtable_get(&failtable, call);
+ if (dup) {
+ trace("Not failing %c due to duplicate\n",
+ info_to_arg[call->type]);
+ return call->fail = false;
+ }
+
+ if (failtest_hook) {
+ switch (failtest_hook(&history)) {
+ case FAIL_OK:
+ break;
+ case FAIL_PROBE:
+ probing = true;
+ break;
+ case FAIL_DONT_FAIL:
+ trace("Not failing %c due to failhook return\n",
+ info_to_arg[call->type]);
+ call->fail = false;
+ return false;
+ default:
+ abort();
+ }
+ }
+
+ /* Add it to our table of calls. */
+ failtable_add(&failtable, call);
+
+ /* We're going to fail in the child. */
+ call->fail = true;
+ if (pipe(control) != 0 || pipe(output) != 0)
+ err(1, "opening pipe");
+
+ /* Move out the way, to high fds. */
+ control[0] = move_fd_to_high(control[0]);
+ control[1] = move_fd_to_high(control[1]);
+ output[0] = move_fd_to_high(output[0]);
+ output[1] = move_fd_to_high(output[1]);
+
+ /* Prevent double-printing (in child and parent) */
+ fflush(stdout);
+ fflush(warnf);
+ if (tracef)
+ fflush(tracef);
+ child = fork();
+ if (child == -1)
+ err(1, "forking failed");
+
+ if (child == 0) {
+ traceindent++;
+ if (tracef) {
+ struct timeval diff;
+ const char *p;
+ char *failpath;
+ struct failtest_call *c;
+
+ c = tlist_tail(&history, list);
+ diff = time_sub(time_now(), start);
+ failpath = failpath_string();
+ p = strrchr(c->file, '/');
+ if (p)
+ p++;
+ else
+ p = c->file;
+ trace("%u->%u (%u.%02u): %s (%s:%u)\n",
+ getppid(), getpid(),
+ (int)diff.tv_sec, (int)diff.tv_usec / 10000,
+ failpath, p, c->line);
+ free(failpath);
+ }
+ /* From here on, we have to clean up! */
+ our_history_start = tlist_tail(&history, list);
+ close(control[0]);
+ close(output[0]);
+ /* Don't swallow stderr if we're tracing. */
+ if (!tracef) {
+ dup2(output[1], STDOUT_FILENO);
+ dup2(output[1], STDERR_FILENO);
+ if (output[1] != STDOUT_FILENO
+ && output[1] != STDERR_FILENO)
+ close(output[1]);
+ }
+ control_fd = move_fd_to_high(control[1]);
+
+ /* Forget any of our parent's saved files. */
+ free_mmapped_files(false);
+
+ /* Now, save any files we need to. */
+ save_mmapped_files();
+
+ /* Failed calls can't leak. */
+ call->can_leak = false;
+
+ return true;
+ }
+
+ signal(SIGUSR1, hand_down);
+
+ close(control[1]);
+ close(output[1]);
+
+ /* We grab output so we can display it; we grab writes so we
+ * can compare. */
+ do {
+ struct pollfd pfd[2];
+ int ret;
+
+ pfd[0].fd = output[0];
+ pfd[0].events = POLLIN|POLLHUP;
+ pfd[1].fd = control[0];
+ pfd[1].events = POLLIN|POLLHUP;
+
+ if (type == SUCCESS)
+ ret = poll(pfd, 1, failtest_timeout_ms);
+ else
+ ret = poll(pfd, 2, failtest_timeout_ms);
+
+ if (ret == 0)
+ hand_down(SIGUSR1);
+ if (ret < 0) {
+ if (errno == EINTR)
+ continue;
+ err(1, "Poll returned %i", ret);
+ }
+
+ if (pfd[0].revents & POLLIN) {
+ ssize_t len;
+
+ out = realloc(out, outlen + 8192);
+ len = read(output[0], out + outlen, 8192);
+ outlen += len;
+ } else if (type != SUCCESS && (pfd[1].revents & POLLIN)) {
+ if (read_all(control[0], &type, sizeof(type))) {
+ if (type == WRITE) {
+ if (!read_write_info(control[0]))
+ break;
+ } else if (type == RELEASE_LOCKS) {
+ release_locks();
+ /* FIXME: Tell them we're done... */
+ }
+ }
+ } else if (pfd[0].revents & POLLHUP) {
+ break;
+ }
+ } while (type != FAILURE);
+
+ close(output[0]);
+ close(control[0]);
+ waitpid(child, &status, 0);
+ if (!WIFEXITED(status)) {
+ if (WTERMSIG(status) == SIGUSR1)
+ child_fail(out, outlen, "Timed out");
+ else
+ child_fail(out, outlen, "Killed by signal %u: ",
+ WTERMSIG(status));
+ }
+ /* Child printed failure already, just pass up exit code. */
+ if (type == FAILURE) {
+ fprintf(stderr, "%.*s", (int)outlen, out);
+ tell_parent(type);
+ exit(WEXITSTATUS(status) ? WEXITSTATUS(status) : 1);
+ }
+ if (WEXITSTATUS(status) != 0)
+ child_fail(out, outlen, "Exited with status %i: ",
+ WEXITSTATUS(status));
+
+ free(out);
+ signal(SIGUSR1, SIG_DFL);
+
+ /* Only child does probe. */
+ probing = false;
+
+ /* We continue onwards without failing. */
+ call->fail = false;
+ return false;
+}
+
+static void cleanup_calloc(struct calloc_call *call, bool restore)
+{
+ trace("undoing calloc %p\n", call->ret);
+ free(call->ret);
+}
+
+void *failtest_calloc(size_t nmemb, size_t size,
+ const char *file, unsigned line)
+{
+ struct failtest_call *p;
+ struct calloc_call call;
+ call.nmemb = nmemb;
+ call.size = size;
+ p = add_history(FAILTEST_CALLOC, true, file, line, &call);
+
+ if (should_fail(p)) {
+ p->u.calloc.ret = NULL;
+ p->error = ENOMEM;
+ } else {
+ p->u.calloc.ret = calloc(nmemb, size);
+ set_cleanup(p, cleanup_calloc, struct calloc_call);
+ }
+ trace("calloc %zu x %zu %s:%u -> %p\n",
+ nmemb, size, file, line, p->u.calloc.ret);
+ errno = p->error;
+ return p->u.calloc.ret;
+}
+
+static void cleanup_malloc(struct malloc_call *call, bool restore)
+{
+ trace("undoing malloc %p\n", call->ret);
+ free(call->ret);
+}
+
+void *failtest_malloc(size_t size, const char *file, unsigned line)
+{
+ struct failtest_call *p;
+ struct malloc_call call;
+ call.size = size;
+
+ p = add_history(FAILTEST_MALLOC, true, file, line, &call);
+ if (should_fail(p)) {
+ p->u.malloc.ret = NULL;
+ p->error = ENOMEM;
+ } else {
+ p->u.malloc.ret = malloc(size);
+ set_cleanup(p, cleanup_malloc, struct malloc_call);
+ }
+ trace("malloc %zu %s:%u -> %p\n",
+ size, file, line, p->u.malloc.ret);
+ errno = p->error;
+ return p->u.malloc.ret;
+}
+
+static void cleanup_realloc(struct realloc_call *call, bool restore)
+{
+ trace("undoing realloc %p\n", call->ret);
+ free(call->ret);
+}
+
+/* Walk back and find out if we got this ptr from a previous routine. */
+static void fixup_ptr_history(void *ptr, const char *why)
+{
+ struct failtest_call *i;
+
+ /* Start at end of history, work back. */
+ tlist_for_each_rev(&history, i, list) {
+ switch (i->type) {
+ case FAILTEST_REALLOC:
+ if (i->u.realloc.ret == ptr) {
+ trace("found realloc %p %s:%u matching %s\n",
+ ptr, i->file, i->line, why);
+ i->cleanup = NULL;
+ i->can_leak = false;
+ return;
+ }
+ break;
+ case FAILTEST_MALLOC:
+ if (i->u.malloc.ret == ptr) {
+ trace("found malloc %p %s:%u matching %s\n",
+ ptr, i->file, i->line, why);
+ i->cleanup = NULL;
+ i->can_leak = false;
+ return;
+ }
+ break;
+ case FAILTEST_CALLOC:
+ if (i->u.calloc.ret == ptr) {
+ trace("found calloc %p %s:%u matching %s\n",
+ ptr, i->file, i->line, why);
+ i->cleanup = NULL;
+ i->can_leak = false;
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ trace("Did not find %p matching %s\n", ptr, why);
+}
+
+void *failtest_realloc(void *ptr, size_t size, const char *file, unsigned line)
+{
+ struct failtest_call *p;
+ struct realloc_call call;
+ call.size = size;
+ p = add_history(FAILTEST_REALLOC, true, file, line, &call);
+
+ /* FIXME: Try one child moving allocation, one not. */
+ if (should_fail(p)) {
+ p->u.realloc.ret = NULL;
+ p->error = ENOMEM;
+ } else {
+ /* Don't catch this one in the history fixup... */
+ p->u.realloc.ret = NULL;
+ fixup_ptr_history(ptr, "realloc");
+ p->u.realloc.ret = realloc(ptr, size);
+ set_cleanup(p, cleanup_realloc, struct realloc_call);
+ }
+ trace("realloc %p %s:%u -> %p\n",
+ ptr, file, line, p->u.realloc.ret);
+ errno = p->error;
+ return p->u.realloc.ret;
+}
+
+/* FIXME: Record free, so we can terminate fixup_ptr_history correctly.
+ * If there's an alloc we don't see, it could get confusing if it matches
+ * a previous allocation we did see. */
+void failtest_free(void *ptr)
+{
+ fixup_ptr_history(ptr, "free");
+ trace("free %p\n", ptr);
+ free(ptr);
+}
+
+
+static struct contents_saved *save_file(const char *pathname)
+{
+ int fd;
+ struct contents_saved *s;
+
+ fd = open(pathname, O_RDONLY);
+ if (fd < 0)
+ return NULL;
+
+ s = save_contents(pathname, fd, lseek(fd, 0, SEEK_END), 0,
+ "open with O_TRUNC");
+ close(fd);
+ return s;
+}
+
+/* Optimization: don't create a child for an open which *we know*
+ * would fail anyway. */
+static bool open_would_fail(const char *pathname, int flags)
+{
+ if ((flags & O_ACCMODE) == O_RDONLY)
+ return access(pathname, R_OK) != 0;
+ if (!(flags & O_CREAT)) {
+ if ((flags & O_ACCMODE) == O_WRONLY)
+ return access(pathname, W_OK) != 0;
+ if ((flags & O_ACCMODE) == O_RDWR)
+ return access(pathname, W_OK) != 0
+ || access(pathname, R_OK) != 0;
+ }
+ /* FIXME: We could check if it exists, for O_CREAT|O_EXCL */
+ return false;
+}
+
+static void cleanup_open(struct open_call *call, bool restore)
+{
+ if (restore && call->saved)
+ restore_contents(container_of(call, struct failtest_call,
+ u.open),
+ call->saved, false, "open with O_TRUNC");
+ if (!call->closed) {
+ trace("Cleaning up open %s by closing fd %i\n",
+ call->pathname, call->ret);
+ close(call->ret);
+ call->closed = true;
+ }
+ free(call->saved);
+}
+
+int failtest_open(const char *pathname,
+ const char *file, unsigned line, ...)
+{
+ struct failtest_call *p;
+ struct open_call call;
+ va_list ap;
+
+ call.pathname = strdup(pathname);
+ va_start(ap, line);
+ call.flags = va_arg(ap, int);
+ call.always_save = false;
+ call.closed = false;
+ if (call.flags & O_CREAT) {
+ call.mode = va_arg(ap, int);
+ va_end(ap);
+ }
+ p = add_history(FAILTEST_OPEN, true, file, line, &call);
+ /* Avoid memory leak! */
+ if (p == &unrecorded_call)
+ free((char *)call.pathname);
+
+ if (should_fail(p)) {
+ /* Don't bother inserting failures that would happen anyway. */
+ if (open_would_fail(pathname, call.flags)) {
+ trace("Open would have failed anyway: stopping\n");
+ failtest_cleanup(true, 0);
+ }
+ p->u.open.ret = -1;
+ /* FIXME: Play with error codes? */
+ p->error = EACCES;
+ } else {
+ /* Save the old version if they're truncating it. */
+ if (call.flags & O_TRUNC)
+ p->u.open.saved = save_file(pathname);
+ else
+ p->u.open.saved = NULL;
+ p->u.open.ret = open(pathname, call.flags, call.mode);
+ if (p->u.open.ret == -1) {
+ p->u.open.closed = true;
+ p->can_leak = false;
+ } else {
+ set_cleanup(p, cleanup_open, struct open_call);
+ }
+ }
+ trace("open %s %s:%u -> %i (opener %p)\n",
+ pathname, file, line, p->u.open.ret, &p->u.open);
+ errno = p->error;
+ return p->u.open.ret;
+}
+
+static void cleanup_mmap(struct mmap_call *mmap, bool restore)
+{
+ trace("cleaning up mmap @%p (opener %p)\n",
+ mmap->ret, mmap->opener);
+ if (restore)
+ restore_contents(mmap->opener, mmap->saved, false, "mmap");
+ free(mmap->saved);
+}
+
+void *failtest_mmap(void *addr, size_t length, int prot, int flags,
+ int fd, off_t offset, const char *file, unsigned line)
+{
+ struct failtest_call *p;
+ struct mmap_call call;
+
+ call.addr = addr;
+ call.length = length;
+ call.prot = prot;
+ call.flags = flags;
+ call.offset = offset;
+ call.fd = fd;
+ call.opener = opener_of(fd);
+
+ /* If we don't know what file it was, don't fail. */
+ if (!call.opener) {
+ if (fd != -1) {
+ fwarnx("failtest_mmap: couldn't figure out source for"
+ " fd %i at %s:%u", fd, file, line);
+ }
+ addr = mmap(addr, length, prot, flags, fd, offset);
+ trace("mmap of fd %i -> %p (opener = NULL)\n", fd, addr);
+ return addr;
+ }
+
+ p = add_history(FAILTEST_MMAP, false, file, line, &call);
+ if (should_fail(p)) {
+ p->u.mmap.ret = MAP_FAILED;
+ p->error = ENOMEM;
+ } else {
+ p->u.mmap.ret = mmap(addr, length, prot, flags, fd, offset);
+ /* Save contents if we're writing to a normal file */
+ if (p->u.mmap.ret != MAP_FAILED
+ && (prot & PROT_WRITE)
+ && call.opener->type == FAILTEST_OPEN) {
+ const char *fname = call.opener->u.open.pathname;
+ p->u.mmap.saved = save_contents(fname, fd, length,
+ offset, "being mmapped");
+ set_cleanup(p, cleanup_mmap, struct mmap_call);
+ }
+ }
+ trace("mmap of fd %i %s:%u -> %p (opener = %p)\n",
+ fd, file, line, addr, call.opener);
+ errno = p->error;
+ return p->u.mmap.ret;
+}
+
+static void cleanup_pipe(struct pipe_call *call, bool restore)
+{
+ trace("cleaning up pipe fd=%i%s,%i%s\n",
+ call->fds[0], call->closed[0] ? "(already closed)" : "",
+ call->fds[1], call->closed[1] ? "(already closed)" : "");
+ if (!call->closed[0])
+ close(call->fds[0]);
+ if (!call->closed[1])
+ close(call->fds[1]);
+}
+
+int failtest_pipe(int pipefd[2], const char *file, unsigned line)
+{
+ struct failtest_call *p;
+ struct pipe_call call;
+
+ p = add_history(FAILTEST_PIPE, true, file, line, &call);
+ if (should_fail(p)) {
+ p->u.open.ret = -1;
+ /* FIXME: Play with error codes? */
+ p->error = EMFILE;
+ } else {
+ p->u.pipe.ret = pipe(p->u.pipe.fds);
+ p->u.pipe.closed[0] = p->u.pipe.closed[1] = false;
+ set_cleanup(p, cleanup_pipe, struct pipe_call);
+ }
+
+ trace("pipe %s:%u -> %i,%i\n", file, line,
+ p->u.pipe.ret ? -1 : p->u.pipe.fds[0],
+ p->u.pipe.ret ? -1 : p->u.pipe.fds[1]);
+
+ /* This causes valgrind to notice if they use pipefd[] after failure */
+ memcpy(pipefd, p->u.pipe.fds, sizeof(p->u.pipe.fds));
+ errno = p->error;
+ return p->u.pipe.ret;
+}
+
+static void cleanup_read(struct read_call *call, bool restore)
+{
+ if (restore) {
+ trace("cleaning up read on fd %i: seeking to %llu\n",
+ call->fd, (long long)call->off);
+
+ /* Read (not readv!) moves file offset! */
+ if (lseek(call->fd, call->off, SEEK_SET) != call->off) {
+ fwarn("Restoring lseek pointer failed (read)");
+ }
+ }
+}
+
+static ssize_t failtest_add_read(int fd, void *buf, size_t count, off_t off,
+ bool is_pread, const char *file, unsigned line)
+{
+ struct failtest_call *p;
+ struct read_call call;
+ call.fd = fd;
+ call.buf = buf;
+ call.count = count;
+ call.off = off;
+ p = add_history(FAILTEST_READ, false, file, line, &call);
+
+ /* FIXME: Try partial read returns. */
+ if (should_fail(p)) {
+ p->u.read.ret = -1;
+ p->error = EIO;
+ } else {
+ if (is_pread)
+ p->u.read.ret = pread(fd, buf, count, off);
+ else {
+ p->u.read.ret = read(fd, buf, count);
+ if (p->u.read.ret != -1)
+ set_cleanup(p, cleanup_read, struct read_call);
+ }
+ }
+ trace("%sread %s:%u fd %i %zu@%llu -> %i\n",
+ is_pread ? "p" : "", file, line, fd, count, (long long)off,
+ p->u.read.ret);
+ errno = p->error;
+ return p->u.read.ret;
+}
+
+static void cleanup_write(struct write_call *write, bool restore)
+{
+ trace("cleaning up write on %s\n", write->opener->u.open.pathname);
+ if (restore)
+ restore_contents(write->opener, write->saved, !write->is_pwrite,
+ "write");
+ free(write->saved);
+}
+
+static ssize_t failtest_add_write(int fd, const void *buf,
+ size_t count, off_t off,
+ bool is_pwrite,
+ const char *file, unsigned line)
+{
+ struct failtest_call *p;
+ struct write_call call;
+
+ call.fd = fd;
+ call.buf = buf;
+ call.count = count;
+ call.off = off;
+ call.is_pwrite = is_pwrite;
+ call.opener = opener_of(fd);
+ p = add_history(FAILTEST_WRITE, false, file, line, &call);
+
+ /* If we're a child, we need to make sure we write the same thing
+ * to non-files as the parent does, so tell it. */
+ if (control_fd != -1 && off == (off_t)-1) {
+ enum info_type type = WRITE;
+
+ write_all(control_fd, &type, sizeof(type));
+ write_all(control_fd, &p->u.write, sizeof(p->u.write));
+ write_all(control_fd, buf, count);
+ }
+
+ /* FIXME: Try partial write returns. */
+ if (should_fail(p)) {
+ p->u.write.ret = -1;
+ p->error = EIO;
+ } else {
+ bool is_file;
+ assert(call.opener == p->u.write.opener);
+
+ if (p->u.write.opener) {
+ is_file = (p->u.write.opener->type == FAILTEST_OPEN);
+ } else {
+ /* We can't unwind it, so at least check same
+ * in parent and child. */
+ is_file = false;
+ }
+
+ /* FIXME: We assume same write order in parent and child */
+ if (!is_file && child_writes_num != 0) {
+ if (child_writes[0].fd != fd)
+ errx(1, "Child wrote to fd %u, not %u?",
+ child_writes[0].fd, fd);
+ if (child_writes[0].off != p->u.write.off)
+ errx(1, "Child wrote to offset %zu, not %zu?",
+ (size_t)child_writes[0].off,
+ (size_t)p->u.write.off);
+ if (child_writes[0].count != count)
+ errx(1, "Child wrote length %zu, not %zu?",
+ child_writes[0].count, count);
+ if (memcmp(child_writes[0].buf, buf, count)) {
+ child_fail(NULL, 0,
+ "Child wrote differently to"
+ " fd %u than we did!\n", fd);
+ }
+ free((char *)child_writes[0].buf);
+ child_writes_num--;
+ memmove(&child_writes[0], &child_writes[1],
+ sizeof(child_writes[0]) * child_writes_num);
+
+ /* Child wrote it already. */
+ trace("write %s:%i on fd %i already done by child\n",
+ file, line, fd);
+ p->u.write.ret = count;
+ errno = p->error;
+ return p->u.write.ret;
+ }
+
+ if (is_file) {
+ p->u.write.saved = save_contents(call.opener->u.open.pathname,
+ fd, count, off,
+ "being overwritten");
+ set_cleanup(p, cleanup_write, struct write_call);
+ }
+
+ /* Though off is current seek ptr for write case, we need to
+ * move it. write() does that for us. */
+ if (p->u.write.is_pwrite)
+ p->u.write.ret = pwrite(fd, buf, count, off);
+ else
+ p->u.write.ret = write(fd, buf, count);
+ }
+ trace("%swrite %s:%i %zu@%llu on fd %i -> %i\n",
+ p->u.write.is_pwrite ? "p" : "",
+ file, line, count, (long long)off, fd, p->u.write.ret);
+ errno = p->error;
+ return p->u.write.ret;
+}
+
+ssize_t failtest_pwrite(int fd, const void *buf, size_t count, off_t offset,
+ const char *file, unsigned line)
+{
+ return failtest_add_write(fd, buf, count, offset, true, file, line);
+}
+
+ssize_t failtest_write(int fd, const void *buf, size_t count,
+ const char *file, unsigned line)
+{
+ return failtest_add_write(fd, buf, count, lseek(fd, 0, SEEK_CUR), false,
+ file, line);
+}
+
+ssize_t failtest_pread(int fd, void *buf, size_t count, off_t off,
+ const char *file, unsigned line)
+{
+ return failtest_add_read(fd, buf, count, off, true, file, line);
+}
+
+ssize_t failtest_read(int fd, void *buf, size_t count,
+ const char *file, unsigned line)
+{
+ return failtest_add_read(fd, buf, count, lseek(fd, 0, SEEK_CUR), false,
+ file, line);
+}
+
+static struct lock_info *WARN_UNUSED_RESULT
+add_lock(struct lock_info *locks, int fd, off_t start, off_t end, int type)
+{
+ unsigned int i;
+ struct lock_info *l;
+
+ for (i = 0; i < lock_num; i++) {
+ l = &locks[i];
+
+ if (l->fd != fd)
+ continue;
+ /* Four cases we care about:
+ * Start overlap:
+ * l = | |
+ * new = | |
+ * Mid overlap:
+ * l = | |
+ * new = | |
+ * End overlap:
+ * l = | |
+ * new = | |
+ * Total overlap:
+ * l = | |
+ * new = | |
+ */
+ if (start > l->start && end < l->end) {
+ /* Mid overlap: trim entry, add new one. */
+ off_t new_start, new_end;
+ new_start = end + 1;
+ new_end = l->end;
+ trace("splitting lock on fd %i from %llu-%llu"
+ " to %llu-%llu\n",
+ fd, (long long)l->start, (long long)l->end,
+ (long long)l->start, (long long)start - 1);
+ l->end = start - 1;
+ locks = add_lock(locks,
+ fd, new_start, new_end, l->type);
+ l = &locks[i];
+ } else if (start <= l->start && end >= l->end) {
+ /* Total overlap: eliminate entry. */
+ trace("erasing lock on fd %i %llu-%llu\n",
+ fd, (long long)l->start, (long long)l->end);
+ l->end = 0;
+ l->start = 1;
+ } else if (end >= l->start && end < l->end) {
+ trace("trimming lock on fd %i from %llu-%llu"
+ " to %llu-%llu\n",
+ fd, (long long)l->start, (long long)l->end,
+ (long long)end + 1, (long long)l->end);
+ /* Start overlap: trim entry. */
+ l->start = end + 1;
+ } else if (start > l->start && start <= l->end) {
+ trace("trimming lock on fd %i from %llu-%llu"
+ " to %llu-%llu\n",
+ fd, (long long)l->start, (long long)l->end,
+ (long long)l->start, (long long)start - 1);
+ /* End overlap: trim entry. */
+ l->end = start-1;
+ }
+ /* Nothing left? Remove it. */
+ if (l->end < l->start) {
+ trace("forgetting lock on fd %i\n", fd);
+ memmove(l, l + 1, (--lock_num - i) * sizeof(l[0]));
+ i--;
+ }
+ }
+
+ if (type != F_UNLCK) {
+ locks = realloc(locks, (lock_num + 1) * sizeof(*locks));
+ l = &locks[lock_num++];
+ l->fd = fd;
+ l->start = start;
+ l->end = end;
+ l->type = type;
+ trace("new lock on fd %i %llu-%llu\n",
+ fd, (long long)l->start, (long long)l->end);
+ }
+ return locks;
+}
+
+/* We trap this so we can record it: we don't fail it. */
+int failtest_close(int fd, const char *file, unsigned line)
+{
+ struct close_call call;
+ struct failtest_call *p, *opener;
+
+ /* Do this before we add ourselves to history! */
+ opener = opener_of(fd);
+
+ call.fd = fd;
+ p = add_history(FAILTEST_CLOSE, false, file, line, &call);
+ p->fail = false;
+
+ /* Consume close from failpath (shouldn't tell us to fail). */
+ if (following_path()) {
+ if (follow_path(p))
+ abort();
+ }
+
+ trace("close on fd %i\n", fd);
+ if (fd < 0)
+ return close(fd);
+
+ /* Mark opener as not leaking, remove its cleanup function. */
+ if (opener) {
+ trace("close on fd %i found opener %p\n", fd, opener);
+ if (opener->type == FAILTEST_PIPE) {
+ /* From a pipe? */
+ if (opener->u.pipe.fds[0] == fd) {
+ assert(!opener->u.pipe.closed[0]);
+ opener->u.pipe.closed[0] = true;
+ } else if (opener->u.pipe.fds[1] == fd) {
+ assert(!opener->u.pipe.closed[1]);
+ opener->u.pipe.closed[1] = true;
+ } else
+ abort();
+ opener->can_leak = (!opener->u.pipe.closed[0]
+ || !opener->u.pipe.closed[1]);
+ } else if (opener->type == FAILTEST_OPEN) {
+ opener->u.open.closed = true;
+ opener->can_leak = false;
+ } else
+ abort();
+ }
+
+ /* Restore offset now, in case parent shared (can't do after close!). */
+ if (control_fd != -1) {
+ struct failtest_call *i;
+
+ tlist_for_each_rev(&history, i, list) {
+ if (i == our_history_start)
+ break;
+ if (i == opener)
+ break;
+ if (i->type == FAILTEST_LSEEK && i->u.lseek.fd == fd) {
+ trace("close on fd %i undoes lseek\n", fd);
+ /* This seeks back. */
+ i->cleanup(&i->u, true);
+ i->cleanup = NULL;
+ } else if (i->type == FAILTEST_WRITE
+ && i->u.write.fd == fd
+ && !i->u.write.is_pwrite) {
+ trace("close on fd %i undoes write"
+ " offset change\n", fd);
+ /* Write (not pwrite!) moves file offset! */
+ if (lseek(fd, i->u.write.off, SEEK_SET)
+ != i->u.write.off) {
+ fwarn("Restoring lseek pointer failed (write)");
+ }
+ } else if (i->type == FAILTEST_READ
+ && i->u.read.fd == fd) {
+ /* preads don't *have* cleanups */
+ if (i->cleanup) {
+ trace("close on fd %i undoes read"
+ " offset change\n", fd);
+ /* This seeks back. */
+ i->cleanup(&i->u, true);
+ i->cleanup = NULL;
+ }
+ }
+ }
+ }
+
+ /* Close unlocks everything. */
+ locks = add_lock(locks, fd, 0, off_max(), F_UNLCK);
+ return close(fd);
+}
+
+/* Zero length means "to end of file" */
+static off_t end_of(off_t start, off_t len)
+{
+ if (len == 0)
+ return off_max();
+ return start + len - 1;
+}
+
+/* FIXME: This only handles locks, really. */
+int failtest_fcntl(int fd, const char *file, unsigned line, int cmd, ...)
+{
+ struct failtest_call *p;
+ struct fcntl_call call;
+ va_list ap;
+
+ call.fd = fd;
+ call.cmd = cmd;
+
+ /* Argument extraction. */
+ switch (cmd) {
+ case F_SETFL:
+ case F_SETFD:
+ va_start(ap, cmd);
+ call.arg.l = va_arg(ap, long);
+ va_end(ap);
+ trace("fcntl on fd %i F_SETFL/F_SETFD\n", fd);
+ return fcntl(fd, cmd, call.arg.l);
+ case F_GETFD:
+ case F_GETFL:
+ trace("fcntl on fd %i F_GETFL/F_GETFD\n", fd);
+ return fcntl(fd, cmd);
+ case F_GETLK:
+ trace("fcntl on fd %i F_GETLK\n", fd);
+ get_locks();
+ va_start(ap, cmd);
+ call.arg.fl = *va_arg(ap, struct flock *);
+ va_end(ap);
+ return fcntl(fd, cmd, &call.arg.fl);
+ case F_SETLK:
+ case F_SETLKW:
+ trace("fcntl on fd %i F_SETLK%s\n",
+ fd, cmd == F_SETLKW ? "W" : "");
+ va_start(ap, cmd);
+ call.arg.fl = *va_arg(ap, struct flock *);
+ va_end(ap);
+ break;
+ default:
+ /* This means you need to implement it here. */
+ err(1, "failtest: unknown fcntl %u", cmd);
+ }
+
+ p = add_history(FAILTEST_FCNTL, false, file, line, &call);
+
+ if (should_fail(p)) {
+ p->u.fcntl.ret = -1;
+ if (p->u.fcntl.cmd == F_SETLK)
+ p->error = EAGAIN;
+ else
+ p->error = EDEADLK;
+ } else {
+ get_locks();
+ p->u.fcntl.ret = fcntl(p->u.fcntl.fd, p->u.fcntl.cmd,
+ &p->u.fcntl.arg.fl);
+ if (p->u.fcntl.ret == -1)
+ p->error = errno;
+ else {
+ /* We don't handle anything else yet. */
+ assert(p->u.fcntl.arg.fl.l_whence == SEEK_SET);
+ locks = add_lock(locks,
+ p->u.fcntl.fd,
+ p->u.fcntl.arg.fl.l_start,
+ end_of(p->u.fcntl.arg.fl.l_start,
+ p->u.fcntl.arg.fl.l_len),
+ p->u.fcntl.arg.fl.l_type);
+ }
+ }
+ trace("fcntl on fd %i -> %i\n", fd, p->u.fcntl.ret);
+ errno = p->error;
+ return p->u.fcntl.ret;
+}
+
+static void cleanup_lseek(struct lseek_call *call, bool restore)
+{
+ if (restore) {
+ trace("cleaning up lseek on fd %i -> %llu\n",
+ call->fd, (long long)call->old_off);
+ if (lseek(call->fd, call->old_off, SEEK_SET) != call->old_off)
+ fwarn("Restoring lseek pointer failed");
+ }
+}
+
+/* We trap this so we can undo it: we don't fail it. */
+off_t failtest_lseek(int fd, off_t offset, int whence, const char *file,
+ unsigned int line)
+{
+ struct failtest_call *p;
+ struct lseek_call call;
+ call.fd = fd;
+ call.offset = offset;
+ call.whence = whence;
+ call.old_off = lseek(fd, 0, SEEK_CUR);
+
+ p = add_history(FAILTEST_LSEEK, false, file, line, &call);
+ p->fail = false;
+
+ /* Consume lseek from failpath. */
+ if (failpath)
+ if (should_fail(p))
+ abort();
+
+ p->u.lseek.ret = lseek(fd, offset, whence);
+
+ if (p->u.lseek.ret != (off_t)-1)
+ set_cleanup(p, cleanup_lseek, struct lseek_call);
+
+ trace("lseek %s:%u on fd %i from %llu to %llu%s\n",
+ file, line, fd, (long long)call.old_off, (long long)offset,
+ whence == SEEK_CUR ? " (from current off)" :
+ whence == SEEK_END ? " (from end)" :
+ whence == SEEK_SET ? "" : " (invalid whence)");
+ return p->u.lseek.ret;
+}
+
+
+pid_t failtest_getpid(const char *file, unsigned line)
+{
+ /* You must call failtest_init first! */
+ assert(orig_pid);
+ return orig_pid;
+}
+
+void failtest_init(int argc, char *argv[])
+{
+ unsigned int i;
+
+ orig_pid = getpid();
+
+ warnf = fdopen(move_fd_to_high(dup(STDERR_FILENO)), "w");
+ for (i = 1; i < argc; i++) {
+ if (!strncmp(argv[i], "--failpath=", strlen("--failpath="))) {
+ failpath = argv[i] + strlen("--failpath=");
+ } else if (strcmp(argv[i], "--trace") == 0) {
+ tracef = warnf;
+ failtest_timeout_ms = -1;
+ } else if (!strncmp(argv[i], "--debugpath=",
+ strlen("--debugpath="))) {
+ debugpath = argv[i] + strlen("--debugpath=");
+ }
+ }
+ failtable_init(&failtable);
+ start = time_now();
+}
+
+bool failtest_has_failed(void)
+{
+ return control_fd != -1;
+}
+
+void failtest_exit(int status)
+{
+ trace("failtest_exit with status %i\n", status);
+ if (failtest_exit_check) {
+ if (!failtest_exit_check(&history))
+ child_fail(NULL, 0, "failtest_exit_check failed\n");
+ }
+
+ failtest_cleanup(false, status);
+}
diff --git a/lib/ccan/failtest/failtest.d b/lib/ccan/failtest/failtest.d
new file mode 100644
index 0000000000..6aa295d6f8
--- /dev/null
+++ b/lib/ccan/failtest/failtest.d
@@ -0,0 +1,70 @@
+ccan/failtest/failtest.o: ccan/failtest/failtest.c \
+ ccan/failtest/failtest.h config.h \
+ /usr/include/i386-linux-gnu/sys/types.h /usr/include/features.h \
+ /usr/include/i386-linux-gnu/bits/predefs.h \
+ /usr/include/i386-linux-gnu/sys/cdefs.h \
+ /usr/include/i386-linux-gnu/bits/wordsize.h \
+ /usr/include/i386-linux-gnu/gnu/stubs.h \
+ /usr/include/i386-linux-gnu/gnu/stubs-32.h \
+ /usr/include/i386-linux-gnu/bits/types.h \
+ /usr/include/i386-linux-gnu/bits/typesizes.h /usr/include/time.h \
+ /usr/lib/gcc/i686-linux-gnu/4.5.4/include/stddef.h /usr/include/endian.h \
+ /usr/include/i386-linux-gnu/bits/endian.h \
+ /usr/include/i386-linux-gnu/bits/byteswap.h \
+ /usr/include/i386-linux-gnu/sys/select.h \
+ /usr/include/i386-linux-gnu/bits/select.h \
+ /usr/include/i386-linux-gnu/bits/sigset.h \
+ /usr/include/i386-linux-gnu/bits/time.h \
+ /usr/include/i386-linux-gnu/sys/sysmacros.h \
+ /usr/include/i386-linux-gnu/bits/pthreadtypes.h \
+ /usr/lib/gcc/i686-linux-gnu/4.5.4/include/stdbool.h /usr/include/fcntl.h \
+ /usr/include/i386-linux-gnu/bits/fcntl.h \
+ /usr/include/i386-linux-gnu/bits/uio.h \
+ /usr/include/i386-linux-gnu/bits/stat.h ccan/compiler/compiler.h \
+ ccan/tlist/tlist.h ccan/list/list.h /usr/include/assert.h \
+ ccan/container_of/container_of.h ccan/check_type/check_type.h \
+ ccan/tcon/tcon.h /usr/lib/gcc/i686-linux-gnu/4.5.4/include/stdarg.h \
+ /usr/include/string.h /usr/include/xlocale.h /usr/include/stdio.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/include/i386-linux-gnu/bits/stdio_lim.h \
+ /usr/include/i386-linux-gnu/bits/sys_errlist.h /usr/include/ctype.h \
+ /usr/include/err.h /usr/include/unistd.h \
+ /usr/include/i386-linux-gnu/bits/posix_opt.h \
+ /usr/include/i386-linux-gnu/bits/environments.h \
+ /usr/include/i386-linux-gnu/bits/confname.h /usr/include/getopt.h \
+ /usr/include/poll.h /usr/include/i386-linux-gnu/sys/poll.h \
+ /usr/include/i386-linux-gnu/bits/poll.h /usr/include/errno.h \
+ /usr/include/i386-linux-gnu/bits/errno.h /usr/include/linux/errno.h \
+ /usr/include/i386-linux-gnu/asm/errno.h /usr/include/asm-generic/errno.h \
+ /usr/include/asm-generic/errno-base.h \
+ /usr/include/i386-linux-gnu/sys/wait.h /usr/include/signal.h \
+ /usr/include/i386-linux-gnu/bits/signum.h \
+ /usr/include/i386-linux-gnu/bits/siginfo.h \
+ /usr/include/i386-linux-gnu/bits/sigaction.h \
+ /usr/include/i386-linux-gnu/bits/sigcontext.h \
+ /usr/include/i386-linux-gnu/asm/sigcontext.h /usr/include/linux/types.h \
+ /usr/include/i386-linux-gnu/asm/types.h /usr/include/asm-generic/types.h \
+ /usr/include/asm-generic/int-ll64.h \
+ /usr/include/i386-linux-gnu/asm/bitsperlong.h \
+ /usr/include/asm-generic/bitsperlong.h /usr/include/linux/posix_types.h \
+ /usr/include/linux/stddef.h \
+ /usr/include/i386-linux-gnu/asm/posix_types.h \
+ /usr/include/i386-linux-gnu/asm/posix_types_32.h \
+ /usr/include/i386-linux-gnu/bits/sigstack.h \
+ /usr/include/i386-linux-gnu/sys/ucontext.h \
+ /usr/include/i386-linux-gnu/bits/sigthread.h \
+ /usr/include/i386-linux-gnu/sys/resource.h \
+ /usr/include/i386-linux-gnu/bits/resource.h \
+ /usr/include/i386-linux-gnu/bits/waitflags.h \
+ /usr/include/i386-linux-gnu/bits/waitstatus.h \
+ /usr/include/i386-linux-gnu/sys/stat.h \
+ /usr/include/i386-linux-gnu/sys/time.h \
+ /usr/include/i386-linux-gnu/sys/mman.h \
+ /usr/include/i386-linux-gnu/bits/mman.h ccan/time/time.h \
+ /usr/lib/gcc/i686-linux-gnu/4.5.4/include/stdint.h /usr/include/stdint.h \
+ /usr/include/i386-linux-gnu/bits/wchar.h \
+ ccan/read_write_all/read_write_all.h ccan/failtest/failtest_proto.h \
+ /usr/include/stdlib.h /usr/include/alloca.h \
+ ccan/build_assert/build_assert.h ccan/hash/hash.h \
+ ccan/htable/htable_type.h ccan/htable/htable.h ccan/str/str.h \
+ ccan/str/str_debug.h /usr/include/execinfo.h
diff --git a/lib/ccan/failtest/failtest.h b/lib/ccan/failtest/failtest.h
new file mode 100644
index 0000000000..9af5669678
--- /dev/null
+++ b/lib/ccan/failtest/failtest.h
@@ -0,0 +1,258 @@
+/* Licensed under LGPL - see LICENSE file for details */
+#ifndef CCAN_FAILTEST_H
+#define CCAN_FAILTEST_H
+#include "config.h"
+#if HAVE_FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 64
+#endif
+#include <sys/types.h>
+#include <stdbool.h>
+#include <fcntl.h>
+#include <ccan/compiler/compiler.h>
+#include <ccan/tlist/tlist.h>
+
+/**
+ * failtest_init - initialize the failtest module
+ * @argc: the number of commandline arguments
+ * @argv: the commandline argument array
+ *
+ * This initializes the module, and in particular if argv[1] is "--failpath="
+ * then it ensures that failures follow that pattern. This allows easy
+ * debugging of complex failure paths.
+ */
+void failtest_init(int argc, char *argv[]);
+
+/**
+ * failtest_exit - clean up and exit the test
+ * @status: the status (usually exit_status() from ccan/tap).
+ *
+ * This cleans up and changes to files made in this child, and exits the test.
+ * It also calls your failtest_default_hook, if any.
+ *
+ * A child which does not exit via failtest_exit() will cause the overall test
+ * to fail.
+ */
+void NORETURN failtest_exit(int status);
+
+/**
+ * enum failtest_call_type - discriminator for failtest_call.u
+ */
+enum failtest_call_type {
+ FAILTEST_MALLOC,
+ FAILTEST_CALLOC,
+ FAILTEST_REALLOC,
+ FAILTEST_OPEN,
+ FAILTEST_CLOSE,
+ FAILTEST_PIPE,
+ FAILTEST_READ,
+ FAILTEST_WRITE,
+ FAILTEST_FCNTL,
+ FAILTEST_MMAP,
+ FAILTEST_LSEEK
+};
+
+struct calloc_call {
+ void *ret;
+ size_t nmemb;
+ size_t size;
+};
+
+struct malloc_call {
+ void *ret;
+ size_t size;
+};
+
+struct realloc_call {
+ void *ret;
+ void *ptr;
+ size_t size;
+};
+
+struct open_call {
+ int ret;
+ const char *pathname;
+ int flags;
+ mode_t mode;
+ bool always_save;
+ bool closed;
+ /* This is used for O_TRUNC opens on existing files. */
+ struct contents_saved *saved;
+};
+
+struct close_call {
+ int fd;
+};
+
+struct pipe_call {
+ int ret;
+ int fds[2];
+ bool closed[2];
+};
+
+struct read_call {
+ ssize_t ret;
+ off_t off;
+ int fd;
+ void *buf;
+ size_t count;
+};
+
+struct write_call {
+ ssize_t ret;
+ int fd;
+ const void *buf;
+ size_t count;
+ off_t off;
+ bool is_pwrite;
+ struct failtest_call *opener;
+ struct contents_saved *saved;
+};
+
+struct fcntl_call {
+ int ret;
+ int fd;
+ int cmd;
+ union {
+ struct flock fl;
+ long l;
+ int i;
+ } arg;
+};
+
+struct mmap_call {
+ void *ret;
+ void *addr;
+ size_t length;
+ int prot;
+ int flags;
+ int fd;
+ off_t offset;
+ struct failtest_call *opener;
+ struct contents_saved *saved;
+};
+
+struct lseek_call {
+ ssize_t ret;
+ int fd;
+ off_t offset;
+ int whence;
+ off_t old_off;
+};
+
+/**
+ * struct failtest_call - description of a call redirected to failtest module
+ * @type: the call type
+ * @file: the filename of the caller
+ * @line: the line number of the caller
+ * @fail: did this call fail
+ * @error: the errno (if any)
+ * @u: the union of call data
+ *
+ * This structure is used to represent the ordered history of calls.
+ *
+ * See Also:
+ * failtest_hook, failtest_exit_check
+ */
+struct failtest_call {
+ /* We're in the history list. */
+ struct list_node list;
+ enum failtest_call_type type;
+ /* Where we were called from. */
+ const char *file;
+ unsigned int line;
+ /* Did we fail? */
+ bool fail;
+ /* What we set errno to. */
+ int error;
+ /* How do we clean this up? */
+ void (*cleanup)(void *u, bool restore);
+ /* Should their program have cleaned up? */
+ bool can_leak;
+ /* Backtrace of call chain. */
+ void **backtrace;
+ unsigned int backtrace_num;
+ /* The actual call data. */
+ union {
+ struct calloc_call calloc;
+ struct malloc_call malloc;
+ struct realloc_call realloc;
+ struct open_call open;
+ struct close_call close;
+ struct pipe_call pipe;
+ struct read_call read;
+ struct write_call write;
+ struct fcntl_call fcntl;
+ struct mmap_call mmap;
+ struct lseek_call lseek;
+ } u;
+};
+
+/* This defines struct tlist_calls. */
+TLIST_TYPE(calls, struct failtest_call);
+
+enum failtest_result {
+ /* Yes try failing this call. */
+ FAIL_OK,
+ /* No, don't try failing this call. */
+ FAIL_DONT_FAIL,
+ /* Try failing this call but don't go too far down that path. */
+ FAIL_PROBE,
+};
+
+/**
+ * failtest_hook - whether a certain call should fail or not.
+ * @history: the ordered history of all failtest calls.
+ *
+ * The default value of this hook is failtest_default_hook(), which returns
+ * FAIL_OK (ie. yes, fail the call).
+ *
+ * You can override it, and avoid failing certain calls. The parameters
+ * of the call (but not the return value(s)) will be filled in for the last
+ * call.
+ *
+ * Example:
+ * static enum failtest_result dont_fail_alloc(struct tlist_calls *history)
+ * {
+ * struct failtest_call *call;
+ * call = tlist_tail(history, list);
+ * if (call->type == FAILTEST_MALLOC
+ * || call->type == FAILTEST_CALLOC
+ * || call->type == FAILTEST_REALLOC)
+ * return FAIL_DONT_FAIL;
+ * return FAIL_OK;
+ * }
+ * ...
+ * failtest_hook = dont_fail_alloc;
+ */
+extern enum failtest_result (*failtest_hook)(struct tlist_calls *history);
+
+/**
+ * failtest_exit_check - hook for additional checks on a failed child.
+ * @history: the ordered history of all failtest calls.
+ *
+ * Your program might have additional checks to do on failure, such as
+ * check that a file is not corrupted, or than an error message has been
+ * logged.
+ *
+ * If this returns false, the path to this failure will be printed and the
+ * overall test will fail.
+ */
+extern bool (*failtest_exit_check)(struct tlist_calls *history);
+
+/**
+ * failtest_has_failed - determine if a failure has occurred.
+ *
+ * Sometimes you want to exit immediately if you've experienced an
+ * injected failure. This is useful when you have four separate tests
+ * in your test suite, and you don't want to do the next one if you've
+ * had a failure in a previous one.
+ */
+extern bool failtest_has_failed(void);
+
+/**
+ * failtest_timeout_ms - how long to wait before killing child.
+ *
+ * Default is 20,000 (20 seconds).
+ */
+extern unsigned int failtest_timeout_ms;
+#endif /* CCAN_FAILTEST_H */
diff --git a/lib/ccan/failtest/failtest_override.h b/lib/ccan/failtest/failtest_override.h
new file mode 100644
index 0000000000..204494b086
--- /dev/null
+++ b/lib/ccan/failtest/failtest_override.h
@@ -0,0 +1,81 @@
+/* Licensed under LGPL - see LICENSE file for details */
+#ifndef CCAN_FAILTEST_OVERRIDE_H
+#define CCAN_FAILTEST_OVERRIDE_H
+/* This file is included before the source file to test. */
+#include "config.h"
+#if HAVE_FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 64
+#endif
+
+/* Replacement of allocators. */
+#include <stdlib.h>
+
+#undef calloc
+#define calloc(nmemb, size) \
+ failtest_calloc((nmemb), (size), __FILE__, __LINE__)
+
+#undef malloc
+#define malloc(size) \
+ failtest_malloc((size), __FILE__, __LINE__)
+
+#undef realloc
+#define realloc(ptr, size) \
+ failtest_realloc((ptr), (size), __FILE__, __LINE__)
+
+#undef free
+#define free(ptr) \
+ failtest_free(ptr)
+
+/* Replacement of I/O. */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#undef open
+#define open(pathname, ...) \
+ failtest_open((pathname), __FILE__, __LINE__, __VA_ARGS__)
+
+#undef pipe
+#define pipe(pipefd) \
+ failtest_pipe((pipefd), __FILE__, __LINE__)
+
+#undef read
+#define read(fd, buf, count) \
+ failtest_read((fd), (buf), (count), __FILE__, __LINE__)
+
+#undef write
+#define write(fd, buf, count) \
+ failtest_write((fd), (buf), (count), __FILE__, __LINE__)
+
+#undef pread
+#define pread(fd, buf, count, off) \
+ failtest_pread((fd), (buf), (count), (off), __FILE__, __LINE__)
+
+#undef pwrite
+#define pwrite(fd, buf, count, off) \
+ failtest_pwrite((fd), (buf), (count), (off), __FILE__, __LINE__)
+
+#undef close
+#define close(fd) failtest_close(fd, __FILE__, __LINE__)
+
+#undef fcntl
+#define fcntl(fd, ...) failtest_fcntl((fd), __FILE__, __LINE__, __VA_ARGS__)
+
+#undef mmap
+#define mmap(addr, length, prot, flags, fd, offset) \
+ failtest_mmap((addr), (length), (prot), (flags), (fd), (offset), \
+ __FILE__, __LINE__)
+
+#undef lseek
+#define lseek(fd, offset, whence) \
+ failtest_lseek((fd), (offset), (whence), __FILE__, __LINE__)
+
+/* Replacement of getpid (since failtest will fork). */
+#undef getpid
+#define getpid() failtest_getpid(__FILE__, __LINE__)
+
+#include <ccan/failtest/failtest_proto.h>
+
+#endif /* CCAN_FAILTEST_OVERRIDE_H */
diff --git a/lib/ccan/failtest/failtest_proto.h b/lib/ccan/failtest/failtest_proto.h
new file mode 100644
index 0000000000..c7e6b48984
--- /dev/null
+++ b/lib/ccan/failtest/failtest_proto.h
@@ -0,0 +1,31 @@
+/* Licensed under LGPL - see LICENSE file for details */
+#ifndef CCAN_FAILTEST_PROTO_H
+#define CCAN_FAILTEST_PROTO_H
+#include <stdlib.h>
+
+/* Potentially-failing versions of routines; #defined in failtest.h */
+void *failtest_calloc(size_t nmemb, size_t size,
+ const char *file, unsigned line);
+void *failtest_malloc(size_t size, const char *file, unsigned line);
+void *failtest_realloc(void *ptr, size_t size,
+ const char *file, unsigned line);
+void failtest_free(void *ptr);
+int failtest_open(const char *pathname,
+ const char *file, unsigned line, ...);
+int failtest_pipe(int pipefd[2], const char *file, unsigned line);
+ssize_t failtest_read(int fd, void *buf, size_t count,
+ const char *file, unsigned line);
+ssize_t failtest_write(int fd, const void *buf, size_t count,
+ const char *file, unsigned line);
+ssize_t failtest_pread(int fd, void *buf, size_t count, off_t offset,
+ const char *file, unsigned line);
+ssize_t failtest_pwrite(int fd, const void *buf, size_t count, off_t offset,
+ const char *file, unsigned line);
+void *failtest_mmap(void *addr, size_t length, int prot, int flags,
+ int fd, off_t offset, const char *file, unsigned line);
+off_t failtest_lseek(int fd, off_t offset, int whence,
+ const char *file, unsigned line);
+int failtest_close(int fd, const char *file, unsigned line);
+int failtest_fcntl(int fd, const char *file, unsigned line, int cmd, ...);
+pid_t failtest_getpid(const char *file, unsigned line);
+#endif /* CCAN_FAILTEST_PROTO_H */
diff --git a/lib/ccan/failtest/failtest_undo.h b/lib/ccan/failtest/failtest_undo.h
new file mode 100644
index 0000000000..3bb953dedd
--- /dev/null
+++ b/lib/ccan/failtest/failtest_undo.h
@@ -0,0 +1,49 @@
+/* Licensed under LGPL - see LICENSE file for details */
+#ifndef CCAN_FAILTEST_RESTORE_H
+#define CCAN_FAILTEST_RESTORE_H
+/* This file undoes the effect of failtest_override.h. */
+
+#undef calloc
+#define calloc(nmemb, size) \
+ failtest_calloc((nmemb), (size), NULL, 0)
+
+#undef malloc
+#define malloc(size) \
+ failtest_malloc((size), NULL, 0)
+
+#undef realloc
+#define realloc(ptr, size) \
+ failtest_realloc((ptr), (size), NULL, 0)
+
+#undef open
+#define open(pathname, ...) \
+ failtest_open((pathname), NULL, 0, __VA_ARGS__)
+
+#undef pipe
+#define pipe(pipefd) \
+ failtest_pipe((pipefd), NULL, 0)
+
+#undef read
+#define read(fd, buf, count) \
+ failtest_read((fd), (buf), (count), NULL, 0)
+
+#undef write
+#define write(fd, buf, count) \
+ failtest_write((fd), (buf), (count), NULL, 0)
+
+#undef mmap
+#define mmap(addr, length, prot, flags, fd, offset) \
+ failtest_mmap((addr), (length), (prot), (flags), (fd), (offset), NULL, 0)
+
+#undef lseek
+#define lseek(fd, off, whence) \
+ failtest_lseek((fd), (off), (whence), NULL, 0)
+
+#undef close
+#define close(fd) failtest_close(fd)
+
+#undef fcntl
+#define fcntl(fd, ...) \
+ failtest_fcntl((fd), NULL, 0, __VA_ARGS__)
+
+#endif /* CCAN_FAILTEST_RESTORE_H */
diff --git a/lib/ccan/failtest/test/run-failpath.c b/lib/ccan/failtest/test/run-failpath.c
new file mode 100644
index 0000000000..9795ee9d05
--- /dev/null
+++ b/lib/ccan/failtest/test/run-failpath.c
@@ -0,0 +1,39 @@
+#include <ccan/failtest/failtest.c>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <ccan/tap/tap.h>
+
+int main(void)
+{
+ int fds[2], fd;
+ void *p;
+
+ plan_tests(14);
+ failtest_init(0, NULL);
+
+ failpath = "mceopwrMCEOPWR";
+
+ ok1((p = failtest_malloc(10, "run-failpath.c", 1)) != NULL);
+ ok1(failtest_calloc(10, 5, "run-failpath.c", 1) != NULL);
+ ok1((p = failtest_realloc(p, 100, "run-failpath.c", 1)) != NULL);
+ ok1((fd = failtest_open("failpath-scratch", "run-failpath.c", 1,
+ O_RDWR|O_CREAT, 0600)) >= 0);
+ ok1(failtest_pipe(fds, "run-failpath.c", 1) == 0);
+ ok1(failtest_write(fd, "xxxx", 4, "run-failpath.c", 1) == 4);
+ lseek(fd, 0, SEEK_SET);
+ ok1(failtest_read(fd, p, 5, "run-failpath.c", 1) == 4);
+
+ /* Now we're into the failures. */
+ ok1(failtest_malloc(10, "run-failpath.c", 1) == NULL);
+ ok1(failtest_calloc(10, 5, "run-failpath.c", 1) == NULL);
+ ok1(failtest_realloc(p, 100, "run-failpath.c", 1) == NULL);
+ ok1(failtest_open("failpath-scratch", "run-failpath.c", 1,
+ O_RDWR|O_CREAT, 0600) == -1);
+ ok1(failtest_pipe(fds, "run-failpath.c", 1) == -1);
+ ok1(failtest_write(fd, "xxxx", 4, "run-failpath.c", 1) == -1);
+ lseek(fd, 0, SEEK_SET);
+ ok1(failtest_read(fd, p, 5, "run-failpath.c", 1) == -1);
+ return exit_status();
+}
diff --git a/lib/ccan/failtest/test/run-history.c b/lib/ccan/failtest/test/run-history.c
new file mode 100644
index 0000000000..b78682f5d5
--- /dev/null
+++ b/lib/ccan/failtest/test/run-history.c
@@ -0,0 +1,183 @@
+/* Include the C files directly. */
+#include <ccan/failtest/failtest.c>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <ccan/tap/tap.h>
+
+int main(void)
+{
+ struct failtest_call *call;
+ struct calloc_call calloc_call;
+ struct malloc_call malloc_call;
+ struct realloc_call realloc_call;
+ struct open_call open_call;
+ struct pipe_call pipe_call;
+ struct read_call read_call;
+ struct write_call write_call;
+ struct mmap_call mmap_call;
+ char buf[20];
+ unsigned int i;
+ char *path;
+
+ /* This is how many tests you plan to run */
+ plan_tests(69);
+
+ calloc_call.ret = calloc(1, 2);
+ calloc_call.nmemb = 1;
+ calloc_call.size = 2;
+ call = add_history(FAILTEST_CALLOC, true,
+ "run-history.c", 1, &calloc_call);
+ /* Normally should_fail would set this. */
+ call->fail = false;
+ ok1(call->type == FAILTEST_CALLOC);
+ ok1(call->can_leak == true);
+ ok1(strcmp(call->file, "run-history.c") == 0);
+ ok1(call->line == 1);
+ ok1(call->u.calloc.ret == calloc_call.ret);
+ ok1(call->u.calloc.nmemb == calloc_call.nmemb);
+ ok1(call->u.calloc.size == calloc_call.size);
+
+ malloc_call.ret = malloc(2);
+ malloc_call.size = 2;
+ call = add_history(FAILTEST_MALLOC, true,
+ "run-history.c", 2, &malloc_call);
+ /* Normally should_fail would set this. */
+ call->fail = false;
+ ok1(call->type == FAILTEST_MALLOC);
+ ok1(call->can_leak == true);
+ ok1(strcmp(call->file, "run-history.c") == 0);
+ ok1(call->line == 2);
+ ok1(call->u.malloc.ret == malloc_call.ret);
+ ok1(call->u.malloc.size == malloc_call.size);
+
+ realloc_call.ret = realloc(malloc_call.ret, 3);
+ realloc_call.ptr = malloc_call.ret;
+ realloc_call.size = 3;
+ call = add_history(FAILTEST_REALLOC, true, "run-history.c", 3,
+ &realloc_call);
+ /* Normally should_fail would set this. */
+ call->fail = false;
+ ok1(call->type == FAILTEST_REALLOC);
+ ok1(call->can_leak == true);
+ ok1(strcmp(call->file, "run-history.c") == 0);
+ ok1(call->line == 3);
+ ok1(call->u.realloc.ret == realloc_call.ret);
+ ok1(call->u.realloc.ptr == realloc_call.ptr);
+ ok1(call->u.realloc.size == realloc_call.size);
+
+ open_call.ret = open("test/run-history.c", O_RDONLY);
+ open_call.pathname = "test/run-history.c";
+ open_call.flags = O_RDONLY;
+ open_call.mode = 0;
+ open_call.closed = false;
+ call = add_history(FAILTEST_OPEN, true, "run-history.c", 4, &open_call);
+ /* Normally should_fail would set this. */
+ call->fail = false;
+ ok1(call->type == FAILTEST_OPEN);
+ ok1(call->can_leak == true);
+ ok1(strcmp(call->file, "run-history.c") == 0);
+ ok1(call->line == 4);
+ ok1(call->u.open.ret == open_call.ret);
+ ok1(strcmp(call->u.open.pathname, open_call.pathname) == 0);
+ ok1(call->u.open.flags == open_call.flags);
+ ok1(call->u.open.mode == open_call.mode);
+
+ pipe_call.ret = pipe(pipe_call.fds);
+ call = add_history(FAILTEST_PIPE, true, "run-history.c", 5, &pipe_call);
+ /* Normally should_fail would set this. */
+ call->fail = false;
+ ok1(call->type == FAILTEST_PIPE);
+ ok1(strcmp(call->file, "run-history.c") == 0);
+ ok1(call->can_leak == true);
+ ok1(call->line == 5);
+ ok1(call->u.pipe.ret == pipe_call.ret);
+ ok1(call->u.pipe.fds[0] == pipe_call.fds[0]);
+ ok1(call->u.pipe.fds[1] == pipe_call.fds[1]);
+
+ read_call.ret = read(open_call.ret, buf, 20);
+ read_call.buf = buf;
+ read_call.fd = open_call.ret;
+ read_call.count = 20;
+ call = add_history(FAILTEST_READ, false, "run-history.c", 6, &read_call);
+ /* Normally should_fail would set this. */
+ call->fail = false;
+ ok1(call->type == FAILTEST_READ);
+ ok1(call->can_leak == false);
+ ok1(strcmp(call->file, "run-history.c") == 0);
+ ok1(call->line == 6);
+ ok1(call->u.read.ret == read_call.ret);
+ ok1(call->u.read.buf == read_call.buf);
+ ok1(call->u.read.fd == read_call.fd);
+ ok1(call->u.read.count == read_call.count);
+
+ write_call.ret = 20;
+ write_call.buf = buf;
+ write_call.fd = open_call.ret;
+ write_call.count = 20;
+ write_call.opener = NULL;
+ call = add_history(FAILTEST_WRITE, false, "run-history.c", 7,
+ &write_call);
+ /* Normally should_fail would set this. */
+ call->fail = false;
+ ok1(call->type == FAILTEST_WRITE);
+ ok1(call->can_leak == false);
+ ok1(strcmp(call->file, "run-history.c") == 0);
+ ok1(call->line == 7);
+ ok1(call->u.write.ret == write_call.ret);
+ ok1(call->u.write.buf == write_call.buf);
+ ok1(call->u.write.fd == write_call.fd);
+ ok1(call->u.write.count == write_call.count);
+ ok1(call->u.write.opener == write_call.opener);
+
+ mmap_call.ret = &mmap_call;
+ mmap_call.addr = NULL;
+ mmap_call.length = 4096;
+ mmap_call.prot = PROT_READ;
+ mmap_call.flags = 0;
+ mmap_call.fd = open_call.ret;
+ mmap_call.offset = 0;
+ mmap_call.opener = opener_of(open_call.ret);
+ ok1(mmap_call.opener->type == FAILTEST_OPEN);
+ mmap_call.saved = NULL;
+
+ call = add_history(FAILTEST_MMAP, false, "run-history.c", 8,
+ &mmap_call);
+ /* Normally should_fail would set this. */
+ call->fail = false;
+ ok1(call->type == FAILTEST_MMAP);
+ ok1(call->can_leak == false);
+ ok1(strcmp(call->file, "run-history.c") == 0);
+ ok1(call->line == 8);
+ ok1(call->u.mmap.ret == mmap_call.ret);
+ ok1(call->u.mmap.addr == mmap_call.addr);
+ ok1(call->u.mmap.length == mmap_call.length);
+ ok1(call->u.mmap.prot == mmap_call.prot);
+ ok1(call->u.mmap.flags == mmap_call.flags);
+ ok1(call->u.mmap.fd == mmap_call.fd);
+ ok1(call->u.mmap.offset == mmap_call.offset);
+ ok1(call->u.mmap.opener == mmap_call.opener);
+ ok1(call->u.mmap.saved == mmap_call.saved);
+
+ i = 0;
+ tlist_for_each(&history, call, list)
+ i++;
+
+ ok1(i == 8);
+
+ tlist_for_each(&history, call, list)
+ call->fail = false;
+
+ path = failpath_string();
+ ok1(streq(path, "cmeoprwa"));
+ free(path);
+
+ tlist_for_each(&history, call, list)
+ call->fail = true;
+
+ path = failpath_string();
+ ok1(streq(path, "CMEOPRWA"));
+ free(path);
+
+ return exit_status();
+}
diff --git a/lib/ccan/failtest/test/run-locking.c b/lib/ccan/failtest/test/run-locking.c
new file mode 100644
index 0000000000..da0ee70fac
--- /dev/null
+++ b/lib/ccan/failtest/test/run-locking.c
@@ -0,0 +1,134 @@
+/* Include the C files directly. */
+#include <ccan/failtest/failtest.c>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <ccan/tap/tap.h>
+
+#define SIZE 8
+
+/* We don't want to fork and fail; we're just testing lock recording. */
+static enum failtest_result dont_fail(struct tlist_calls *history)
+{
+ return FAIL_DONT_FAIL;
+}
+
+static bool place_lock(int fd, char lockarr[], unsigned pos, unsigned size,
+ int type)
+{
+ struct flock fl;
+
+ /* Update record keeping. */
+ if (type == F_RDLCK)
+ memset(lockarr+pos, 1, size);
+ else if (type == F_WRLCK)
+ memset(lockarr+pos, 2, size);
+ else
+ memset(lockarr+pos, 0, size);
+
+ fl.l_whence = SEEK_SET;
+ fl.l_type = type;
+ fl.l_start = pos;
+ fl.l_len = size;
+ return failtest_fcntl(fd, "run-locking.c", 1, F_SETLK, &fl) == 0;
+}
+
+static char lock_lookup(int fd, unsigned pos)
+{
+ char ret = 0;
+ unsigned int i;
+ struct lock_info *l;
+
+ for (i = 0; i < lock_num; i++) {
+ l = &locks[i];
+
+ if (l->fd != fd)
+ continue;
+
+ if (pos >= l->start && pos <= l->end) {
+ if (ret)
+ ret = 3;
+ else if (l->type == F_RDLCK)
+ ret = 1;
+ else
+ ret = 2;
+ }
+ }
+ return ret;
+}
+
+static bool test(int fd,
+ unsigned p1, unsigned s1,
+ unsigned p2, unsigned s2,
+ unsigned p3, unsigned s3)
+{
+ unsigned int i;
+ char lockarr[SIZE];
+
+ memset(lockarr, 0, sizeof(lockarr));
+
+ if (!place_lock(fd, lockarr, p1, s1, F_WRLCK))
+ return false;
+
+ if (!place_lock(fd, lockarr, p2, s2, F_RDLCK))
+ return false;
+
+ if (!place_lock(fd, lockarr, p3, s3, F_UNLCK))
+ return false;
+
+ for (i = 0; i < SIZE; i++) {
+ if (lock_lookup(fd, i) != lockarr[i])
+ return false;
+ }
+
+ /* Reset lock info. */
+ lock_num = 0;
+ return true;
+}
+
+int main(void)
+{
+ int fd;
+ long flags;
+ unsigned int isize;
+
+ plan_tests(5835);
+ failtest_init(0, NULL);
+ failtest_hook = dont_fail;
+
+ fd = open("run-locking-scratch", O_RDWR|O_CREAT, 0600);
+ /* GETFL and SETFL wrappers should pass through. */
+ flags = fcntl(fd, F_GETFL);
+ ok1(failtest_fcntl(fd, "run-locking.c", 1, F_GETFL) == flags);
+ flags |= O_NONBLOCK;
+ ok1(failtest_fcntl(fd, "run-locking.c", 1, F_SETFL, flags) == 0);
+ ok1(failtest_fcntl(fd, "run-locking.c", 1, F_GETFL) == flags);
+
+ for (isize = 1; isize < 4; isize++) {
+ unsigned int ipos;
+ for (ipos = 0; ipos + isize < SIZE; ipos++) {
+ unsigned int jsize;
+ for (jsize = 1; jsize < 4; jsize++) {
+ unsigned int jpos;
+ for (jpos = 0; jpos + jsize < SIZE; jpos++) {
+ unsigned int ksize;
+ for (ksize = 1; ksize < 4; ksize++) {
+ unsigned int kpos;
+ for (kpos = 0;
+ kpos + ksize < SIZE;
+ kpos++) {
+ ok1(test(fd,
+ ipos, isize,
+ jpos, jsize,
+ kpos, ksize));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return exit_status();
+}
diff --git a/lib/ccan/failtest/test/run-malloc.c b/lib/ccan/failtest/test/run-malloc.c
new file mode 100644
index 0000000000..96641b8525
--- /dev/null
+++ b/lib/ccan/failtest/test/run-malloc.c
@@ -0,0 +1,116 @@
+#include "config.h"
+#include <stdlib.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <ccan/tap/tap.h>
+
+/* We don't actually want it to exit... */
+static jmp_buf exited;
+#define exit(status) longjmp(exited, (status) + 1)
+
+#define printf saved_printf
+static int saved_printf(const char *fmt, ...);
+
+#define fprintf saved_fprintf
+static int saved_fprintf(FILE *ignored, const char *fmt, ...);
+
+#define vfprintf saved_vfprintf
+static int saved_vfprintf(FILE *ignored, const char *fmt, va_list ap);
+
+/* Hack to avoid a memory leak which valgrind complains about. */
+#define realloc set_realloc
+static void *set_realloc(void *ptr, size_t size);
+
+#define free set_free
+static void set_free(void *ptr);
+
+/* Include the C files directly. */
+#include <ccan/failtest/failtest.c>
+
+#undef realloc
+#undef free
+
+static char *buffer;
+static void *set_realloc(void *ptr, size_t size)
+{
+ return buffer = realloc(ptr, size);
+}
+
+static void set_free(void *ptr)
+{
+ if (ptr == buffer)
+ buffer = NULL;
+ free(ptr);
+}
+
+static char *output = NULL;
+
+static int saved_vprintf(const char *fmt, va_list ap)
+{
+ int ret;
+ int len = 0;
+ va_list ap2;
+
+ va_copy(ap2, ap);
+ ret = vsnprintf(NULL, 0, fmt, ap2);
+ va_end(ap2);
+
+ if (output)
+ len = strlen(output);
+
+ output = realloc(output, len + ret + 1);
+ return vsprintf(output + len, fmt, ap);
+}
+
+static int saved_vfprintf(FILE *ignored, const char *fmt, va_list ap)
+{
+ return saved_vprintf(fmt, ap);
+}
+
+static int saved_printf(const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, fmt);
+ ret = saved_vprintf(fmt, ap);
+ va_end(ap);
+ return ret;
+}
+
+static int saved_fprintf(FILE *ignored, const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, fmt);
+ ret = saved_vprintf(fmt, ap);
+ va_end(ap);
+ return ret;
+}
+
+int main(void)
+{
+ int status;
+
+ plan_tests(3);
+ failtest_init(0, NULL);
+
+ status = setjmp(exited);
+ if (status == 0) {
+ char *p = failtest_malloc(1, "run-malloc.c", 1);
+ /* If we just segv, valgrind counts that as a failure.
+ * So kill ourselves creatively. */
+ if (!p)
+ kill(getpid(), SIGSEGV);
+ fail("Expected child to crash!");
+ } else {
+ ok1(status == 2);
+ ok1(strstr(output, "Killed by signal"));
+ ok1(strstr(output, "--failpath=M\n"));
+ }
+ free(buffer);
+ return exit_status();
+}
diff --git a/lib/ccan/failtest/test/run-open.c b/lib/ccan/failtest/test/run-open.c
new file mode 100644
index 0000000000..0166506480
--- /dev/null
+++ b/lib/ccan/failtest/test/run-open.c
@@ -0,0 +1,72 @@
+/* Include the C files directly. */
+#include <ccan/failtest/failtest.c>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <ccan/tap/tap.h>
+
+int main(void)
+{
+ int fd, pfd[2], err;
+ char buf[] = "Hello world!";
+ struct stat st;
+
+ plan_tests(12);
+ failtest_init(0, NULL);
+
+ if (pipe(pfd))
+ abort();
+ fd = failtest_open("run-open-scratchpad", "run-open.c", 1,
+ O_RDWR|O_CREAT, 0600);
+ if (fd == -1) {
+ /* We are the child: write error code for parent to check. */
+ err = errno;
+ if (write(pfd[1], &err, sizeof(err)) != sizeof(err))
+ abort();
+ failtest_exit(0);
+ }
+ /* Check it is read-write. */
+ ok1(write(fd, buf, strlen(buf)) == strlen(buf));
+ lseek(fd, SEEK_SET, 0);
+ ok1(read(fd, buf, strlen("Hello world!")) == strlen("Hello world!"));
+ ok1(strcmp(buf, "Hello world!") == 0);
+
+ /* Check name and perms. */
+ ok1(stat("run-open-scratchpad", &st) == 0);
+ ok1(st.st_size == strlen(buf));
+ ok1(S_ISREG(st.st_mode));
+ ok1((st.st_mode & 0777) == 0600);
+
+ /* Check child got correct errno. */
+ ok1(read(pfd[0], &err, sizeof(err)) == sizeof(err));
+ ok1(err == EACCES);
+
+ /* Clean up. */
+ failtest_close(fd, "run-open.c", 1);
+ close(pfd[0]);
+ close(pfd[1]);
+
+ /* Two-arg open. */
+ if (pipe(pfd) != 0)
+ abort();
+ fd = failtest_open("run-open-scratchpad", "run-open.c", 1, O_RDONLY);
+ if (fd == -1) {
+ /* We are the child: write error code for parent to check. */
+ err = errno;
+ if (write(pfd[1], &err, sizeof(err)) != sizeof(err))
+ abort();
+ failtest_exit(0);
+ }
+ /* Check it is read-only. */
+ ok1(write(fd, buf, strlen(buf)) == -1);
+ ok1(read(fd, buf, strlen("Hello world!")) == strlen("Hello world!"));
+ ok1(strcmp(buf, "Hello world!") == 0);
+ /* Clean up. */
+ failtest_close(fd, "run-open.c", 1);
+ close(pfd[0]);
+ close(pfd[1]);
+
+ return exit_status();
+}
diff --git a/lib/ccan/failtest/test/run-write.c b/lib/ccan/failtest/test/run-write.c
new file mode 100644
index 0000000000..6a712fec53
--- /dev/null
+++ b/lib/ccan/failtest/test/run-write.c
@@ -0,0 +1,51 @@
+/* Include the C files directly. */
+#include <ccan/failtest/failtest.c>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <ccan/tap/tap.h>
+
+int main(int argc, char *argv[])
+{
+ int fd;
+ char *p;
+ char buf[] = "Hello world!";
+
+ plan_tests(5);
+ failtest_init(argc, argv);
+
+ fd = failtest_open("run-write-scratchpad", __FILE__, __LINE__,
+ O_RDWR|O_CREAT, 0600);
+ /* Child will fail, ignore. */
+ if (fd < 0)
+ failtest_exit(0);
+ if (write(fd, buf, strlen(buf)) != strlen(buf))
+ abort();
+ ok1(lseek(fd, 0, SEEK_CUR) == strlen(buf));
+
+ p = failtest_malloc(100, __FILE__, __LINE__);
+ if (!p) {
+ /* We are the child. Do a heap of writes. */
+ unsigned int i;
+
+ for (i = 0; i < strlen(buf)+1; i++)
+ if (failtest_write(fd, "x", 1, __FILE__, __LINE__)
+ == 1)
+ break;
+ failtest_close(fd, __FILE__, __LINE__);
+ failtest_exit(0);
+ }
+
+ /* Seek pointer should be left alone! */
+ ok1(lseek(fd, 0, SEEK_CUR) == strlen(buf));
+ /* Length should be restored. */
+ ok1(lseek(fd, 0, SEEK_END) == strlen(buf));
+ lseek(fd, 0, SEEK_SET);
+ ok1(read(fd, buf, strlen(buf)) == strlen("Hello world!"));
+ ok1(strcmp(buf, "Hello world!") == 0);
+ failtest_close(fd, __FILE__, __LINE__);
+
+ return exit_status();
+}
diff --git a/lib/ccan/list/LICENSE b/lib/ccan/list/LICENSE
new file mode 100644
index 0000000000..5522aa5f33
--- /dev/null
+++ b/lib/ccan/list/LICENSE
@@ -0,0 +1,508 @@
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations
+below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it
+becomes a de-facto standard. To achieve this, non-free programs must
+be allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control
+compilation and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at least
+ three years, to give the same user the materials specified in
+ Subsection 6a, above, for a charge no more than the cost of
+ performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply, and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License
+may add an explicit geographical distribution limitation excluding those
+countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms
+of the ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library.
+It is safest to attach them to the start of each source file to most
+effectively convey the exclusion of warranty; and each file should
+have at least the "copyright" line and a pointer to where the full
+notice is found.
+
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or
+your school, if any, to sign a "copyright disclaimer" for the library,
+if necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James
+ Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/lib/ccan/list/_info b/lib/ccan/list/_info
new file mode 100644
index 0000000000..a30659c1cf
--- /dev/null
+++ b/lib/ccan/list/_info
@@ -0,0 +1,70 @@
+#include <stdio.h>
+#include <string.h>
+#include "config.h"
+
+/**
+ * list - double linked list routines
+ *
+ * The list header contains routines for manipulating double linked lists.
+ * It defines two types: struct list_head used for anchoring lists, and
+ * struct list_node which is usually embedded in the structure which is placed
+ * in the list.
+ *
+ * Example:
+ * #include <err.h>
+ * #include <stdio.h>
+ * #include <stdlib.h>
+ * #include <ccan/list/list.h>
+ *
+ * struct parent {
+ * const char *name;
+ * struct list_head children;
+ * unsigned int num_children;
+ * };
+ *
+ * struct child {
+ * const char *name;
+ * struct list_node list;
+ * };
+ *
+ * int main(int argc, char *argv[])
+ * {
+ * struct parent p;
+ * struct child *c;
+ * unsigned int i;
+ *
+ * if (argc < 2)
+ * errx(1, "Usage: %s parent children...", argv[0]);
+ *
+ * p.name = argv[1];
+ * list_head_init(&p.children);
+ * p.num_children = 0;
+ * for (i = 2; i < argc; i++) {
+ * c = malloc(sizeof(*c));
+ * c->name = argv[i];
+ * list_add(&p.children, &c->list);
+ * p.num_children++;
+ * }
+ *
+ * printf("%s has %u children:", p.name, p.num_children);
+ * list_for_each(&p.children, c, list)
+ * printf("%s ", c->name);
+ * printf("\n");
+ * return 0;
+ * }
+ *
+ * License: LGPL (v2.1 or any later version)
+ * Author: Rusty Russell <rusty@rustcorp.com.au>
+ */
+int main(int argc, char *argv[])
+{
+ if (argc != 2)
+ return 1;
+
+ if (strcmp(argv[1], "depends") == 0) {
+ printf("ccan/container_of\n");
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/lib/ccan/list/list.c b/lib/ccan/list/list.c
new file mode 100644
index 0000000000..29dc30ba19
--- /dev/null
+++ b/lib/ccan/list/list.c
@@ -0,0 +1,43 @@
+/* Licensed under LGPLv2.1+ - see LICENSE file for details */
+#include <stdio.h>
+#include <stdlib.h>
+#include "list.h"
+
+static void *corrupt(const char *abortstr,
+ const struct list_node *head,
+ const struct list_node *node,
+ unsigned int count)
+{
+ if (abortstr) {
+ fprintf(stderr,
+ "%s: prev corrupt in node %p (%u) of %p\n",
+ abortstr, node, count, head);
+ abort();
+ }
+ return NULL;
+}
+
+struct list_node *list_check_node(const struct list_node *node,
+ const char *abortstr)
+{
+ const struct list_node *p, *n;
+ int count = 0;
+
+ for (p = node, n = node->next; n != node; p = n, n = n->next) {
+ count++;
+ if (n->prev != p)
+ return corrupt(abortstr, node, n, count);
+ }
+ /* Check prev on head node. */
+ if (node->prev != p)
+ return corrupt(abortstr, node, node, 0);
+
+ return (struct list_node *)node;
+}
+
+struct list_head *list_check(const struct list_head *h, const char *abortstr)
+{
+ if (!list_check_node(&h->n, abortstr))
+ return NULL;
+ return (struct list_head *)h;
+}
diff --git a/lib/ccan/list/list.d b/lib/ccan/list/list.d
new file mode 100644
index 0000000000..dd249588c4
--- /dev/null
+++ b/lib/ccan/list/list.d
@@ -0,0 +1,27 @@
+ccan/list/list.o: ccan/list/list.c /usr/include/stdio.h \
+ /usr/include/features.h /usr/include/i386-linux-gnu/bits/predefs.h \
+ /usr/include/i386-linux-gnu/sys/cdefs.h \
+ /usr/include/i386-linux-gnu/bits/wordsize.h \
+ /usr/include/i386-linux-gnu/gnu/stubs.h \
+ /usr/include/i386-linux-gnu/gnu/stubs-32.h \
+ /usr/lib/gcc/i686-linux-gnu/4.5.4/include/stddef.h \
+ /usr/include/i386-linux-gnu/bits/types.h \
+ /usr/include/i386-linux-gnu/bits/typesizes.h /usr/include/libio.h \
+ /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/i686-linux-gnu/4.5.4/include/stdarg.h \
+ /usr/include/i386-linux-gnu/bits/stdio_lim.h \
+ /usr/include/i386-linux-gnu/bits/sys_errlist.h /usr/include/stdlib.h \
+ /usr/include/i386-linux-gnu/bits/waitflags.h \
+ /usr/include/i386-linux-gnu/bits/waitstatus.h /usr/include/endian.h \
+ /usr/include/i386-linux-gnu/bits/endian.h \
+ /usr/include/i386-linux-gnu/bits/byteswap.h \
+ /usr/include/i386-linux-gnu/sys/types.h /usr/include/time.h \
+ /usr/include/i386-linux-gnu/sys/select.h \
+ /usr/include/i386-linux-gnu/bits/select.h \
+ /usr/include/i386-linux-gnu/bits/sigset.h \
+ /usr/include/i386-linux-gnu/bits/time.h \
+ /usr/include/i386-linux-gnu/sys/sysmacros.h \
+ /usr/include/i386-linux-gnu/bits/pthreadtypes.h /usr/include/alloca.h \
+ ccan/list/list.h /usr/lib/gcc/i686-linux-gnu/4.5.4/include/stdbool.h \
+ /usr/include/assert.h ccan/container_of/container_of.h config.h \
+ ccan/check_type/check_type.h
diff --git a/lib/ccan/list/list.h b/lib/ccan/list/list.h
new file mode 100644
index 0000000000..0091ea4b65
--- /dev/null
+++ b/lib/ccan/list/list.h
@@ -0,0 +1,469 @@
+/* Licensed under LGPLv2.1+ - see LICENSE file for details */
+#ifndef CCAN_LIST_H
+#define CCAN_LIST_H
+#include <stdbool.h>
+#include <assert.h>
+#include <ccan/container_of/container_of.h>
+#include <ccan/check_type/check_type.h>
+
+/**
+ * struct list_node - an entry in a doubly-linked list
+ * @next: next entry (self if empty)
+ * @prev: previous entry (self if empty)
+ *
+ * This is used as an entry in a linked list.
+ * Example:
+ * struct child {
+ * const char *name;
+ * // Linked list of all us children.
+ * struct list_node list;
+ * };
+ */
+struct list_node
+{
+ struct list_node *next, *prev;
+};
+
+/**
+ * struct list_head - the head of a doubly-linked list
+ * @h: the list_head (containing next and prev pointers)
+ *
+ * This is used as the head of a linked list.
+ * Example:
+ * struct parent {
+ * const char *name;
+ * struct list_head children;
+ * unsigned int num_children;
+ * };
+ */
+struct list_head
+{
+ struct list_node n;
+};
+
+/**
+ * list_check - check head of a list for consistency
+ * @h: the list_head
+ * @abortstr: the location to print on aborting, or NULL.
+ *
+ * Because list_nodes have redundant information, consistency checking between
+ * the back and forward links can be done. This is useful as a debugging check.
+ * If @abortstr is non-NULL, that will be printed in a diagnostic if the list
+ * is inconsistent, and the function will abort.
+ *
+ * Returns the list head if the list is consistent, NULL if not (it
+ * can never return NULL if @abortstr is set).
+ *
+ * See also: list_check_node()
+ *
+ * Example:
+ * static void dump_parent(struct parent *p)
+ * {
+ * struct child *c;
+ *
+ * printf("%s (%u children):\n", p->name, p->num_children);
+ * list_check(&p->children, "bad child list");
+ * list_for_each(&p->children, c, list)
+ * printf(" -> %s\n", c->name);
+ * }
+ */
+struct list_head *list_check(const struct list_head *h, const char *abortstr);
+
+/**
+ * list_check_node - check node of a list for consistency
+ * @n: the list_node
+ * @abortstr: the location to print on aborting, or NULL.
+ *
+ * Check consistency of the list node is in (it must be in one).
+ *
+ * See also: list_check()
+ *
+ * Example:
+ * static void dump_child(const struct child *c)
+ * {
+ * list_check_node(&c->list, "bad child list");
+ * printf("%s\n", c->name);
+ * }
+ */
+struct list_node *list_check_node(const struct list_node *n,
+ const char *abortstr);
+
+#ifdef CCAN_LIST_DEBUG
+#define list_debug(h) list_check((h), __func__)
+#define list_debug_node(n) list_check_node((n), __func__)
+#else
+#define list_debug(h) (h)
+#define list_debug_node(n) (n)
+#endif
+
+/**
+ * LIST_HEAD_INIT - initializer for an empty list_head
+ * @name: the name of the list.
+ *
+ * Explicit initializer for an empty list.
+ *
+ * See also:
+ * LIST_HEAD, list_head_init()
+ *
+ * Example:
+ * static struct list_head my_list = LIST_HEAD_INIT(my_list);
+ */
+#define LIST_HEAD_INIT(name) { { &name.n, &name.n } }
+
+/**
+ * LIST_HEAD - define and initialize an empty list_head
+ * @name: the name of the list.
+ *
+ * The LIST_HEAD macro defines a list_head and initializes it to an empty
+ * list. It can be prepended by "static" to define a static list_head.
+ *
+ * See also:
+ * LIST_HEAD_INIT, list_head_init()
+ *
+ * Example:
+ * static LIST_HEAD(my_global_list);
+ */
+#define LIST_HEAD(name) \
+ struct list_head name = LIST_HEAD_INIT(name)
+
+/**
+ * list_head_init - initialize a list_head
+ * @h: the list_head to set to the empty list
+ *
+ * Example:
+ * ...
+ * struct parent *parent = malloc(sizeof(*parent));
+ *
+ * list_head_init(&parent->children);
+ * parent->num_children = 0;
+ */
+static inline void list_head_init(struct list_head *h)
+{
+ h->n.next = h->n.prev = &h->n;
+}
+
+/**
+ * list_add - add an entry at the start of a linked list.
+ * @h: the list_head to add the node to
+ * @n: the list_node to add to the list.
+ *
+ * The list_node does not need to be initialized; it will be overwritten.
+ * Example:
+ * struct child *child = malloc(sizeof(*child));
+ *
+ * child->name = "marvin";
+ * list_add(&parent->children, &child->list);
+ * parent->num_children++;
+ */
+static inline void list_add(struct list_head *h, struct list_node *n)
+{
+ n->next = h->n.next;
+ n->prev = &h->n;
+ h->n.next->prev = n;
+ h->n.next = n;
+ (void)list_debug(h);
+}
+
+/**
+ * list_add_tail - add an entry at the end of a linked list.
+ * @h: the list_head to add the node to
+ * @n: the list_node to add to the list.
+ *
+ * The list_node does not need to be initialized; it will be overwritten.
+ * Example:
+ * list_add_tail(&parent->children, &child->list);
+ * parent->num_children++;
+ */
+static inline void list_add_tail(struct list_head *h, struct list_node *n)
+{
+ n->next = &h->n;
+ n->prev = h->n.prev;
+ h->n.prev->next = n;
+ h->n.prev = n;
+ (void)list_debug(h);
+}
+
+/**
+ * list_empty - is a list empty?
+ * @h: the list_head
+ *
+ * If the list is empty, returns true.
+ *
+ * Example:
+ * assert(list_empty(&parent->children) == (parent->num_children == 0));
+ */
+static inline bool list_empty(const struct list_head *h)
+{
+ (void)list_debug(h);
+ return h->n.next == &h->n;
+}
+
+/**
+ * list_del - delete an entry from an (unknown) linked list.
+ * @n: the list_node to delete from the list.
+ *
+ * Note that this leaves @n in an undefined state; it can be added to
+ * another list, but not deleted again.
+ *
+ * See also:
+ * list_del_from()
+ *
+ * Example:
+ * list_del(&child->list);
+ * parent->num_children--;
+ */
+static inline void list_del(struct list_node *n)
+{
+ (void)list_debug_node(n);
+ n->next->prev = n->prev;
+ n->prev->next = n->next;
+#ifdef CCAN_LIST_DEBUG
+ /* Catch use-after-del. */
+ n->next = n->prev = NULL;
+#endif
+}
+
+/**
+ * list_del_from - delete an entry from a known linked list.
+ * @h: the list_head the node is in.
+ * @n: the list_node to delete from the list.
+ *
+ * This explicitly indicates which list a node is expected to be in,
+ * which is better documentation and can catch more bugs.
+ *
+ * See also: list_del()
+ *
+ * Example:
+ * list_del_from(&parent->children, &child->list);
+ * parent->num_children--;
+ */
+static inline void list_del_from(struct list_head *h, struct list_node *n)
+{
+#ifdef CCAN_LIST_DEBUG
+ {
+ /* Thorough check: make sure it was in list! */
+ struct list_node *i;
+ for (i = h->n.next; i != n; i = i->next)
+ assert(i != &h->n);
+ }
+#endif /* CCAN_LIST_DEBUG */
+
+ /* Quick test that catches a surprising number of bugs. */
+ assert(!list_empty(h));
+ list_del(n);
+}
+
+/**
+ * list_entry - convert a list_node back into the structure containing it.
+ * @n: the list_node
+ * @type: the type of the entry
+ * @member: the list_node member of the type
+ *
+ * Example:
+ * // First list entry is children.next; convert back to child.
+ * child = list_entry(parent->children.n.next, struct child, list);
+ *
+ * See Also:
+ * list_top(), list_for_each()
+ */
+#define list_entry(n, type, member) container_of(n, type, member)
+
+/**
+ * list_top - get the first entry in a list
+ * @h: the list_head
+ * @type: the type of the entry
+ * @member: the list_node member of the type
+ *
+ * If the list is empty, returns NULL.
+ *
+ * Example:
+ * struct child *first;
+ * first = list_top(&parent->children, struct child, list);
+ */
+#define list_top(h, type, member) \
+ ((type *)list_top_((h), list_off_(type, member)))
+
+static inline const void *list_top_(const struct list_head *h, size_t off)
+{
+ if (list_empty(h))
+ return NULL;
+ return (const char *)h->n.next - off;
+}
+
+/**
+ * list_tail - get the last entry in a list
+ * @h: the list_head
+ * @type: the type of the entry
+ * @member: the list_node member of the type
+ *
+ * If the list is empty, returns NULL.
+ *
+ * Example:
+ * struct child *last;
+ * last = list_tail(&parent->children, struct child, list);
+ */
+#define list_tail(h, type, member) \
+ ((type *)list_tail_((h), list_off_(type, member)))
+
+static inline const void *list_tail_(const struct list_head *h, size_t off)
+{
+ if (list_empty(h))
+ return NULL;
+ return (const char *)h->n.prev - off;
+}
+
+/**
+ * list_for_each - iterate through a list.
+ * @h: the list_head (warning: evaluated multiple times!)
+ * @i: the structure containing the list_node
+ * @member: the list_node member of the structure
+ *
+ * This is a convenient wrapper to iterate @i over the entire list. It's
+ * a for loop, so you can break and continue as normal.
+ *
+ * Example:
+ * list_for_each(&parent->children, child, list)
+ * printf("Name: %s\n", child->name);
+ */
+#define list_for_each(h, i, member) \
+ list_for_each_off(h, i, list_off_var_(i, member))
+
+/**
+ * list_for_each_rev - iterate through a list backwards.
+ * @h: the list_head
+ * @i: the structure containing the list_node
+ * @member: the list_node member of the structure
+ *
+ * This is a convenient wrapper to iterate @i over the entire list. It's
+ * a for loop, so you can break and continue as normal.
+ *
+ * Example:
+ * list_for_each_rev(&parent->children, child, list)
+ * printf("Name: %s\n", child->name);
+ */
+#define list_for_each_rev(h, i, member) \
+ for (i = container_of_var(list_debug(h)->n.prev, i, member); \
+ &i->member != &(h)->n; \
+ i = container_of_var(i->member.prev, i, member))
+
+/**
+ * list_for_each_safe - iterate through a list, maybe during deletion
+ * @h: the list_head
+ * @i: the structure containing the list_node
+ * @nxt: the structure containing the list_node
+ * @member: the list_node member of the structure
+ *
+ * This is a convenient wrapper to iterate @i over the entire list. It's
+ * a for loop, so you can break and continue as normal. The extra variable
+ * @nxt is used to hold the next element, so you can delete @i from the list.
+ *
+ * Example:
+ * struct child *next;
+ * list_for_each_safe(&parent->children, child, next, list) {
+ * list_del(&child->list);
+ * parent->num_children--;
+ * }
+ */
+#define list_for_each_safe(h, i, nxt, member) \
+ list_for_each_safe_off(h, i, nxt, list_off_var_(i, member))
+
+/**
+ * list_for_each_off - iterate through a list of memory regions.
+ * @h: the list_head
+ * @i: the pointer to a memory region wich contains list node data.
+ * @off: offset(relative to @i) at which list node data resides.
+ *
+ * This is a low-level wrapper to iterate @i over the entire list, used to
+ * implement all oher, more high-level, for-each constructs. It's a for loop,
+ * so you can break and continue as normal.
+ *
+ * WARNING! Being the low-level macro that it is, this wrapper doesn't know
+ * nor care about the type of @i. The only assumtion made is that @i points
+ * to a chunk of memory that at some @offset, relative to @i, contains a
+ * properly filled `struct node_list' which in turn contains pointers to
+ * memory chunks and it's turtles all the way down. Whith all that in mind
+ * remember that given the wrong pointer/offset couple this macro will
+ * happilly churn all you memory untill SEGFAULT stops it, in other words
+ * caveat emptor.
+ *
+ * It is worth mentioning that one of legitimate use-cases for that wrapper
+ * is operation on opaque types with known offset for `struct list_node'
+ * member(preferably 0), because it allows you not to disclose the type of
+ * @i.
+ *
+ * Example:
+ * list_for_each_off(&parent->children, child,
+ * offsetof(struct child, list))
+ * printf("Name: %s\n", child->name);
+ */
+#define list_for_each_off(h, i, off) \
+ for (i = list_node_to_off_(list_debug(h)->n.next, (off)); \
+ list_node_from_off_((void *)i, (off)) != &(h)->n; \
+ i = list_node_to_off_(list_node_from_off_((void *)i, (off))->next, \
+ (off)))
+
+/**
+ * list_for_each_safe_off - iterate through a list of memory regions, maybe
+ * during deletion
+ * @h: the list_head
+ * @i: the pointer to a memory region wich contains list node data.
+ * @nxt: the structure containing the list_node
+ * @off: offset(relative to @i) at which list node data resides.
+ *
+ * For details see `list_for_each_off' and `list_for_each_safe'
+ * descriptions.
+ *
+ * Example:
+ * list_for_each_safe_off(&parent->children, child,
+ * next, offsetof(struct child, list))
+ * printf("Name: %s\n", child->name);
+ */
+#define list_for_each_safe_off(h, i, nxt, off) \
+ for (i = list_node_to_off_(list_debug(h)->n.next, (off)), \
+ nxt = list_node_to_off_(list_node_from_off_(i, (off))->next, \
+ (off)); \
+ list_node_from_off_(i, (off)) != &(h)->n; \
+ i = nxt, \
+ nxt = list_node_to_off_(list_node_from_off_(i, (off))->next, \
+ (off)))
+
+
+/* Other -off variants. */
+#define list_entry_off(n, type, off) \
+ ((type *)list_node_from_off_((n), (off)))
+
+#define list_head_off(h, type, off) \
+ ((type *)list_head_off((h), (off)))
+
+#define list_tail_off(h, type, off) \
+ ((type *)list_tail_((h), (off)))
+
+#define list_add_off(h, n, off) \
+ list_add((h), list_node_from_off_((n), (off)))
+
+#define list_del_off(n, off) \
+ list_del(list_node_from_off_((n), (off)))
+
+#define list_del_from_off(h, n, off) \
+ list_del_from(h, list_node_from_off_((n), (off)))
+
+/* Offset helper functions so we only single-evaluate. */
+static inline void *list_node_to_off_(struct list_node *node, size_t off)
+{
+ return (void *)((char *)node - off);
+}
+static inline struct list_node *list_node_from_off_(void *ptr, size_t off)
+{
+ return (struct list_node *)((char *)ptr + off);
+}
+
+/* Get the offset of the member, but make sure it's a list_node. */
+#define list_off_(type, member) \
+ (container_off(type, member) + \
+ check_type(((type *)0)->member, struct list_node))
+
+#define list_off_var_(var, member) \
+ (container_off_var(var, member) + \
+ check_type(var->member, struct list_node))
+
+#endif /* CCAN_LIST_H */
diff --git a/lib/ccan/list/test/compile_ok-constant.c b/lib/ccan/list/test/compile_ok-constant.c
new file mode 100644
index 0000000000..c57cdadc31
--- /dev/null
+++ b/lib/ccan/list/test/compile_ok-constant.c
@@ -0,0 +1,49 @@
+#include <ccan/list/list.h>
+#include <ccan/tap/tap.h>
+#include <ccan/list/list.c>
+#include <stdbool.h>
+#include <stdio.h>
+
+struct child {
+ const char *name;
+ struct list_node list;
+};
+
+static bool children(const struct list_head *list)
+{
+ return !list_empty(list);
+}
+
+static const struct child *first_child(const struct list_head *list)
+{
+ return list_top(list, struct child, list);
+}
+
+static const struct child *last_child(const struct list_head *list)
+{
+ return list_tail(list, struct child, list);
+}
+
+static void check_children(const struct list_head *list)
+{
+ list_check(list, "bad child list");
+}
+
+static void print_children(const struct list_head *list)
+{
+ const struct child *c;
+ list_for_each(list, c, list)
+ printf("%s\n", c->name);
+}
+
+int main(void)
+{
+ LIST_HEAD(h);
+
+ children(&h);
+ first_child(&h);
+ last_child(&h);
+ check_children(&h);
+ print_children(&h);
+ return 0;
+}
diff --git a/lib/ccan/list/test/helper.c b/lib/ccan/list/test/helper.c
new file mode 100644
index 0000000000..8903ac1738
--- /dev/null
+++ b/lib/ccan/list/test/helper.c
@@ -0,0 +1,54 @@
+#include <stdlib.h>
+#include <stdbool.h>
+#include <time.h>
+
+#include <ccan/list/list.h>
+#include "helper.h"
+
+#define ANSWER_TO_THE_ULTIMATE_QUESTION_OF_LIFE_THE_UNIVERSE_AND_EVERYTHING \
+ (42)
+
+struct opaque {
+ struct list_node list;
+ size_t secret_offset;
+ char secret_drawer[42];
+};
+
+static bool not_randomized = true;
+
+struct opaque *create_opaque_blob(void)
+{
+ struct opaque *blob = calloc(1, sizeof(struct opaque));
+
+ if (not_randomized) {
+ srandom((int)time(NULL));
+ not_randomized = false;
+ }
+
+ blob->secret_offset = random() % (sizeof(blob->secret_drawer));
+ blob->secret_drawer[blob->secret_offset] =
+ ANSWER_TO_THE_ULTIMATE_QUESTION_OF_LIFE_THE_UNIVERSE_AND_EVERYTHING;
+
+ return blob;
+}
+
+bool if_blobs_know_the_secret(struct opaque *blob)
+{
+ bool answer = true;
+ int i;
+ for (i = 0; i < sizeof(blob->secret_drawer) /
+ sizeof(blob->secret_drawer[0]); i++)
+ if (i != blob->secret_offset)
+ answer = answer && (blob->secret_drawer[i] == 0);
+ else
+ answer = answer &&
+ (blob->secret_drawer[blob->secret_offset] ==
+ ANSWER_TO_THE_ULTIMATE_QUESTION_OF_LIFE_THE_UNIVERSE_AND_EVERYTHING);
+
+ return answer;
+}
+
+void destroy_opaque_blob(struct opaque *blob)
+{
+ free(blob);
+}
diff --git a/lib/ccan/list/test/helper.h b/lib/ccan/list/test/helper.h
new file mode 100644
index 0000000000..a09a3a997b
--- /dev/null
+++ b/lib/ccan/list/test/helper.h
@@ -0,0 +1,7 @@
+/* These are in a separate C file so we can test undefined structures. */
+struct opaque;
+typedef struct opaque opaque_t;
+
+opaque_t *create_opaque_blob(void);
+bool if_blobs_know_the_secret(opaque_t *blob);
+void destroy_opaque_blob(opaque_t *blob);
diff --git a/lib/ccan/list/test/run-check-corrupt.c b/lib/ccan/list/test/run-check-corrupt.c
new file mode 100644
index 0000000000..5dd9f9cc83
--- /dev/null
+++ b/lib/ccan/list/test/run-check-corrupt.c
@@ -0,0 +1,89 @@
+#include <setjmp.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <err.h>
+
+/* We don't actually want it to exit... */
+static jmp_buf aborted;
+#define abort() longjmp(aborted, 1)
+
+#define fprintf my_fprintf
+static char printf_buffer[1000];
+
+static int my_fprintf(FILE *stream, const char *format, ...)
+{
+ va_list ap;
+ int ret;
+ va_start(ap, format);
+ ret = vsprintf(printf_buffer, format, ap);
+ va_end(ap);
+ return ret;
+}
+
+#include <ccan/list/list.h>
+#include <ccan/tap/tap.h>
+#include <ccan/list/list.c>
+
+int main(int argc, char *argv[])
+{
+ struct list_head list;
+ struct list_node n1;
+ char expect[100];
+
+ plan_tests(9);
+ /* Empty list. */
+ list.n.next = &list.n;
+ list.n.prev = &list.n;
+ ok1(list_check(&list, NULL) == &list);
+
+ /* Bad back ptr */
+ list.n.prev = &n1;
+ /* Non-aborting version. */
+ ok1(list_check(&list, NULL) == NULL);
+
+ /* Aborting version. */
+ sprintf(expect, "test message: prev corrupt in node %p (0) of %p\n",
+ &list, &list);
+ if (setjmp(aborted) == 0) {
+ list_check(&list, "test message");
+ fail("list_check on empty with bad back ptr didn't fail!");
+ } else {
+ ok1(strcmp(printf_buffer, expect) == 0);
+ }
+
+ /* n1 in list. */
+ list.n.next = &n1;
+ list.n.prev = &n1;
+ n1.prev = &list.n;
+ n1.next = &list.n;
+ ok1(list_check(&list, NULL) == &list);
+ ok1(list_check_node(&n1, NULL) == &n1);
+
+ /* Bad back ptr */
+ n1.prev = &n1;
+ ok1(list_check(&list, NULL) == NULL);
+ ok1(list_check_node(&n1, NULL) == NULL);
+
+ /* Aborting version. */
+ sprintf(expect, "test message: prev corrupt in node %p (1) of %p\n",
+ &n1, &list);
+ if (setjmp(aborted) == 0) {
+ list_check(&list, "test message");
+ fail("list_check on n1 bad back ptr didn't fail!");
+ } else {
+ ok1(strcmp(printf_buffer, expect) == 0);
+ }
+
+ sprintf(expect, "test message: prev corrupt in node %p (0) of %p\n",
+ &n1, &n1);
+ if (setjmp(aborted) == 0) {
+ list_check_node(&n1, "test message");
+ fail("list_check_node on n1 bad back ptr didn't fail!");
+ } else {
+ ok1(strcmp(printf_buffer, expect) == 0);
+ }
+
+ return exit_status();
+}
diff --git a/lib/ccan/list/test/run-list_del_from-assert.c b/lib/ccan/list/test/run-list_del_from-assert.c
new file mode 100644
index 0000000000..05d6cad62c
--- /dev/null
+++ b/lib/ccan/list/test/run-list_del_from-assert.c
@@ -0,0 +1,36 @@
+#define CCAN_LIST_DEBUG 1
+#include <ccan/list/list.h>
+#include <ccan/tap/tap.h>
+#include <ccan/list/list.c>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <signal.h>
+
+int main(int argc, char *argv[])
+{
+ struct list_head list1, list2;
+ struct list_node n1, n2, n3;
+ pid_t child;
+ int status;
+
+ plan_tests(1);
+ list_head_init(&list1);
+ list_head_init(&list2);
+ list_add(&list1, &n1);
+ list_add(&list2, &n2);
+ list_add_tail(&list2, &n3);
+
+ child = fork();
+ if (child) {
+ wait(&status);
+ } else {
+ /* This should abort. */
+ list_del_from(&list1, &n3);
+ exit(0);
+ }
+
+ ok1(WIFSIGNALED(status) && WTERMSIG(status) == SIGABRT);
+ list_del_from(&list2, &n3);
+ return exit_status();
+}
diff --git a/lib/ccan/list/test/run-single-eval.c b/lib/ccan/list/test/run-single-eval.c
new file mode 100644
index 0000000000..f90eed357a
--- /dev/null
+++ b/lib/ccan/list/test/run-single-eval.c
@@ -0,0 +1,168 @@
+/* Make sure macros only evaluate their args once. */
+#include <ccan/list/list.h>
+#include <ccan/tap/tap.h>
+#include <ccan/list/list.c>
+
+struct parent {
+ const char *name;
+ struct list_head children;
+ unsigned int num_children;
+ int eval_count;
+};
+
+struct child {
+ const char *name;
+ struct list_node list;
+};
+
+static LIST_HEAD(static_list);
+
+#define ref(obj, counter) ((counter)++, (obj))
+
+int main(int argc, char *argv[])
+{
+ struct parent parent;
+ struct child c1, c2, c3, *c, *n;
+ unsigned int i;
+ unsigned int static_count = 0, parent_count = 0, list_count = 0,
+ node_count = 0;
+ struct list_head list = LIST_HEAD_INIT(list);
+
+ plan_tests(74);
+ /* Test LIST_HEAD, LIST_HEAD_INIT, list_empty and check_list */
+ ok1(list_empty(ref(&static_list, static_count)));
+ ok1(static_count == 1);
+ ok1(list_check(ref(&static_list, static_count), NULL));
+ ok1(static_count == 2);
+ ok1(list_empty(ref(&list, list_count)));
+ ok1(list_count == 1);
+ ok1(list_check(ref(&list, list_count), NULL));
+ ok1(list_count == 2);
+
+ parent.num_children = 0;
+ list_head_init(ref(&parent.children, parent_count));
+ ok1(parent_count == 1);
+ /* Test list_head_init */
+ ok1(list_empty(ref(&parent.children, parent_count)));
+ ok1(parent_count == 2);
+ ok1(list_check(ref(&parent.children, parent_count), NULL));
+ ok1(parent_count == 3);
+
+ c2.name = "c2";
+ list_add(ref(&parent.children, parent_count), &c2.list);
+ ok1(parent_count == 4);
+ /* Test list_add and !list_empty. */
+ ok1(!list_empty(ref(&parent.children, parent_count)));
+ ok1(parent_count == 5);
+ ok1(c2.list.next == &parent.children.n);
+ ok1(c2.list.prev == &parent.children.n);
+ ok1(parent.children.n.next == &c2.list);
+ ok1(parent.children.n.prev == &c2.list);
+ /* Test list_check */
+ ok1(list_check(ref(&parent.children, parent_count), NULL));
+ ok1(parent_count == 6);
+
+ c1.name = "c1";
+ list_add(ref(&parent.children, parent_count), &c1.list);
+ ok1(parent_count == 7);
+ /* Test list_add and !list_empty. */
+ ok1(!list_empty(ref(&parent.children, parent_count)));
+ ok1(parent_count == 8);
+ ok1(c2.list.next == &parent.children.n);
+ ok1(c2.list.prev == &c1.list);
+ ok1(parent.children.n.next == &c1.list);
+ ok1(parent.children.n.prev == &c2.list);
+ ok1(c1.list.next == &c2.list);
+ ok1(c1.list.prev == &parent.children.n);
+ /* Test list_check */
+ ok1(list_check(ref(&parent.children, parent_count), NULL));
+ ok1(parent_count == 9);
+
+ c3.name = "c3";
+ list_add_tail(ref(&parent.children, parent_count), &c3.list);
+ ok1(parent_count == 10);
+ /* Test list_add_tail and !list_empty. */
+ ok1(!list_empty(ref(&parent.children, parent_count)));
+ ok1(parent_count == 11);
+ ok1(parent.children.n.next == &c1.list);
+ ok1(parent.children.n.prev == &c3.list);
+ ok1(c1.list.next == &c2.list);
+ ok1(c1.list.prev == &parent.children.n);
+ ok1(c2.list.next == &c3.list);
+ ok1(c2.list.prev == &c1.list);
+ ok1(c3.list.next == &parent.children.n);
+ ok1(c3.list.prev == &c2.list);
+ /* Test list_check */
+ ok1(list_check(ref(&parent.children, parent_count), NULL));
+ ok1(parent_count == 12);
+
+ /* Test list_check_node */
+ ok1(list_check_node(&c1.list, NULL));
+ ok1(list_check_node(&c2.list, NULL));
+ ok1(list_check_node(&c3.list, NULL));
+
+ /* Test list_top */
+ ok1(list_top(ref(&parent.children, parent_count), struct child, list) == &c1);
+ ok1(parent_count == 13);
+
+ /* Test list_tail */
+ ok1(list_tail(ref(&parent.children, parent_count), struct child, list) == &c3);
+ ok1(parent_count == 14);
+
+ /* Test list_for_each. */
+ i = 0;
+ list_for_each(&parent.children, c, list) {
+ switch (i++) {
+ case 0:
+ ok1(c == &c1);
+ break;
+ case 1:
+ ok1(c == &c2);
+ break;
+ case 2:
+ ok1(c == &c3);
+ break;
+ }
+ if (i > 2)
+ break;
+ }
+ ok1(i == 3);
+
+ /* Test list_for_each_safe, list_del and list_del_from. */
+ i = 0;
+ list_for_each_safe(&parent.children, c, n, list) {
+ switch (i++) {
+ case 0:
+ ok1(c == &c1);
+ list_del(ref(&c->list, node_count));
+ ok1(node_count == 1);
+ break;
+ case 1:
+ ok1(c == &c2);
+ list_del_from(ref(&parent.children, parent_count),
+ ref(&c->list, node_count));
+ ok1(node_count == 2);
+ break;
+ case 2:
+ ok1(c == &c3);
+ list_del_from(ref(&parent.children, parent_count),
+ ref(&c->list, node_count));
+ ok1(node_count == 3);
+ break;
+ }
+ ok1(list_check(ref(&parent.children, parent_count), NULL));
+ if (i > 2)
+ break;
+ }
+ ok1(i == 3);
+ ok1(parent_count == 19);
+ ok1(list_empty(ref(&parent.children, parent_count)));
+ ok1(parent_count == 20);
+
+ /* Test list_top/list_tail on empty list. */
+ ok1(list_top(ref(&parent.children, parent_count), struct child, list) == NULL);
+ ok1(parent_count == 21);
+ ok1(list_tail(ref(&parent.children, parent_count), struct child, list) == NULL);
+ ok1(parent_count == 22);
+ return exit_status();
+}
diff --git a/lib/ccan/list/test/run-with-debug.c b/lib/ccan/list/test/run-with-debug.c
new file mode 100644
index 0000000000..d0902421f1
--- /dev/null
+++ b/lib/ccan/list/test/run-with-debug.c
@@ -0,0 +1,3 @@
+/* Just like run.c, but with all debug checks enabled. */
+#define CCAN_LIST_DEBUG 1
+#include <ccan/list/test/run.c>
diff --git a/lib/ccan/list/test/run.c b/lib/ccan/list/test/run.c
new file mode 100644
index 0000000000..952a0e15e6
--- /dev/null
+++ b/lib/ccan/list/test/run.c
@@ -0,0 +1,200 @@
+#include <ccan/list/list.h>
+#include <ccan/tap/tap.h>
+#include <ccan/list/list.c>
+#include "helper.h"
+
+struct parent {
+ const char *name;
+ struct list_head children;
+ unsigned int num_children;
+};
+
+struct child {
+ const char *name;
+ struct list_node list;
+};
+
+static LIST_HEAD(static_list);
+
+int main(int argc, char *argv[])
+{
+ struct parent parent;
+ struct child c1, c2, c3, *c, *n;
+ unsigned int i;
+ struct list_head list = LIST_HEAD_INIT(list);
+ opaque_t *q, *nq;
+ struct list_head opaque_list = LIST_HEAD_INIT(opaque_list);
+
+ plan_tests(65);
+ /* Test LIST_HEAD, LIST_HEAD_INIT, list_empty and check_list */
+ ok1(list_empty(&static_list));
+ ok1(list_check(&static_list, NULL));
+ ok1(list_empty(&list));
+ ok1(list_check(&list, NULL));
+
+ parent.num_children = 0;
+ list_head_init(&parent.children);
+ /* Test list_head_init */
+ ok1(list_empty(&parent.children));
+ ok1(list_check(&parent.children, NULL));
+
+ c2.name = "c2";
+ list_add(&parent.children, &c2.list);
+ /* Test list_add and !list_empty. */
+ ok1(!list_empty(&parent.children));
+ ok1(c2.list.next == &parent.children.n);
+ ok1(c2.list.prev == &parent.children.n);
+ ok1(parent.children.n.next == &c2.list);
+ ok1(parent.children.n.prev == &c2.list);
+ /* Test list_check */
+ ok1(list_check(&parent.children, NULL));
+
+ c1.name = "c1";
+ list_add(&parent.children, &c1.list);
+ /* Test list_add and !list_empty. */
+ ok1(!list_empty(&parent.children));
+ ok1(c2.list.next == &parent.children.n);
+ ok1(c2.list.prev == &c1.list);
+ ok1(parent.children.n.next == &c1.list);
+ ok1(parent.children.n.prev == &c2.list);
+ ok1(c1.list.next == &c2.list);
+ ok1(c1.list.prev == &parent.children.n);
+ /* Test list_check */
+ ok1(list_check(&parent.children, NULL));
+
+ c3.name = "c3";
+ list_add_tail(&parent.children, &c3.list);
+ /* Test list_add_tail and !list_empty. */
+ ok1(!list_empty(&parent.children));
+ ok1(parent.children.n.next == &c1.list);
+ ok1(parent.children.n.prev == &c3.list);
+ ok1(c1.list.next == &c2.list);
+ ok1(c1.list.prev == &parent.children.n);
+ ok1(c2.list.next == &c3.list);
+ ok1(c2.list.prev == &c1.list);
+ ok1(c3.list.next == &parent.children.n);
+ ok1(c3.list.prev == &c2.list);
+ /* Test list_check */
+ ok1(list_check(&parent.children, NULL));
+
+ /* Test list_check_node */
+ ok1(list_check_node(&c1.list, NULL));
+ ok1(list_check_node(&c2.list, NULL));
+ ok1(list_check_node(&c3.list, NULL));
+
+ /* Test list_top */
+ ok1(list_top(&parent.children, struct child, list) == &c1);
+
+ /* Test list_tail */
+ ok1(list_tail(&parent.children, struct child, list) == &c3);
+
+ /* Test list_for_each. */
+ i = 0;
+ list_for_each(&parent.children, c, list) {
+ switch (i++) {
+ case 0:
+ ok1(c == &c1);
+ break;
+ case 1:
+ ok1(c == &c2);
+ break;
+ case 2:
+ ok1(c == &c3);
+ break;
+ }
+ if (i > 2)
+ break;
+ }
+ ok1(i == 3);
+
+ /* Test list_for_each_rev. */
+ i = 0;
+ list_for_each_rev(&parent.children, c, list) {
+ switch (i++) {
+ case 0:
+ ok1(c == &c3);
+ break;
+ case 1:
+ ok1(c == &c2);
+ break;
+ case 2:
+ ok1(c == &c1);
+ break;
+ }
+ if (i > 2)
+ break;
+ }
+ ok1(i == 3);
+
+ /* Test list_for_each_safe, list_del and list_del_from. */
+ i = 0;
+ list_for_each_safe(&parent.children, c, n, list) {
+ switch (i++) {
+ case 0:
+ ok1(c == &c1);
+ list_del(&c->list);
+ break;
+ case 1:
+ ok1(c == &c2);
+ list_del_from(&parent.children, &c->list);
+ break;
+ case 2:
+ ok1(c == &c3);
+ list_del_from(&parent.children, &c->list);
+ break;
+ }
+ ok1(list_check(&parent.children, NULL));
+ if (i > 2)
+ break;
+ }
+ ok1(i == 3);
+ ok1(list_empty(&parent.children));
+
+ /* Test list_for_each_off. */
+ list_add_tail(&opaque_list,
+ (struct list_node *)create_opaque_blob());
+ list_add_tail(&opaque_list,
+ (struct list_node *)create_opaque_blob());
+ list_add_tail(&opaque_list,
+ (struct list_node *)create_opaque_blob());
+
+ i = 0;
+
+ list_for_each_off(&opaque_list, q, 0) {
+ i++;
+ ok1(if_blobs_know_the_secret(q));
+ }
+ ok1(i == 3);
+
+ /* Test list_for_each_safe_off, list_del_off and list_del_from_off. */
+ i = 0;
+ list_for_each_safe_off(&opaque_list, q, nq, 0) {
+ switch (i++) {
+ case 0:
+ ok1(if_blobs_know_the_secret(q));
+ list_del_off(q, 0);
+ destroy_opaque_blob(q);
+ break;
+ case 1:
+ ok1(if_blobs_know_the_secret(q));
+ list_del_from_off(&opaque_list, q, 0);
+ destroy_opaque_blob(q);
+ break;
+ case 2:
+ ok1(c == &c3);
+ list_del_from_off(&opaque_list, q, 0);
+ destroy_opaque_blob(q);
+ break;
+ }
+ ok1(list_check(&opaque_list, NULL));
+ if (i > 2)
+ break;
+ }
+ ok1(i == 3);
+ ok1(list_empty(&opaque_list));
+
+ /* Test list_top/list_tail on empty list. */
+ ok1(list_top(&parent.children, struct child, list) == NULL);
+ ok1(list_tail(&parent.children, struct child, list) == NULL);
+ return exit_status();
+}
diff --git a/lib/ccan/read_write_all/LICENSE b/lib/ccan/read_write_all/LICENSE
new file mode 100644
index 0000000000..5522aa5f33
--- /dev/null
+++ b/lib/ccan/read_write_all/LICENSE
@@ -0,0 +1,508 @@
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations
+below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it
+becomes a de-facto standard. To achieve this, non-free programs must
+be allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control
+compilation and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at least
+ three years, to give the same user the materials specified in
+ Subsection 6a, above, for a charge no more than the cost of
+ performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply, and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License
+may add an explicit geographical distribution limitation excluding those
+countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms
+of the ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library.
+It is safest to attach them to the start of each source file to most
+effectively convey the exclusion of warranty; and each file should
+have at least the "copyright" line and a pointer to where the full
+notice is found.
+
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or
+your school, if any, to sign a "copyright disclaimer" for the library,
+if necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James
+ Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/lib/ccan/read_write_all/_info b/lib/ccan/read_write_all/_info
new file mode 100644
index 0000000000..d70cbd1d15
--- /dev/null
+++ b/lib/ccan/read_write_all/_info
@@ -0,0 +1,44 @@
+#include <stdio.h>
+#include <string.h>
+#include "config.h"
+
+/**
+ * read_write_all - read_all and write_all routines.
+ *
+ * Successful read and write calls may only partly complete if a
+ * signal is received or they are not operating on a normal file.
+ *
+ * read_all() and write_all() do the looping for you.
+ *
+ * Example:
+ * #include <err.h>
+ * #include <stdio.h>
+ * #include <unistd.h>
+ * #include <ccan/read_write_all/read_write_all.h>
+ *
+ * #define BUFFER_SIZE 10
+ * int main(int argc, char *argv[])
+ * {
+ * char buffer[BUFFER_SIZE+1];
+ *
+ * if (!read_all(STDIN_FILENO, buffer, BUFFER_SIZE))
+ * err(1, "Could not read %u characters", BUFFER_SIZE);
+ * buffer[BUFFER_SIZE] = '\0';
+ * printf("I read '%.*s'\n", BUFFER_SIZE, buffer);
+ * return 0;
+ * }
+ *
+ * License: LGPL (v2.1 or any later version)
+ * Author: Rusty Russell <rusty@rustcorp.com.au>
+ */
+int main(int argc, char *argv[])
+{
+ if (argc != 2)
+ return 1;
+
+ if (strcmp(argv[1], "depends") == 0) {
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/lib/ccan/read_write_all/read_write_all.c b/lib/ccan/read_write_all/read_write_all.c
new file mode 100644
index 0000000000..c66d521598
--- /dev/null
+++ b/lib/ccan/read_write_all/read_write_all.c
@@ -0,0 +1,38 @@
+/* Licensed under LGPLv2+ - see LICENSE file for details */
+#include "read_write_all.h"
+#include <unistd.h>
+#include <errno.h>
+
+bool write_all(int fd, const void *data, size_t size)
+{
+ while (size) {
+ ssize_t done;
+
+ done = write(fd, data, size);
+ if (done < 0 && errno == EINTR)
+ continue;
+ if (done <= 0)
+ return false;
+ data = (const char *)data + done;
+ size -= done;
+ }
+
+ return true;
+}
+
+bool read_all(int fd, void *data, size_t size)
+{
+ while (size) {
+ ssize_t done;
+
+ done = read(fd, data, size);
+ if (done < 0 && errno == EINTR)
+ continue;
+ if (done <= 0)
+ return false;
+ data = (char *)data + done;
+ size -= done;
+ }
+
+ return true;
+}
diff --git a/lib/ccan/read_write_all/read_write_all.d b/lib/ccan/read_write_all/read_write_all.d
new file mode 100644
index 0000000000..f3f48f0290
--- /dev/null
+++ b/lib/ccan/read_write_all/read_write_all.d
@@ -0,0 +1,19 @@
+ccan/read_write_all/read_write_all.o: \
+ ccan/read_write_all/read_write_all.c \
+ ccan/read_write_all/read_write_all.h \
+ /usr/lib/gcc/i686-linux-gnu/4.5.4/include/stddef.h \
+ /usr/lib/gcc/i686-linux-gnu/4.5.4/include/stdbool.h \
+ /usr/include/unistd.h /usr/include/features.h \
+ /usr/include/i386-linux-gnu/bits/predefs.h \
+ /usr/include/i386-linux-gnu/sys/cdefs.h \
+ /usr/include/i386-linux-gnu/bits/wordsize.h \
+ /usr/include/i386-linux-gnu/gnu/stubs.h \
+ /usr/include/i386-linux-gnu/gnu/stubs-32.h \
+ /usr/include/i386-linux-gnu/bits/posix_opt.h \
+ /usr/include/i386-linux-gnu/bits/environments.h \
+ /usr/include/i386-linux-gnu/bits/types.h \
+ /usr/include/i386-linux-gnu/bits/typesizes.h \
+ /usr/include/i386-linux-gnu/bits/confname.h /usr/include/getopt.h \
+ /usr/include/errno.h /usr/include/i386-linux-gnu/bits/errno.h \
+ /usr/include/linux/errno.h /usr/include/i386-linux-gnu/asm/errno.h \
+ /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h
diff --git a/lib/ccan/read_write_all/read_write_all.h b/lib/ccan/read_write_all/read_write_all.h
new file mode 100644
index 0000000000..aa2635aaf2
--- /dev/null
+++ b/lib/ccan/read_write_all/read_write_all.h
@@ -0,0 +1,10 @@
+/* Licensed under LGPLv2+ - see LICENSE file for details */
+#ifndef _CCAN_READ_WRITE_H
+#define _CCAN_READ_WRITE_H
+#include <stddef.h>
+#include <stdbool.h>
+
+bool write_all(int fd, const void *data, size_t size);
+bool read_all(int fd, void *data, size_t size);
+
+#endif /* _CCAN_READ_WRITE_H */
diff --git a/lib/ccan/read_write_all/test/run-read_all.c b/lib/ccan/read_write_all/test/run-read_all.c
new file mode 100644
index 0000000000..29f81fc703
--- /dev/null
+++ b/lib/ccan/read_write_all/test/run-read_all.c
@@ -0,0 +1,76 @@
+/* FIXME: Do something tricky to ensure we really do loop in read_all. */
+
+#include <ccan/read_write_all/read_write_all.h>
+#include <ccan/read_write_all/read_write_all.c>
+#include <ccan/tap/tap.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <limits.h>
+#include <err.h>
+#include <stdlib.h>
+#include <string.h>
+
+static volatile int sigcount;
+static int p2c[2], c2p[2];
+static void got_signal(int sig)
+{
+ char c = 0;
+ if (write(p2c[1], &c, 1) == 1)
+ sigcount++;
+}
+
+/* < PIPE_BUF *will* be atomic. But > PIPE_BUF only *might* be non-atomic. */
+#define BUFSZ (1024*1024)
+
+int main(int argc, char *argv[])
+{
+ char *buffer;
+ char c = 0;
+ int status;
+ pid_t child;
+
+ buffer = calloc(BUFSZ, 2);
+ plan_tests(6);
+
+ /* We fork and torture parent. */
+ if (pipe(p2c) != 0 || pipe(c2p) != 0)
+ err(1, "pipe");
+ child = fork();
+
+ if (!child) {
+ close(p2c[1]);
+ close(c2p[0]);
+ /* Child. Make sure parent ready, then write in two parts. */
+ if (read(p2c[0], &c, 1) != 1)
+ exit(1);
+ memset(buffer, 0xff, BUFSZ*2);
+ if (!write_all(c2p[1], buffer, BUFSZ))
+ exit(2);
+ if (kill(getppid(), SIGUSR1) != 0)
+ exit(3);
+ /* Make sure they get signal. */
+ if (read(p2c[0], &c, 1) != 1)
+ exit(4);
+ if (write(c2p[1], buffer, BUFSZ) != BUFSZ)
+ exit(5);
+ exit(0);
+ }
+ if (child == -1)
+ err(1, "forking");
+
+ close(p2c[0]);
+ close(c2p[1]);
+ signal(SIGUSR1, got_signal);
+ ok1(write(p2c[1], &c, 1) == 1);
+ ok1(read_all(c2p[0], buffer, BUFSZ*2));
+ ok1(memchr(buffer, 0, BUFSZ*2) == NULL);
+ ok1(sigcount == 1);
+ ok1(wait(&status) == child);
+ ok(WIFEXITED(status) && WEXITSTATUS(status) == 0,
+ "WIFEXITED(status) = %u, WEXITSTATUS(status) = %u",
+ WIFEXITED(status), WEXITSTATUS(status));
+ free(buffer);
+ return exit_status();
+}
diff --git a/lib/ccan/read_write_all/test/run-write_all.c b/lib/ccan/read_write_all/test/run-write_all.c
new file mode 100644
index 0000000000..e2baf48dfe
--- /dev/null
+++ b/lib/ccan/read_write_all/test/run-write_all.c
@@ -0,0 +1,68 @@
+#include <ccan/read_write_all/read_write_all.h>
+#include <ccan/tap/tap.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <limits.h>
+#include <sys/wait.h>
+#include <err.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+static ssize_t test_write(int fd, const void *buf, size_t count);
+#define write test_write
+#include <ccan/read_write_all/read_write_all.c>
+#undef write
+
+static ssize_t write_return;
+
+static ssize_t test_write(int fd, const void *buf, size_t count)
+{
+ if (write_return == 0) {
+ errno = ENOSPC;
+ return 0;
+ }
+
+ if (write_return < 0) {
+ errno = -write_return;
+ /* Don't return EINTR more than once! */
+ if (errno == EINTR)
+ write_return = count;
+ return -1;
+ }
+
+ if (write_return < count)
+ return write_return;
+ return count;
+}
+
+#define BUFSZ 1024
+
+int main(int argc, char *argv[])
+{
+ char *buffer;
+
+ buffer = malloc(BUFSZ);
+ plan_tests(8);
+
+ write_return = -ENOSPC;
+ ok1(!write_all(100, buffer, BUFSZ));
+ ok1(errno == ENOSPC);
+
+ write_return = -EINTR;
+ ok1(write_all(100, buffer, BUFSZ));
+ ok1(errno == EINTR);
+
+ write_return = 1;
+ errno = 0;
+ ok1(write_all(100, buffer, BUFSZ));
+ ok1(errno == 0);
+
+ write_return = BUFSZ;
+ ok1(write_all(100, buffer, BUFSZ));
+ ok1(errno == 0);
+ free(buffer);
+
+ return exit_status();
+}
diff --git a/lib/ccan/tcon/_info b/lib/ccan/tcon/_info
new file mode 100644
index 0000000000..02c0dd8add
--- /dev/null
+++ b/lib/ccan/tcon/_info
@@ -0,0 +1,74 @@
+#include "config.h"
+#include <string.h>
+
+/**
+ * tcon - routines for creating typesafe generic containers
+ *
+ * This code lets users create a structure with a typecanary; your API
+ * is then a set of macros which check the type canary before calling
+ * the generic routines.
+ *
+ * Example:
+ * #include <ccan/tcon/tcon.h>
+ * #include <stdio.h>
+ *
+ * // A simple container class. Can only contain one thing though!
+ * struct container {
+ * void *contents;
+ * };
+ * static inline void container_add_raw(struct container *c, void *p)
+ * {
+ * c->contents = p;
+ * }
+ * static inline void *container_get_raw(struct container *c)
+ * {
+ * return c->contents;
+ * }
+ *
+ * // This lets the user define their container type; includes a
+ * // "type canary" to check types against.
+ * #define DEFINE_TYPED_CONTAINER_STRUCT(name, type) \
+ * struct name { struct container raw; TCON(type canary); }
+ *
+ * // These macros make sure the container type and pointer match.
+ * #define container_add(c, p) \
+ * container_add_raw(&tcon_check((c), canary, (p))->raw, (p))
+ * #define container_get(c) \
+ * tcon_cast((c), canary, container_get_raw(&(c)->raw))
+ *
+ * // Now, let's define two different containers.
+ * DEFINE_TYPED_CONTAINER_STRUCT(int_container, int *);
+ * DEFINE_TYPED_CONTAINER_STRUCT(string_container, char *);
+ *
+ * int main(int argc, char *argv[])
+ * {
+ * struct int_container ic;
+ * struct string_container sc;
+ *
+ * // We would get a warning if we used the wrong types...
+ * container_add(&ic, &argc);
+ * container_add(&sc, argv[argc-1]);
+ *
+ * printf("Last arg is %s of %i arguments\n",
+ * container_get(&sc), *container_get(&ic) - 1);
+ * return 0;
+ * }
+ * // Given "foo" outputs "Last arg is foo of 1 arguments"
+ * // Given "foo bar" outputs "Last arg is bar of 2 arguments"
+ *
+ * License: Public domain
+ *
+ * Author: Rusty Russell <rusty@rustcorp.com.au>
+ */
+int main(int argc, char *argv[])
+{
+ /* Expect exactly one argument */
+ if (argc != 2)
+ return 1;
+
+ if (strcmp(argv[1], "depends") == 0) {
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/lib/ccan/tcon/tcon.h b/lib/ccan/tcon/tcon.h
new file mode 100644
index 0000000000..93c3ea6b9f
--- /dev/null
+++ b/lib/ccan/tcon/tcon.h
@@ -0,0 +1,115 @@
+/* Placed into the public domain */
+#ifndef CCAN_TCON_H
+#define CCAN_TCON_H
+#include "config.h"
+
+/**
+ * TCON - declare a _tcon type containing canary variables.
+ * @decls: the semi-colon separated list of type canaries.
+ *
+ * This declares a _tcon member for a structure. It should be the
+ * last element in your structure; with sufficient compiler support it
+ * will not use any actual storage. tcon_check() will compare
+ * expressions with one of these "type canaries" to cause warnings if
+ * the container is misused.
+ *
+ * A type of "void *" will allow tcon_check() to pass on any (pointer) type.
+ *
+ * Example:
+ * // Simply typesafe linked list.
+ * struct list_head {
+ * struct list_head *prev, *next;
+ * };
+ *
+ * struct string_list {
+ * struct list_head raw;
+ * TCON(char *canary);
+ * };
+ *
+ * // More complex: mapping from one type to another.
+ * struct map {
+ * void *contents;
+ * };
+ *
+ * struct int_to_string_map {
+ * struct map raw;
+ * TCON(char *charp_canary; int int_canary);
+ * };
+ */
+#if HAVE_FLEXIBLE_ARRAY_MEMBER
+#define TCON(decls) struct { decls; } _tcon[]
+#else
+#define TCON(decls) struct { decls; } _tcon[1]
+#endif
+
+/**
+ * tcon_check - typecheck a typed container
+ * @x: the structure containing the TCON.
+ * @canary: which canary to check against.
+ * @expr: the expression whose type must match the TCON (not evaluated)
+ *
+ * This macro is used to check that the expression is the type
+ * expected for this structure (note the "useless" sizeof() argument
+ * which contains this comparison with the type canary).
+ *
+ * It evaluates to @x so you can chain it.
+ *
+ * Example:
+ * #define tlist_add(h, n, member) \
+ * list_add(&tcon_check((h), canary, (n))->raw, &(n)->member)
+ */
+#define tcon_check(x, canary, expr) \
+ (sizeof((x)->_tcon[0].canary == (expr)) ? (x) : (x))
+
+/**
+ * tcon_check_ptr - typecheck a typed container
+ * @x: the structure containing the TCON.
+ * @canary: which canary to check against.
+ * @expr: the expression whose type must match &TCON (not evaluated)
+ *
+ * This macro is used to check that the expression is a pointer to the type
+ * expected for this structure (note the "useless" sizeof() argument
+ * which contains this comparison with the type canary), or NULL.
+ *
+ * It evaluates to @x so you can chain it.
+ */
+#define tcon_check_ptr(x, canary, expr) \
+ (sizeof(&(x)->_tcon[0].canary == (expr)) ? (x) : (x))
+
+
+/**
+ * tcon_type - the type within a container (or void *)
+ * @x: the structure containing the TCON.
+ * @canary: which canary to check against.
+ */
+#if HAVE_TYPEOF
+#define tcon_type(x, canary) __typeof__((x)->_tcon[0].canary)
+#else
+#define tcon_type(x, canary) void *
+#endif
+
+/**
+ * tcon_ptr_type - pointer to the type within a container (or void *)
+ * @x: the structure containing the TCON.
+ * @canary: which canary to check against.
+ */
+#if HAVE_TYPEOF
+#define tcon_ptr_type(x, canary) __typeof__(&(x)->_tcon[0].canary)
+#else
+#define tcon_ptr_type(x, canary) void *
+#endif
+
+/**
+ * tcon_cast - cast to a canary type for this container (or void *)
+ * @x: a structure containing the TCON.
+ * @canary: which canary to cast to.
+ * @expr: the value to cast
+ *
+ * This is used to cast to the correct type for this container. If the
+ * platform doesn't HAVE_TYPEOF, then it casts to void * (which will
+ * cause a warning if the user doesn't expect a pointer type).
+ */
+#define tcon_cast(x, canary, expr) ((tcon_type((x), canary))(expr))
+#define tcon_cast_ptr(x, canary, expr) ((tcon_ptr_type((x), canary))(expr))
+
+#endif /* CCAN_TCON_H */
diff --git a/lib/ccan/tcon/test/compile_fail-tcon_cast.c b/lib/ccan/tcon/test/compile_fail-tcon_cast.c
new file mode 100644
index 0000000000..f80ef42c09
--- /dev/null
+++ b/lib/ccan/tcon/test/compile_fail-tcon_cast.c
@@ -0,0 +1,29 @@
+#include <ccan/tcon/tcon.h>
+#include <stdlib.h>
+
+struct container {
+ void *p;
+};
+
+struct int_and_charp_container {
+ struct container raw;
+ TCON(int *tc1; char *tc2);
+};
+
+int main(int argc, char *argv[])
+{
+ struct int_and_charp_container icon;
+#ifdef FAIL
+#if !HAVE_TYPEOF
+#error We cannot detect type problems without HAVE_TYPEOF
+#endif
+ char *
+#else
+ int *
+#endif
+ x;
+
+ icon.raw.p = NULL;
+ x = tcon_cast(&icon, tc1, icon.raw.p);
+ return 0;
+}
diff --git a/lib/ccan/tcon/test/compile_fail.c b/lib/ccan/tcon/test/compile_fail.c
new file mode 100644
index 0000000000..683bbd62ff
--- /dev/null
+++ b/lib/ccan/tcon/test/compile_fail.c
@@ -0,0 +1,25 @@
+#include <ccan/tcon/tcon.h>
+#include <stdlib.h>
+
+struct container {
+ void *p;
+};
+
+struct int_container {
+ struct container raw;
+ TCON(int *canary);
+};
+
+int main(int argc, char *argv[])
+{
+ struct int_container icon;
+#ifdef FAIL
+ char *
+#else
+ int *
+#endif
+ x = NULL;
+
+ tcon_check(&icon, canary, x)->raw.p = x;
+ return 0;
+}
diff --git a/lib/ccan/tcon/test/compile_ok-void.c b/lib/ccan/tcon/test/compile_ok-void.c
new file mode 100644
index 0000000000..26b712f6b2
--- /dev/null
+++ b/lib/ccan/tcon/test/compile_ok-void.c
@@ -0,0 +1,21 @@
+#include <ccan/tcon/tcon.h>
+#include <stdlib.h>
+
+struct container {
+ void *p;
+};
+
+struct void_container {
+ struct container raw;
+ TCON(void *canary);
+};
+
+int main(int argc, char *argv[])
+{
+ struct void_container vcon;
+
+ tcon_check(&vcon, canary, NULL)->raw.p = NULL;
+ tcon_check(&vcon, canary, argv[0])->raw.p = NULL;
+ tcon_check(&vcon, canary, main)->raw.p = NULL;
+ return 0;
+}
diff --git a/lib/ccan/tcon/test/compile_ok.c b/lib/ccan/tcon/test/compile_ok.c
new file mode 100644
index 0000000000..447f0ee50a
--- /dev/null
+++ b/lib/ccan/tcon/test/compile_ok.c
@@ -0,0 +1,27 @@
+#include <ccan/tcon/tcon.h>
+#include <stdlib.h>
+
+struct container {
+ void *p;
+};
+
+struct int_container {
+ struct container raw;
+ TCON(int tc);
+};
+
+struct charp_and_int_container {
+ struct container raw;
+ TCON(int tc1; char *tc2);
+};
+
+int main(int argc, char *argv[])
+{
+ struct int_container icon;
+ struct charp_and_int_container cicon;
+
+ tcon_check(&icon, tc, 7)->raw.p = NULL;
+ tcon_check(&cicon, tc1, 7)->raw.p = argv[0];
+ tcon_check(&cicon, tc2, argv[0])->raw.p = argv[0];
+ return 0;
+}
diff --git a/lib/ccan/time/LICENSE b/lib/ccan/time/LICENSE
new file mode 100644
index 0000000000..89de354795
--- /dev/null
+++ b/lib/ccan/time/LICENSE
@@ -0,0 +1,17 @@
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/lib/ccan/time/_info b/lib/ccan/time/_info
new file mode 100644
index 0000000000..fdad27561a
--- /dev/null
+++ b/lib/ccan/time/_info
@@ -0,0 +1,47 @@
+#include <string.h>
+#include "config.h"
+
+/**
+ * time - routines for dealing with time
+ *
+ * This code provides convenient functions for working with time.
+ *
+ * Author: Rusty Russell <rusty@rustcorp.com.au>
+ * License: BSD-MIT
+ *
+ * Example:
+ * #include <ccan/time/time.h>
+ * #include <stdlib.h>
+ * #include <stdio.h>
+ * #include <err.h>
+ *
+ * int main(int argc, char *argv[])
+ * {
+ * struct timeval t;
+ *
+ * if (argc != 2)
+ * errx(1, "Usage: %s <diff in millisec>", argv[0]);
+ *
+ * t = time_now();
+ * if (argv[1][0] == '-')
+ * t = time_sub(t, time_from_msec(atol(argv[1]+1)));
+ * else
+ * t = time_add(t, time_from_msec(atol(argv[1])));
+ *
+ * printf("%lu.%06u\n",
+ * (unsigned long)t.tv_sec, (unsigned)t.tv_usec);
+ * return 0;
+ * }
+ */
+int main(int argc, char *argv[])
+{
+ /* Expect exactly one argument */
+ if (argc != 2)
+ return 1;
+
+ if (strcmp(argv[1], "depends") == 0) {
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/lib/ccan/time/test/run.c b/lib/ccan/time/test/run.c
new file mode 100644
index 0000000000..80391694cd
--- /dev/null
+++ b/lib/ccan/time/test/run.c
@@ -0,0 +1,111 @@
+#include <ccan/time/time.h>
+#include <ccan/time/time.c>
+#include <ccan/tap/tap.h>
+
+int main(void)
+{
+ struct timeval t1, t2, t3, zero = { 0, 0 };
+
+ plan_tests(46);
+
+ /* Test time_now */
+ t1 = time_now();
+ t2 = time_now();
+
+ /* Test time_sub. */
+ t3 = time_sub(t2, t1);
+ ok1(t3.tv_sec > 0 || t3.tv_usec >= 0);
+ t3 = time_sub(t2, t2);
+ ok1(t3.tv_sec == 0 && t3.tv_usec == 0);
+ t3 = time_sub(t1, t1);
+ ok1(t3.tv_sec == 0 && t3.tv_usec == 0);
+
+ /* Test time_eq */
+ ok1(time_eq(t1, t1));
+ ok1(time_eq(t2, t2));
+ ok1(!time_eq(t1, t3));
+ ok1(!time_eq(t2, t3));
+
+ /* Make sure t2 > t1. */
+ t3.tv_sec = 0;
+ t3.tv_usec = 1;
+ t2 = time_add(t2, t3);
+
+ /* Test time_less and time_greater. */
+ ok1(!time_eq(t1, t2));
+ ok1(!time_greater(t1, t2));
+ ok1(time_less(t1, t2));
+ ok1(time_greater(t2, t1));
+ ok1(!time_less(t2, t1));
+ t3.tv_sec = 0;
+ t3.tv_usec = 999999;
+ t2 = time_add(t2, t3);
+ ok1(!time_eq(t1, t2));
+ ok1(!time_greater(t1, t2));
+ ok1(time_less(t1, t2));
+ ok1(time_greater(t2, t1));
+ ok1(!time_less(t2, t1));
+
+ t3 = time_sub(t2, zero);
+ ok1(time_eq(t3, t2));
+ t3 = time_sub(t2, t2);
+ ok1(time_eq(t3, zero));
+
+ /* time_from_msec / time_to_msec */
+ t3 = time_from_msec(500);
+ ok1(t3.tv_sec == 0);
+ ok1(t3.tv_usec == 500000);
+ ok1(time_to_msec(t3) == 500);
+
+ t3 = time_from_msec(1000);
+ ok1(t3.tv_sec == 1);
+ ok1(t3.tv_usec == 0);
+ ok1(time_to_msec(t3) == 1000);
+
+ t3 = time_from_msec(1500);
+ ok1(t3.tv_sec == 1);
+ ok1(t3.tv_usec == 500000);
+ ok1(time_to_msec(t3) == 1500);
+
+ /* time_from_usec */
+ t3 = time_from_usec(500000);
+ ok1(t3.tv_sec == 0);
+ ok1(t3.tv_usec == 500000);
+ ok1(time_to_usec(t3) == 500000);
+
+ t3 = time_from_usec(1000000);
+ ok1(t3.tv_sec == 1);
+ ok1(t3.tv_usec == 0);
+ ok1(time_to_usec(t3) == 1000000);
+
+ t3 = time_from_usec(1500000);
+ ok1(t3.tv_sec == 1);
+ ok1(t3.tv_usec == 500000);
+ ok1(time_to_usec(t3) == 1500000);
+
+ /* Test wrapunder */
+ t3 = time_sub(time_sub(t2, time_from_msec(500)), time_from_msec(500));
+ ok1(t3.tv_sec == t2.tv_sec - 1);
+ ok1(t3.tv_usec == t2.tv_usec);
+
+ /* time_divide and time_multiply */
+ t1.tv_usec = 100;
+ t1.tv_sec = 100;
+
+ t3 = time_divide(t1, 2);
+ ok1(t3.tv_sec == 50);
+ ok1(t3.tv_usec == 50);
+
+ t3 = time_divide(t1, 100);
+ ok1(t3.tv_sec == 1);
+ ok1(t3.tv_usec == 1);
+
+ t3 = time_multiply(t3, 100);
+ ok1(time_eq(t3, t1));
+
+ t3 = time_divide(t1, 200);
+ ok1(t3.tv_sec == 0);
+ ok1(t3.tv_usec == 500000);
+
+ return exit_status();
+}
diff --git a/lib/ccan/time/time.c b/lib/ccan/time/time.c
new file mode 100644
index 0000000000..5e36bf7b48
--- /dev/null
+++ b/lib/ccan/time/time.c
@@ -0,0 +1,108 @@
+/* Licensed under BSD-MIT - see LICENSE file for details */
+#include <ccan/time/time.h>
+#include <stdlib.h>
+#include <assert.h>
+
+struct timeval time_now(void)
+{
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ return now;
+}
+
+bool time_greater(struct timeval a, struct timeval b)
+{
+ if (a.tv_sec > b.tv_sec)
+ return true;
+ else if (a.tv_sec < b.tv_sec)
+ return false;
+
+ return a.tv_usec > b.tv_usec;
+}
+
+bool time_less(struct timeval a, struct timeval b)
+{
+ if (a.tv_sec < b.tv_sec)
+ return true;
+ else if (a.tv_sec > b.tv_sec)
+ return false;
+
+ return a.tv_usec < b.tv_usec;
+}
+
+bool time_eq(struct timeval a, struct timeval b)
+{
+ return a.tv_sec == b.tv_sec && a.tv_usec == b.tv_usec;
+}
+
+struct timeval time_sub(struct timeval recent, struct timeval old)
+{
+ struct timeval diff;
+
+ diff.tv_sec = recent.tv_sec - old.tv_sec;
+ if (old.tv_usec > recent.tv_usec) {
+ diff.tv_sec--;
+ diff.tv_usec = 1000000 + recent.tv_usec - old.tv_usec;
+ } else
+ diff.tv_usec = recent.tv_usec - old.tv_usec;
+
+ assert(diff.tv_sec >= 0);
+ return diff;
+}
+
+struct timeval time_add(struct timeval a, struct timeval b)
+{
+ struct timeval sum;
+
+ sum.tv_sec = a.tv_sec + b.tv_sec;
+ sum.tv_usec = a.tv_usec + b.tv_usec;
+ if (sum.tv_usec > 1000000) {
+ sum.tv_sec++;
+ sum.tv_usec -= 1000000;
+ }
+ return sum;
+}
+
+struct timeval time_divide(struct timeval t, unsigned long div)
+{
+ return time_from_usec(time_to_usec(t) / div);
+}
+
+struct timeval time_multiply(struct timeval t, unsigned long mult)
+{
+ return time_from_usec(time_to_usec(t) * mult);
+}
+
+uint64_t time_to_msec(struct timeval t)
+{
+ uint64_t msec;
+
+ msec = t.tv_usec / 1000 + (uint64_t)t.tv_sec * 1000;
+ return msec;
+}
+
+uint64_t time_to_usec(struct timeval t)
+{
+ uint64_t usec;
+
+ usec = t.tv_usec + (uint64_t)t.tv_sec * 1000000;
+ return usec;
+}
+
+struct timeval time_from_msec(uint64_t msec)
+{
+ struct timeval t;
+
+ t.tv_usec = (msec % 1000) * 1000;
+ t.tv_sec = msec / 1000;
+ return t;
+}
+
+struct timeval time_from_usec(uint64_t usec)
+{
+ struct timeval t;
+
+ t.tv_usec = usec % 1000000;
+ t.tv_sec = usec / 1000000;
+ return t;
+}
diff --git a/lib/ccan/time/time.d b/lib/ccan/time/time.d
new file mode 100644
index 0000000000..d61a6265ea
--- /dev/null
+++ b/lib/ccan/time/time.d
@@ -0,0 +1,25 @@
+ccan/time/time.o: ccan/time/time.c ccan/time/time.h config.h \
+ /usr/include/i386-linux-gnu/sys/time.h /usr/include/features.h \
+ /usr/include/i386-linux-gnu/bits/predefs.h \
+ /usr/include/i386-linux-gnu/sys/cdefs.h \
+ /usr/include/i386-linux-gnu/bits/wordsize.h \
+ /usr/include/i386-linux-gnu/gnu/stubs.h \
+ /usr/include/i386-linux-gnu/gnu/stubs-32.h \
+ /usr/include/i386-linux-gnu/bits/types.h \
+ /usr/include/i386-linux-gnu/bits/typesizes.h /usr/include/time.h \
+ /usr/include/i386-linux-gnu/bits/time.h \
+ /usr/include/i386-linux-gnu/sys/select.h \
+ /usr/include/i386-linux-gnu/bits/select.h \
+ /usr/include/i386-linux-gnu/bits/sigset.h \
+ /usr/lib/gcc/i686-linux-gnu/4.5.4/include/stdint.h /usr/include/stdint.h \
+ /usr/include/i386-linux-gnu/bits/wchar.h \
+ /usr/lib/gcc/i686-linux-gnu/4.5.4/include/stdbool.h \
+ /usr/include/stdlib.h /usr/lib/gcc/i686-linux-gnu/4.5.4/include/stddef.h \
+ /usr/include/i386-linux-gnu/bits/waitflags.h \
+ /usr/include/i386-linux-gnu/bits/waitstatus.h /usr/include/endian.h \
+ /usr/include/i386-linux-gnu/bits/endian.h \
+ /usr/include/i386-linux-gnu/bits/byteswap.h /usr/include/xlocale.h \
+ /usr/include/i386-linux-gnu/sys/types.h \
+ /usr/include/i386-linux-gnu/sys/sysmacros.h \
+ /usr/include/i386-linux-gnu/bits/pthreadtypes.h /usr/include/alloca.h \
+ /usr/include/assert.h
diff --git a/lib/ccan/time/time.h b/lib/ccan/time/time.h
new file mode 100644
index 0000000000..fb2ee459d6
--- /dev/null
+++ b/lib/ccan/time/time.h
@@ -0,0 +1,184 @@
+/* Licensed under BSD-MIT - see LICENSE file for details */
+#ifndef CCAN_TIME_H
+#define CCAN_TIME_H
+#include "config.h"
+#include <sys/time.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+/**
+ * time_now - return the current time
+ *
+ * Example:
+ * printf("Now is %lu seconds since epoch\n", (long)time_now().tv_sec);
+ */
+struct timeval time_now(void);
+
+/**
+ * time_greater - is a after b?
+ * @a: one time.
+ * @b: another time.
+ *
+ * Example:
+ * static bool timed_out(const struct timeval *start)
+ * {
+ * #define TIMEOUT time_from_msec(1000)
+ * return time_greater(time_now(), time_add(*start, TIMEOUT));
+ * }
+ */
+bool time_greater(struct timeval a, struct timeval b);
+
+/**
+ * time_less - is a before b?
+ * @a: one time.
+ * @b: another time.
+ *
+ * Example:
+ * static bool still_valid(const struct timeval *start)
+ * {
+ * #define TIMEOUT time_from_msec(1000)
+ * return time_less(time_now(), time_add(*start, TIMEOUT));
+ * }
+ */
+bool time_less(struct timeval a, struct timeval b);
+
+/**
+ * time_eq - is a equal to b?
+ * @a: one time.
+ * @b: another time.
+ *
+ * Example:
+ * #include <sys/types.h>
+ * #include <sys/wait.h>
+ *
+ * // Can we fork in under a microsecond?
+ * static bool fast_fork(void)
+ * {
+ * struct timeval start = time_now();
+ * if (fork() != 0) {
+ * exit(0);
+ * }
+ * wait(NULL);
+ * return time_eq(start, time_now());
+ * }
+ */
+bool time_eq(struct timeval a, struct timeval b);
+
+/**
+ * time_sub - subtract two times
+ * @recent: the larger (more recent) time.
+ * @old: the smaller (less recent) time.
+ *
+ * This returns a well formed struct timeval.
+ *
+ * Example:
+ * static bool was_recent(const struct timeval *start)
+ * {
+ * return time_sub(time_now(), *start).tv_sec < 1;
+ * }
+ */
+struct timeval time_sub(struct timeval recent, struct timeval old);
+
+/**
+ * time_add - add two times
+ * @a: one time.
+ * @b: another time.
+ *
+ * The times must not overflow, or the results are undefined.
+ *
+ * Example:
+ * // We do one every second.
+ * static struct timeval next_time(void)
+ * {
+ * return time_add(time_now(), time_from_msec(1000));
+ * }
+ */
+struct timeval time_add(struct timeval a, struct timeval b);
+
+/**
+ * time_divide - divide a time by a value.
+ * @t: a time.
+ * @div: number to divide it by.
+ *
+ * Example:
+ * // How long does it take to do a fork?
+ * static struct timeval forking_time(void)
+ * {
+ * struct timeval start = time_now();
+ * unsigned int i;
+ *
+ * for (i = 0; i < 1000; i++) {
+ * if (fork() != 0) {
+ * exit(0);
+ * }
+ * wait(NULL);
+ * }
+ * return time_divide(time_sub(time_now(), start), i);
+ * }
+ */
+struct timeval time_divide(struct timeval t, unsigned long div);
+
+/**
+ * time_multiply - multiply a time by a value.
+ * @t: a time.
+ * @mult: number to multiply it by.
+ *
+ * Example:
+ * ...
+ * printf("Time to do 100000 forks would be %u sec\n",
+ * (unsigned)time_multiply(forking_time(), 1000000).tv_sec);
+ */
+struct timeval time_multiply(struct timeval t, unsigned long mult);
+
+/**
+ * time_to_msec - return number of milliseconds
+ * @t: a time
+ *
+ * It's often more convenient to deal with time values as
+ * milliseconds. Note that this will fit into a 32-bit variable if
+ * it's a time difference of less than ~7 weeks.
+ *
+ * Example:
+ * ...
+ * printf("Forking time is %u msec\n",
+ * (unsigned)time_to_msec(forking_time()));
+ */
+uint64_t time_to_msec(struct timeval t);
+
+/**
+ * time_to_usec - return number of microseconds
+ * @t: a time
+ *
+ * It's often more convenient to deal with time values as
+ * microseconds. Note that this will fit into a 32-bit variable if
+ * it's a time difference of less than ~1 hour.
+ *
+ * Example:
+ * ...
+ * printf("Forking time is %u usec\n",
+ * (unsigned)time_to_usec(forking_time()));
+ *
+ */
+uint64_t time_to_usec(struct timeval t);
+
+/**
+ * time_from_msec - convert milliseconds to a timeval
+ * @msec: time in milliseconds
+ *
+ * Example:
+ * // 1/2 second timeout
+ * #define TIMEOUT time_from_msec(500)
+ */
+struct timeval time_from_msec(uint64_t msec);
+
+/**
+ * time_from_usec - convert microseconds to a timeval
+ * @usec: time in microseconds
+ *
+ * Example:
+ * // 1/2 second timeout
+ * #define TIMEOUT time_from_usec(500000)
+ */
+struct timeval time_from_usec(uint64_t usec);
+
+#endif /* CCAN_TIME_H */
diff --git a/lib/ccan/tlist/LICENSE b/lib/ccan/tlist/LICENSE
new file mode 100644
index 0000000000..cca7fc278f
--- /dev/null
+++ b/lib/ccan/tlist/LICENSE
@@ -0,0 +1,165 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/lib/ccan/tlist/_info b/lib/ccan/tlist/_info
new file mode 100644
index 0000000000..e18e2efb23
--- /dev/null
+++ b/lib/ccan/tlist/_info
@@ -0,0 +1,74 @@
+#include <stdio.h>
+#include <string.h>
+#include "config.h"
+
+/**
+ * tlist - typesafe double linked list routines
+ *
+ * The list header contains routines for manipulating double linked lists;
+ * this extends it so you can create list head types which only accomodate
+ * a specific entry type.
+ *
+ * Example:
+ * #include <err.h>
+ * #include <stdio.h>
+ * #include <stdlib.h>
+ * #include <ccan/tlist/tlist.h>
+ *
+ * // We could use TLIST_TYPE(children, struct child) to define this.
+ * struct tlist_children {
+ * struct list_head raw;
+ * TCON(struct child *canary);
+ * };
+ * struct parent {
+ * const char *name;
+ * struct tlist_children children;
+ * unsigned int num_children;
+ * };
+ *
+ * struct child {
+ * const char *name;
+ * struct list_node list;
+ * };
+ *
+ * int main(int argc, char *argv[])
+ * {
+ * struct parent p;
+ * struct child *c;
+ * unsigned int i;
+ *
+ * if (argc < 2)
+ * errx(1, "Usage: %s parent children...", argv[0]);
+ *
+ * p.name = argv[1];
+ * tlist_init(&p.children);
+ * for (i = 2; i < argc; i++) {
+ * c = malloc(sizeof(*c));
+ * c->name = argv[i];
+ * tlist_add(&p.children, c, list);
+ * p.num_children++;
+ * }
+ *
+ * printf("%s has %u children:", p.name, p.num_children);
+ * tlist_for_each(&p.children, c, list)
+ * printf("%s ", c->name);
+ * printf("\n");
+ * return 0;
+ * }
+ *
+ * License: LGPL
+ * Author: Rusty Russell <rusty@rustcorp.com.au>
+ */
+int main(int argc, char *argv[])
+{
+ if (argc != 2)
+ return 1;
+
+ if (strcmp(argv[1], "depends") == 0) {
+ printf("ccan/list\n");
+ printf("ccan/tcon\n");
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/lib/ccan/tlist/test/compile_fail-tlist_add.c b/lib/ccan/tlist/test/compile_fail-tlist_add.c
new file mode 100644
index 0000000000..1b87bfd119
--- /dev/null
+++ b/lib/ccan/tlist/test/compile_fail-tlist_add.c
@@ -0,0 +1,35 @@
+#include <ccan/tlist/tlist.h>
+
+TLIST_TYPE(children, struct child);
+TLIST_TYPE(cousins, struct cousin);
+
+struct child {
+ const char *name;
+ struct list_node list;
+};
+
+struct cousin {
+ const char *name;
+ struct list_node list;
+};
+
+int main(int argc, char *argv[])
+{
+ struct tlist_children children;
+ struct tlist_cousins cousins;
+ struct child child = { "child" };
+ struct cousin cousin = { "cousin" };
+
+ tlist_init(&children);
+ tlist_init(&cousins);
+ tlist_add(&children, &child, list);
+ tlist_add(&cousins, &cousin, list);
+ tlist_del_from(&cousins, &cousin, list);
+#ifdef FAIL
+#if !HAVE_FLEXIBLE_ARRAY_MEMBER
+#error Need flexible array members to check type
+#endif
+ tlist_add(&children, &cousin, list);
+#endif
+ return 0;
+}
diff --git a/lib/ccan/tlist/test/compile_fail-tlist_add_tail.c b/lib/ccan/tlist/test/compile_fail-tlist_add_tail.c
new file mode 100644
index 0000000000..33dff3d8eb
--- /dev/null
+++ b/lib/ccan/tlist/test/compile_fail-tlist_add_tail.c
@@ -0,0 +1,35 @@
+#include <ccan/tlist/tlist.h>
+
+TLIST_TYPE(children, struct child);
+TLIST_TYPE(cousins, struct cousin);
+
+struct child {
+ const char *name;
+ struct list_node list;
+};
+
+struct cousin {
+ const char *name;
+ struct list_node list;
+};
+
+int main(int argc, char *argv[])
+{
+ struct tlist_children children;
+ struct tlist_cousins cousins;
+ struct child child = { "child" };
+ struct cousin cousin = { "cousin" };
+
+ tlist_init(&children);
+ tlist_init(&cousins);
+ tlist_add(&children, &child, list);
+ tlist_add(&cousins, &cousin, list);
+ tlist_del_from(&cousins, &cousin, list);
+#ifdef FAIL
+#if !HAVE_FLEXIBLE_ARRAY_MEMBER
+#error Need flexible array members to check type
+#endif
+ tlist_add_tail(&children, &cousin, list);
+#endif
+ return 0;
+}
diff --git a/lib/ccan/tlist/test/compile_fail-tlist_del_from.c b/lib/ccan/tlist/test/compile_fail-tlist_del_from.c
new file mode 100644
index 0000000000..d06a72fbfa
--- /dev/null
+++ b/lib/ccan/tlist/test/compile_fail-tlist_del_from.c
@@ -0,0 +1,34 @@
+#include <ccan/tlist/tlist.h>
+
+TLIST_TYPE(children, struct child);
+TLIST_TYPE(cousins, struct cousin);
+
+struct child {
+ const char *name;
+ struct list_node list;
+};
+
+struct cousin {
+ const char *name;
+ struct list_node list;
+};
+
+int main(int argc, char *argv[])
+{
+ struct tlist_children children;
+ struct tlist_cousins cousins;
+ struct child child = { "child" };
+ struct cousin cousin = { "cousin" };
+
+ tlist_init(&children);
+ tlist_init(&cousins);
+ tlist_add(&children, &child, list);
+ tlist_add(&cousins, &cousin, list);
+#ifdef FAIL
+#if !HAVE_FLEXIBLE_ARRAY_MEMBER
+#error Need flexible array members to check type
+#endif
+ tlist_del_from(&children, &cousin, list);
+#endif
+ return 0;
+}
diff --git a/lib/ccan/tlist/test/compile_fail-tlist_for_each.c b/lib/ccan/tlist/test/compile_fail-tlist_for_each.c
new file mode 100644
index 0000000000..1b2fb6882f
--- /dev/null
+++ b/lib/ccan/tlist/test/compile_fail-tlist_for_each.c
@@ -0,0 +1,34 @@
+#include <ccan/tlist/tlist.h>
+
+TLIST_TYPE(children, struct child);
+
+struct child {
+ const char *name;
+ struct list_node list;
+};
+
+struct cousin {
+ const char *name;
+ struct list_node list;
+};
+
+int main(int argc, char *argv[])
+{
+ struct tlist_children children;
+ struct child child = { "child" };
+#ifdef FAIL
+#if !HAVE_FLEXIBLE_ARRAY_MEMBER
+#error Need flexible array members to check type
+#endif
+ struct cousin *c;
+#else
+ struct child *c;
+#endif
+
+ tlist_init(&children);
+ tlist_add(&children, &child, list);
+
+ tlist_for_each(&children, c, list)
+ (void) c; /* Suppress unused-but-set-variable warning. */
+ return 0;
+}
diff --git a/lib/ccan/tlist/test/compile_fail-tlist_for_each_safe.c b/lib/ccan/tlist/test/compile_fail-tlist_for_each_safe.c
new file mode 100644
index 0000000000..651c6cefd6
--- /dev/null
+++ b/lib/ccan/tlist/test/compile_fail-tlist_for_each_safe.c
@@ -0,0 +1,33 @@
+#include <ccan/tlist/tlist.h>
+
+TLIST_TYPE(children, struct child);
+
+struct child {
+ const char *name;
+ struct list_node list;
+};
+
+struct cousin {
+ const char *name;
+ struct list_node list;
+};
+
+int main(int argc, char *argv[])
+{
+ struct tlist_children children;
+ struct child child = { "child" };
+#ifdef FAIL
+#if !HAVE_FLEXIBLE_ARRAY_MEMBER
+#error Need flexible array members to check type
+#endif
+ struct cousin *c, *n;
+#else
+ struct child *c, *n;
+#endif
+
+ tlist_init(&children);
+ tlist_add(&children, &child, list);
+
+ tlist_for_each_safe(&children, c, n, list);
+ return 0;
+}
diff --git a/lib/ccan/tlist/test/compile_fail-tlist_tail.c b/lib/ccan/tlist/test/compile_fail-tlist_tail.c
new file mode 100644
index 0000000000..48f394446e
--- /dev/null
+++ b/lib/ccan/tlist/test/compile_fail-tlist_tail.c
@@ -0,0 +1,31 @@
+#include <ccan/tlist/tlist.h>
+
+TLIST_TYPE(children, struct child);
+
+struct child {
+ const char *name;
+ struct list_node list;
+};
+
+struct cousin {
+ const char *name;
+ struct list_node list;
+};
+
+int main(int argc, char *argv[])
+{
+ struct tlist_children children;
+ struct child child = { "child" };
+#ifdef FAIL
+ struct cousin *c;
+#else
+ struct child *c;
+#endif
+
+ tlist_init(&children);
+ tlist_add(&children, &child, list);
+
+ c = tlist_tail(&children, list);
+ (void) c; /* Suppress unused-but-set-variable warning. */
+ return 0;
+}
diff --git a/lib/ccan/tlist/test/compile_fail-tlist_top.c b/lib/ccan/tlist/test/compile_fail-tlist_top.c
new file mode 100644
index 0000000000..21651400ef
--- /dev/null
+++ b/lib/ccan/tlist/test/compile_fail-tlist_top.c
@@ -0,0 +1,31 @@
+#include <ccan/tlist/tlist.h>
+
+TLIST_TYPE(children, struct child);
+
+struct child {
+ const char *name;
+ struct list_node list;
+};
+
+struct cousin {
+ const char *name;
+ struct list_node list;
+};
+
+int main(int argc, char *argv[])
+{
+ struct tlist_children children;
+ struct child child = { "child" };
+#ifdef FAIL
+ struct cousin *c;
+#else
+ struct child *c;
+#endif
+
+ tlist_init(&children);
+ tlist_add(&children, &child, list);
+
+ c = tlist_top(&children, list);
+ (void) c; /* Suppress unused-but-set-variable warning. */
+ return 0;
+}
diff --git a/lib/ccan/tlist/test/run.c b/lib/ccan/tlist/test/run.c
new file mode 100644
index 0000000000..95b02ebe21
--- /dev/null
+++ b/lib/ccan/tlist/test/run.c
@@ -0,0 +1,147 @@
+#define CCAN_LIST_DEBUG 1
+#include <ccan/tlist/tlist.h>
+#include <ccan/tap/tap.h>
+
+TLIST_TYPE(children, struct child);
+
+struct parent {
+ const char *name;
+ struct tlist_children children;
+ unsigned int num_children;
+};
+
+struct child {
+ const char *name;
+ struct list_node list;
+};
+
+int main(int argc, char *argv[])
+{
+ struct parent parent;
+ struct child c1, c2, c3, *c, *n;
+ unsigned int i;
+ struct tlist_children tlist = TLIST_INIT(tlist);
+
+ plan_tests(48);
+ /* Test TLIST_INIT, and tlist_empty */
+ ok1(tlist_empty(&tlist));
+ ok1(tlist_check(&tlist, NULL));
+
+ parent.num_children = 0;
+ tlist_init(&parent.children);
+ /* Test tlist_init */
+ ok1(tlist_empty(&parent.children));
+ ok1(tlist_check(&parent.children, NULL));
+
+ c2.name = "c2";
+ tlist_add(&parent.children, &c2, list);
+ /* Test tlist_add and !tlist_empty. */
+ ok1(!tlist_empty(&parent.children));
+ ok1(c2.list.next == &parent.children.raw.n);
+ ok1(c2.list.prev == &parent.children.raw.n);
+ ok1(parent.children.raw.n.next == &c2.list);
+ ok1(parent.children.raw.n.prev == &c2.list);
+ /* Test tlist_check */
+ ok1(tlist_check(&parent.children, NULL));
+
+ c1.name = "c1";
+ tlist_add(&parent.children, &c1, list);
+ /* Test list_add and !list_empty. */
+ ok1(!tlist_empty(&parent.children));
+ ok1(c2.list.next == &parent.children.raw.n);
+ ok1(c2.list.prev == &c1.list);
+ ok1(parent.children.raw.n.next == &c1.list);
+ ok1(parent.children.raw.n.prev == &c2.list);
+ ok1(c1.list.next == &c2.list);
+ ok1(c1.list.prev == &parent.children.raw.n);
+ /* Test tlist_check */
+ ok1(tlist_check(&parent.children, NULL));
+
+ c3.name = "c3";
+ tlist_add_tail(&parent.children, &c3, list);
+ /* Test list_add_tail and !list_empty. */
+ ok1(!tlist_empty(&parent.children));
+ ok1(parent.children.raw.n.next == &c1.list);
+ ok1(parent.children.raw.n.prev == &c3.list);
+ ok1(c1.list.next == &c2.list);
+ ok1(c1.list.prev == &parent.children.raw.n);
+ ok1(c2.list.next == &c3.list);
+ ok1(c2.list.prev == &c1.list);
+ ok1(c3.list.next == &parent.children.raw.n);
+ ok1(c3.list.prev == &c2.list);
+ /* Test tlist_check */
+ ok1(tlist_check(&parent.children, NULL));
+
+ /* Test tlist_top */
+ ok1(tlist_top(&parent.children, list) == &c1);
+
+ /* Test list_tail */
+ ok1(tlist_tail(&parent.children, list) == &c3);
+
+ /* Test tlist_for_each. */
+ i = 0;
+ tlist_for_each(&parent.children, c, list) {
+ switch (i++) {
+ case 0:
+ ok1(c == &c1);
+ break;
+ case 1:
+ ok1(c == &c2);
+ break;
+ case 2:
+ ok1(c == &c3);
+ break;
+ }
+ if (i > 2)
+ break;
+ }
+ ok1(i == 3);
+
+ /* Test tlist_for_each_rev. */
+ i = 0;
+ tlist_for_each_rev(&parent.children, c, list) {
+ switch (i++) {
+ case 0:
+ ok1(c == &c3);
+ break;
+ case 1:
+ ok1(c == &c2);
+ break;
+ case 2:
+ ok1(c == &c1);
+ break;
+ }
+ if (i > 2)
+ break;
+ }
+ ok1(i == 3);
+
+ /* Test tlist_for_each_safe, tlist_del and tlist_del_from. */
+ i = 0;
+ tlist_for_each_safe(&parent.children, c, n, list) {
+ switch (i++) {
+ case 0:
+ ok1(c == &c1);
+ tlist_del(c, list);
+ break;
+ case 1:
+ ok1(c == &c2);
+ tlist_del_from(&parent.children, c, list);
+ break;
+ case 2:
+ ok1(c == &c3);
+ tlist_del_from(&parent.children, c, list);
+ break;
+ }
+ ok1(tlist_check(&parent.children, NULL));
+ if (i > 2)
+ break;
+ }
+ ok1(i == 3);
+ ok1(tlist_empty(&parent.children));
+
+ /* Test list_top/list_tail on empty list. */
+ ok1(tlist_top(&parent.children, list) == (struct child *)NULL);
+ ok1(tlist_tail(&parent.children, list) == (struct child *)NULL);
+ return exit_status();
+}
diff --git a/lib/ccan/tlist/tlist.h b/lib/ccan/tlist/tlist.h
new file mode 100644
index 0000000000..1ce0b85ed9
--- /dev/null
+++ b/lib/ccan/tlist/tlist.h
@@ -0,0 +1,265 @@
+/* Licensed under LGPL - see LICENSE file for details */
+#ifndef CCAN_TLIST_H
+#define CCAN_TLIST_H
+#include <ccan/list/list.h>
+#include <ccan/tcon/tcon.h>
+
+/**
+ * TLIST_TYPE - declare a typed list type (struct tlist)
+ * @suffix: the name to use (struct tlist_@suffix)
+ * @type: the type the list will contain (void for any type)
+ *
+ * This declares a structure "struct tlist_@suffix" to use for
+ * lists containing this type. The actual list can be accessed using
+ * ".raw" or tlist_raw().
+ *
+ * Example:
+ * // Defines struct tlist_children
+ * TLIST_TYPE(children, struct child);
+ * struct parent {
+ * const char *name;
+ * struct tlist_children children;
+ * unsigned int num_children;
+ * };
+ *
+ * struct child {
+ * const char *name;
+ * struct list_node list;
+ * };
+ */
+#define TLIST_TYPE(suffix, type) \
+ struct tlist_##suffix { \
+ struct list_head raw; \
+ TCON(type *canary); \
+ }
+
+/**
+ * TLIST_INIT - initalizer for an empty tlist
+ * @name: the name of the list.
+ *
+ * Explicit initializer for an empty list.
+ *
+ * See also:
+ * tlist_init()
+ *
+ * Example:
+ * static struct tlist_children my_list = TLIST_INIT(my_list);
+ */
+#define TLIST_INIT(name) { LIST_HEAD_INIT(name.raw) }
+
+/**
+ * tlist_check - check head of a list for consistency
+ * @h: the tlist_head
+ * @abortstr: the location to print on aborting, or NULL.
+ *
+ * Because list_nodes have redundant information, consistency checking between
+ * the back and forward links can be done. This is useful as a debugging check.
+ * If @abortstr is non-NULL, that will be printed in a diagnostic if the list
+ * is inconsistent, and the function will abort.
+ *
+ * Returns non-NULL if the list is consistent, NULL otherwise (it
+ * can never return NULL if @abortstr is set).
+ *
+ * See also: list_check()
+ *
+ * Example:
+ * static void dump_parent(struct parent *p)
+ * {
+ * struct child *c;
+ *
+ * printf("%s (%u children):\n", p->name, p->num_children);
+ * tlist_check(&p->children, "bad child list");
+ * tlist_for_each(&p->children, c, list)
+ * printf(" -> %s\n", c->name);
+ * }
+ */
+#define tlist_check(h, abortstr) \
+ list_check(&(h)->raw, (abortstr))
+
+/**
+ * tlist_init - initialize a tlist
+ * @h: the tlist to set to the empty list
+ *
+ * Example:
+ * ...
+ * struct parent *parent = malloc(sizeof(*parent));
+ *
+ * tlist_init(&parent->children);
+ * parent->num_children = 0;
+ */
+#define tlist_init(h) list_head_init(&(h)->raw)
+
+/**
+ * tlist_raw - unwrap the typed list and check the type
+ * @h: the tlist
+ * @expr: the expression to check the type against (not evaluated)
+ *
+ * This macro usually causes the compiler to emit a warning if the
+ * variable is of an unexpected type. It is used internally where we
+ * need to access the raw underlying list.
+ */
+#define tlist_raw(h, expr) (&tcon_check((h), canary, (expr))->raw)
+
+/**
+ * tlist_add - add an entry at the start of a linked list.
+ * @h: the tlist to add the node to
+ * @n: the entry to add to the list.
+ * @member: the member of n to add to the list.
+ *
+ * The entry's list_node does not need to be initialized; it will be
+ * overwritten.
+ * Example:
+ * struct child *child = malloc(sizeof(*child));
+ *
+ * child->name = "marvin";
+ * tlist_add(&parent->children, child, list);
+ * parent->num_children++;
+ */
+#define tlist_add(h, n, member) list_add(tlist_raw((h), (n)), &(n)->member)
+
+/**
+ * tlist_add_tail - add an entry at the end of a linked list.
+ * @h: the tlist to add the node to
+ * @n: the entry to add to the list.
+ * @member: the member of n to add to the list.
+ *
+ * The list_node does not need to be initialized; it will be overwritten.
+ * Example:
+ * tlist_add_tail(&parent->children, child, list);
+ * parent->num_children++;
+ */
+#define tlist_add_tail(h, n, member) \
+ list_add_tail(tlist_raw((h), (n)), &(n)->member)
+
+/**
+ * tlist_del_from - delete an entry from a linked list.
+ * @h: the tlist @n is in
+ * @n: the entry to delete
+ * @member: the member of n to remove from the list.
+ *
+ * This explicitly indicates which list a node is expected to be in,
+ * which is better documentation and can catch more bugs.
+ *
+ * Note that this leaves @n->@member in an undefined state; it
+ * can be added to another list, but not deleted again.
+ *
+ * See also: tlist_del()
+ *
+ * Example:
+ * tlist_del_from(&parent->children, child, list);
+ * parent->num_children--;
+ */
+#define tlist_del_from(h, n, member) \
+ list_del_from(tlist_raw((h), (n)), &(n)->member)
+
+/**
+ * tlist_del - delete an entry from an unknown linked list.
+ * @n: the entry to delete from the list.
+ * @member: the member of @n which is in the list.
+ *
+ * Example:
+ * tlist_del(child, list);
+ * parent->num_children--;
+ */
+#define tlist_del(n, member) \
+ list_del(&(n)->member)
+
+/**
+ * tlist_empty - is a list empty?
+ * @h: the tlist
+ *
+ * If the list is empty, returns true.
+ *
+ * Example:
+ * assert(tlist_empty(&parent->children) == (parent->num_children == 0));
+ */
+#define tlist_empty(h) list_empty(&(h)->raw)
+
+/**
+ * tlist_top - get the first entry in a list
+ * @h: the tlist
+ * @member: the list_node member of the type
+ *
+ * If the list is empty, returns NULL.
+ *
+ * Example:
+ * struct child *first;
+ * first = tlist_top(&parent->children, list);
+ */
+#define tlist_top(h, member) \
+ ((tcon_type((h), canary)) \
+ list_top_(&(h)->raw, \
+ (char *)(&(h)->_tcon[0].canary->member) - \
+ (char *)((h)->_tcon[0].canary)))
+
+/**
+ * tlist_tail - get the last entry in a list
+ * @h: the tlist
+ * @member: the list_node member of the type
+ *
+ * If the list is empty, returns NULL.
+ *
+ * Example:
+ * struct child *last;
+ * last = tlist_tail(&parent->children, list);
+ */
+#define tlist_tail(h, member) \
+ ((tcon_type((h), canary)) \
+ list_tail_(&(h)->raw, \
+ (char *)(&(h)->_tcon[0].canary->member) - \
+ (char *)((h)->_tcon[0].canary)))
+
+/**
+ * tlist_for_each - iterate through a list.
+ * @h: the tlist
+ * @i: an iterator of suitable type for this list.
+ * @member: the list_node member of @i
+ *
+ * This is a convenient wrapper to iterate @i over the entire list. It's
+ * a for loop, so you can break and continue as normal.
+ *
+ * Example:
+ * tlist_for_each(&parent->children, child, list)
+ * printf("Name: %s\n", child->name);
+ */
+#define tlist_for_each(h, i, member) \
+ list_for_each(tlist_raw((h), (i)), (i), member)
+
+/**
+ * tlist_for_each - iterate through a list backwards.
+ * @h: the tlist
+ * @i: an iterator of suitable type for this list.
+ * @member: the list_node member of @i
+ *
+ * This is a convenient wrapper to iterate @i over the entire list. It's
+ * a for loop, so you can break and continue as normal.
+ *
+ * Example:
+ * tlist_for_each_rev(&parent->children, child, list)
+ * printf("Name: %s\n", child->name);
+ */
+#define tlist_for_each_rev(h, i, member) \
+ list_for_each_rev(tlist_raw((h), (i)), (i), member)
+
+/**
+ * tlist_for_each_safe - iterate through a list, maybe during deletion
+ * @h: the tlist
+ * @i: an iterator of suitable type for this list.
+ * @nxt: another iterator to store the next entry.
+ * @member: the list_node member of the structure
+ *
+ * This is a convenient wrapper to iterate @i over the entire list. It's
+ * a for loop, so you can break and continue as normal. The extra variable
+ * @nxt is used to hold the next element, so you can delete @i from the list.
+ *
+ * Example:
+ * struct child *next;
+ * tlist_for_each_safe(&parent->children, child, next, list) {
+ * tlist_del(child, list);
+ * parent->num_children--;
+ * }
+ */
+#define tlist_for_each_safe(h, i, nxt, member) \
+ list_for_each_safe(tlist_raw((h), (i)), (i), (nxt), member)
+
+#endif /* CCAN_TLIST_H */