Integration of UTS Namespace Testcases to LTP as submitted by <risrajak@linux.vnet.ibm.com>
diff --git a/testcases/kernel/containers/libclone/libclone.c b/testcases/kernel/containers/libclone/libclone.c
new file mode 100644
index 0000000..f555c84
--- /dev/null
+++ b/testcases/kernel/containers/libclone/libclone.c
@@ -0,0 +1,132 @@
+#include "libclone.h"
+
+/* Serge: should I be passing in strings for error messages? */
+
+int do_clone_tests(unsigned long clone_flags,
+ int(*fn1)(void *arg), void *arg1,
+ int(*fn2)(void *arg), void *arg2)
+{
+ int ret;
+ void *childstack, *stack = malloc(getpagesize());
+
+ if (!stack) {
+ perror("malloc");
+ return -1;
+ }
+
+ childstack = stack + getpagesize();
+
+ ret = clone(fn1, childstack, clone_flags | SIGCHLD, arg1);
+ if (ret == -1) {
+ perror("clone");
+ free(stack);
+ return -1;
+ }
+ if (fn2)
+ ret = fn2(arg2);
+ else
+ ret = 0;
+
+ return ret;
+}
+
+int do_unshare_tests(unsigned long clone_flags,
+ int (*fn1)(void *arg), void *arg1,
+ int (*fn2)(void *arg), void *arg2)
+{
+ int pid, ret = 0;
+ int retpipe[2];
+ char buf[2];
+
+ if (pipe(retpipe) == -1) {
+ perror("pipe");
+ return -1;
+ }
+ pid = fork();
+ if (pid == -1) {
+ perror("fork");
+ close(retpipe[0]);
+ close(retpipe[1]);
+ return -1;
+ }
+ if (pid == 0) {
+ close(retpipe[0]);
+ ret = syscall(SYS_unshare, clone_flags);
+ if (ret == -1) {
+ write(retpipe[1], "0", 2);
+ close(retpipe[1]);
+ perror("unshare");
+ exit(1);
+ } else
+ write(retpipe[1], "1", 2);
+ close(retpipe[1]);
+ ret = fn1(arg1);
+ exit(ret);
+ } else {
+ close(retpipe[1]);
+ read(retpipe[0], &buf, 2);
+ close(retpipe[0]);
+ if (*buf == '0')
+ return -1;
+ if (fn2)
+ ret = fn2(arg2);
+ }
+
+ return ret;
+}
+
+int do_plain_tests(int (*fn1)(void *arg), void *arg1,
+ int (*fn2)(void *arg), void *arg2)
+{
+ int ret = 0, pid;
+
+ pid = fork();
+ if (pid == -1) {
+ perror("fork");
+ return -1;
+ }
+ if (pid == 0)
+ return fn1(arg1);
+ if (fn2)
+ ret = fn2(arg2);
+ return ret;
+}
+
+int do_clone_unshare_test(int use_clone, unsigned long clone_flags,
+ int (*fn1)(void *arg), void *arg1)
+{
+ switch (use_clone) {
+ case T_NONE:
+ return do_plain_tests(fn1, arg1, NULL, NULL);
+ case T_CLONE:
+ return do_clone_tests(clone_flags, fn1, arg1, NULL, NULL);
+ case T_UNSHARE:
+ return do_unshare_tests(clone_flags, fn1, arg1, NULL, NULL);
+ default:
+ printf("%s: bad use_clone option: %d\n", __FUNCTION__,
+ use_clone);
+ return -1;
+ }
+}
+
+
+/*
+ * Run fn1 in a unshared environmnent, and fn2 in the original context
+ */
+int do_clone_unshare_tests(int use_clone, unsigned long clone_flags,
+ int (*fn1)(void *arg), void *arg1,
+ int (*fn2)(void *arg), void *arg2)
+{
+ switch (use_clone) {
+ case T_NONE:
+ return do_plain_tests(fn1, arg1, fn2, arg2);
+ case T_CLONE:
+ return do_clone_tests(clone_flags, fn1, arg1, fn2, arg2);
+ case T_UNSHARE:
+ return do_unshare_tests(clone_flags, fn1, arg1, fn2, arg2);
+ default:
+ printf("%s: bad use_clone option: %d\n", __FUNCTION__,
+ use_clone);
+ return -1;
+ }
+}