Integration of UTS Namespace Testcases to LTP as submitted by <risrajak@linux.vnet.ibm.com>
diff --git a/README b/README
index 55b6dbf..777887f 100644
--- a/README
+++ b/README
@@ -78,6 +78,12 @@
that we found but haven't integrated into LTP yet. Feel free to suggest
new snippets to be added, or take one of these and finish it off.
+testcases/kernel/containers/*
+ Contains all the testcases related to container functionality ( e.g: utsname etc..)
+ For further information on the each of the container functionality refer
+ the following file: testcases/kernel/containers/README
+
+
Warning!
--------
Be careful with these tests!
diff --git a/runltp b/runltp
index d335de0..3a9d0d8 100755
--- a/runltp
+++ b/runltp
@@ -283,7 +283,8 @@
${LTPROOT}/runtest/fsx ${LTPROOT}/runtest/dio \
${LTPROOT}/runtest/mm ${LTPROOT}/runtest/ipc \
${LTPROOT}/runtest/sched ${LTPROOT}/runtest/math \
- ${LTPROOT}/runtest/nptl ${LTPROOT}/runtest/pty
+ ${LTPROOT}/runtest/nptl ${LTPROOT}/runtest/pty \
+ ${LTPROOT}/runtest/containers
do
[ -a "$SCENFILES" ] || \
{
diff --git a/runtest/containers b/runtest/containers
new file mode 100644
index 0000000..5665ec7
--- /dev/null
+++ b/runtest/containers
@@ -0,0 +1,2 @@
+#DESCRIPTION:Resource namespaces
+Containers container_test.sh
diff --git a/testcases/kernel/Makefile b/testcases/kernel/Makefile
index 8362633..511849c 100644
--- a/testcases/kernel/Makefile
+++ b/testcases/kernel/Makefile
@@ -1,4 +1,4 @@
-SUBDIRS = include fs io ipc mem pty sched security syscalls
+SUBDIRS = containers include fs io ipc mem pty sched security syscalls
UCLINUX_SUBDIRS = syscalls
all:
diff --git a/testcases/kernel/containers/Makefile b/testcases/kernel/containers/Makefile
new file mode 100644
index 0000000..32a2c70
--- /dev/null
+++ b/testcases/kernel/containers/Makefile
@@ -0,0 +1,14 @@
+SUBDIRS = libclone utsname
+
+all noltp noltp_check:
+ @set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i $@; done
+
+install:
+ @set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i install ; done
+ chmod ugo+x container_test.sh
+ ln -f container_test.sh ../../bin/container_test.sh
+
+clean:
+ @set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i clean ; done
+
+
diff --git a/testcases/kernel/containers/README b/testcases/kernel/containers/README
new file mode 100644
index 0000000..cefc4c4
--- /dev/null
+++ b/testcases/kernel/containers/README
@@ -0,0 +1,12 @@
+CONTAINER TESTS AUTOMATION SUITE
+----------------------------
+
+The container test automation suite helps run the container functionality
+(e.g: utsname etc..) tests and report results. Please refer the following
+each functionality README file for detail:
+
+utsname/*
+ Contains all the testcases related to utsname tests.
+libclone/*
+ Contains the library API for clone() .
+
diff --git a/testcases/kernel/containers/container_test.sh b/testcases/kernel/containers/container_test.sh
new file mode 100755
index 0000000..a045286
--- /dev/null
+++ b/testcases/kernel/containers/container_test.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+#
+# This test performs capability tests for file operations.
+#
+# Copyright 2007 IBM
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+
+#check_utsns_enabled
+#if [ $? -eq 0 ]; then
+ echo "Running utsns tests."
+ runutstest.sh
+#else
+# echo "Uts namespaces not enabled in kernel. Not running utsns tests."
+#fi
+
+#check_pidns_enabled
+#if [ $? -eq 0 ]; then
+# echo "Running pidns tests."
+# runpidnstest.sh
+#else
+ #echo "Process id namespaces not enabled in kernel. Not running pidns tests."
+#fi
+
+#check_userns_enabled
+#if [ $? -eq 0 ]; then
+ #echo "Running userns tests."
+# userns_mounts unshare
+# userns_mounts clone
+# userns_sigio none
+# userns_sigio unshare
+# userns_sigio clone
+# for i in `seq 1 4`; do
+# userns_sigpending $i
+# done
+#else
+ #echo "User namespaces not enabled in kernel. Not running userns tests."
+#fi
diff --git a/testcases/kernel/containers/libclone/Makefile b/testcases/kernel/containers/libclone/Makefile
new file mode 100755
index 0000000..c03cf91
--- /dev/null
+++ b/testcases/kernel/containers/libclone/Makefile
@@ -0,0 +1,15 @@
+TARGET=libclone.a
+SRCS=$(wildcard *.c)
+OBJS=$(patsubst %.c,%.o,$(SRCS))
+
+all noltp : $(TARGET)
+
+$(TARGET): $(OBJS)
+ $(AR) -cr $@ $^
+
+clean:
+ rm -f $(TARGET) $(OBJS)
+
+noltp_check: noltp
+
+install:
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;
+ }
+}
diff --git a/testcases/kernel/containers/libclone/libclone.h b/testcases/kernel/containers/libclone/libclone.h
new file mode 100644
index 0000000..9d3ce4a
--- /dev/null
+++ b/testcases/kernel/containers/libclone/libclone.h
@@ -0,0 +1,85 @@
+#ifndef __LIBCLONE_H
+#define __LIBCLONE_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sched.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <libgen.h>
+#include <sched.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <signal.h>
+
+#define T_UNSHARE 0
+#define T_CLONE 1
+#define T_NONE 2
+
+#ifndef SYS_unshare
+#ifdef __NR_unshare
+#define SYS_unshare __NR_unshare
+#elif __i386__
+#define SYS_unshare 310
+#elif __ia64__
+#define SYS_unshare 1296
+#elif __x86_64__
+#define SYS_unshare 272
+#elif __s390x__
+#define SYS_unshare 303
+#elif __powerpc__
+#define SYS_unshare 282
+#else
+#error "unshare not supported on this architecure."
+#endif
+#endif
+
+#ifndef CLONE_NEWUTS
+#define CLONE_NEWUTS 0x04000000
+#endif
+
+#ifndef CLONE_NEWIPC
+#define CLONE_NEWIPC 0x08000000
+#endif
+
+#ifndef CLONE_NEWUSER
+#define CLONE_NEWUSER 0x10000000
+#endif
+
+#ifndef CLONE_NEWNET2
+#define CLONE_NEWNET2 0x20000000
+#endif
+
+#ifndef CLONE_NEWNET3
+#define CLONE_NEWNET3 0x40000000
+#endif
+
+#ifndef CLONE_NEWPID
+#define CLONE_NEWPID 0x80000000
+#endif
+
+/*
+ * Run fn1 in a unshared environmnent, and fn2 in the original context
+ * Fn2 may be NULL.
+ */
+
+int do_clone_tests(unsigned long clone_flags,
+ int(*fn1)(void *arg), void *arg1,
+ int(*fn2)(void *arg), void *arg2);
+
+int do_unshare_tests(unsigned long clone_flags,
+ int (*fn1)(void *arg), void *arg1,
+ int (*fn2)(void *arg), void *arg2);
+
+int do_fork_tests(int (*fn1)(void *arg), void *arg1,
+ int (*fn2)(void *arg), void *arg2);
+
+int do_clone_unshare_test(int use_clone, unsigned long clone_flags,
+ int (*fn1)(void *arg), void *arg1);
+
+int do_clone_unshare_tests(int use_clone, unsigned long clone_flags,
+ int (*fn1)(void *arg), void *arg1,
+ int (*fn2)(void *arg), void *arg2);
+
+#endif
diff --git a/testcases/kernel/containers/utsname/Makefile b/testcases/kernel/containers/utsname/Makefile
new file mode 100755
index 0000000..7a18a82
--- /dev/null
+++ b/testcases/kernel/containers/utsname/Makefile
@@ -0,0 +1,24 @@
+CC=gcc
+
+CFLAGS += -I../../../../include -I../libclone -Wall
+LDLIBS += -L../../../../lib -L../libclone ../libclone/libclone.a -lltp
+
+SRCS = $(wildcard *.c)
+TARGETS = $(patsubst %.c,%,$(SRCS))
+NOLTP_TARGETS = $(patsubst %.c,%_noltp,$(SRCS))
+
+%_noltp : %.c
+ $(CC) -g -DNO_LTP -o $@ $< ../libclone/libclone.a
+
+all: $(TARGETS)
+
+noltp: $(NOLTP_TARGETS)
+
+clean:
+ rm -f $(TARGETS) *.o $(NOLTP_TARGETS)
+
+install:
+ @set -e; for i in $(TARGETS) runutstest.sh check_utsns_enabled; do ln -f $$i ../../../bin/$$i ; chmod +x runutstest.sh ; done
+
+noltp_check: noltp
+ ./runtests_noltp.sh
diff --git a/testcases/kernel/containers/utsname/README b/testcases/kernel/containers/utsname/README
new file mode 100644
index 0000000..bc97cd9
--- /dev/null
+++ b/testcases/kernel/containers/utsname/README
@@ -0,0 +1,33 @@
+This contains five tests for the uts namespace unsharing functionality.
+
+To enable this functionality, you currently must use a -mm kernel (see
+kernel.org). Then to run these tests, just type
+
+ sh runutstest.sh
+
+The tests are intended to do the following:
+
+test 1: check that after fork, two children see the same utsname
+ P1: A=gethostname
+ P2: B=gethostname
+ Ensure(A==B)
+test 2: check that after fork, two children are in the same utsname namespace.
+ P1: sethostname(newname); A=gethostname
+ P2: (wait); B=gethostname
+ Ensure (A==B)
+
+test 3: check that after unshare, processes are in different utsname namespaces.
+ P1: A=gethostname; unshare(utsname); sethostname(newname); C=gethostname
+ P2: B=gethostname; (wait); (wait); D=gethostname
+ Ensure (A==B && A==D && C!=D)
+
+test 4: similar to test 3, but other child changes hostname.
+ P1: A=gethostname; unshare(utsname); (wait); C=gethostname
+ P2: B=gethostname; (wait); sethostname(newname); D=gethostname
+ Ensure (A==B && A==C && C!=D)
+
+test 5: check that unsharing utsname without required permissions (CAP_SYS_AUDIT)
+ fails.
+ P1: A=gethostname; unshare(utsname) without suff. perms; (wait); C=gethostname
+ P2: B=gethostname; (wait); sethostname(newname); D=gethostname
+ Ensure (A==B==C==D) and state is ok.
diff --git a/testcases/kernel/containers/utsname/check_utsns_enabled.c b/testcases/kernel/containers/utsname/check_utsns_enabled.c
new file mode 100644
index 0000000..befa673
--- /dev/null
+++ b/testcases/kernel/containers/utsname/check_utsns_enabled.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2007 IBM
+ * Author: Serge Hallyn <serue@us.ibm.com>
+ *
+ * uts namespaces were introduced around 2.6.19. Kernels before that,
+ * assume they are not enabled. Kernels after that, check for -EINVAL
+ * when trying to use CLONE_NEWUTS.
+ */
+
+#include <sys/utsname.h>
+#include <sched.h>
+#include <stdio.h>
+#include "../libclone/libclone.h"
+#include "test.h"
+
+int dummy(void *v)
+{
+ return 0;
+}
+
+/*
+ * Not really expecting anyone to use this on a 2.6.19-rc kernel,
+ * else we may get some false positives here.
+ */
+#if 0
+int kernel_version_newenough()
+{
+ int ret;
+ struct utsname buf;
+ char *s;
+ int maj, min, micro;
+
+ ret = uname(&buf);
+ if (ret == -1) {
+ perror("uname");
+ return 0;
+ }
+ s = buf.release;
+ sscanf(s, "%d.%d.%d", &maj, &min, µ);
+ if (maj < 2)
+ return 0;
+ if (min < 6)
+ return 0;
+ if (micro < 19)
+ return 0;
+ return 1;
+}
+#endif /* Library is already provided by LTP*/
+int main()
+{
+ void *childstack, *stack;
+ int pid;
+
+ //if (!kernel_version_newenough())
+ if (tst_kvercmp(2,6,19) < 0)
+ return 1;
+ stack = malloc(getpagesize());
+ if (!stack) {
+ perror("malloc");
+ return 2;
+ }
+
+ childstack = stack + getpagesize();
+
+ pid = clone(dummy, childstack, CLONE_NEWUTS, NULL);
+
+ if (pid == -1)
+ return 3;
+ return 0;
+}
diff --git a/testcases/kernel/containers/utsname/runtests_noltp.sh b/testcases/kernel/containers/utsname/runtests_noltp.sh
new file mode 100755
index 0000000..5298666
--- /dev/null
+++ b/testcases/kernel/containers/utsname/runtests_noltp.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+exit_code=0
+echo "unshare tests"
+for i in `seq 1 5`; do
+ echo "test $i (unshare)"
+ ./utstest_noltp unshare $i
+ if [ $? -ne 0 ]; then
+ exit_code=$?
+ fi
+done
+echo "clone tests"
+for i in `seq 1 5`; do
+ echo "test $i (clone)"
+ ./utstest_noltp clone $i
+ if [ $? -ne 0 ]; then
+ exit_code=$?
+ fi
+done
+exit $exit_code
diff --git a/testcases/kernel/containers/utsname/runutstest.sh b/testcases/kernel/containers/utsname/runutstest.sh
new file mode 100755
index 0000000..dfa8304
--- /dev/null
+++ b/testcases/kernel/containers/utsname/runutstest.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+echo "unshare tests"
+for i in `seq 1 5`; do
+ echo "test $i (unshare)"
+ utstest unshare $i
+done
+echo "clone tests"
+for i in `seq 1 5`; do
+ echo "test $i (clone)"
+ utstest clone $i
+done
diff --git a/testcases/kernel/containers/utsname/utstest.c b/testcases/kernel/containers/utsname/utstest.c
new file mode 100644
index 0000000..73f96bc
--- /dev/null
+++ b/testcases/kernel/containers/utsname/utstest.c
@@ -0,0 +1,307 @@
+/*
+ * Copyright 2007 IBM
+ * Author: Serge Hallyn <serue@us.ibm.com>
+ *
+ * test1:
+ P1: A=gethostname
+ P2: B=gethostname
+ Ensure(A==B)
+
+ * test2:
+ P1: sethostname(A);
+ P2: (wait); B=gethostname
+ Ensure (A==B)
+
+ * test3:
+ P1: A=gethostname; unshare(utsname); sethostname(newname); C=gethostname
+ P2: B=gethostname; (wait); (wait); D=gethostname
+ Ensure (A==B && A==D && C!=D)
+
+ * test4:
+ P1: A=gethostname; unshare(utsname); (wait); C=gethostname
+ P2: B=gethostname; (wait); sethostname(newname); D=gethostname
+ Ensure (A==B && A==C && C!=D)
+
+ * test5:
+ P1: drop_privs(); unshare(utsname); (wait); C=gethostname
+ P2: (wait); sethostname(B); D=gethostname
+ Ensure (B==C==D) and state is ok.
+ *
+ */
+
+#define _GNU_SOURCE 1
+#include <sys/wait.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#ifndef NO_LTP
+#include <test.h>
+#include <libclone.h>
+#else
+#include "../libclone/libclone.h"
+#endif
+
+char *TCID = "uts_namespace";
+int TST_TOTAL=1;
+
+#ifdef NO_LTP
+#define TFAIL "FAILURE: "
+#define TPASS "PASS: "
+#define tst_resm(x, format, arg...) printf("%s:" format, x, ## arg)
+#define tst_exit() exit(1)
+#endif
+
+int drop_root()
+{
+ int ret;
+ ret = setresuid(1000, 1000, 1000);
+ if (ret) {
+ perror("setresuid");
+ exit(4);
+ }
+ return 1;
+}
+
+int p1fd[2], p2fd[2];
+pid_t cpid;
+
+#define HLEN 100
+#define NAME1 "serge1"
+#define NAME2 "serge2"
+
+void picknewhostname(char *orig, char *new)
+{
+ memset(new, 0, HLEN);
+ if (strcmp(orig, NAME1) == 0)
+ strcpy(new, NAME2);
+ else
+ strcpy(new, NAME1);
+}
+
+void zeroize(char *s)
+{
+ memset(s, 0, HLEN);
+}
+
+char *tsttype;
+int P1(void *vtest)
+{
+ char hostname[HLEN], newhostname[HLEN], rhostname[HLEN];
+ int err;
+ int len;
+ int testnum;
+
+ testnum = atoi((char *)vtest);
+
+ close(p1fd[1]);
+ close(p2fd[0]);
+
+ switch(testnum) {
+ case 1:
+ gethostname(hostname, HLEN);
+ zeroize(rhostname);
+ len = read(p1fd[0], rhostname, HLEN);
+ if (strcmp(hostname, rhostname) == 0) {
+ tst_resm(TPASS, "test 1 (%s): success\n", tsttype);
+ tst_exit();
+ }
+ tst_resm(TFAIL, "test 1 (%s): hostname 1 %s, hostname 2 %s\n",
+ tsttype, hostname, rhostname);
+ tst_exit();
+ case 2:
+ gethostname(hostname, HLEN);
+ picknewhostname(hostname, newhostname);
+ err = sethostname(newhostname, strlen(newhostname));
+ write(p2fd[1], "1", 1);
+ if (err == -1) {
+ tst_resm(TFAIL, "test 2 (%s): failed to sethostname",
+ tsttype);
+ tst_exit();
+ }
+ zeroize(rhostname);
+ len = read(p1fd[0], rhostname, HLEN);
+ if (strcmp(newhostname, rhostname) == 0) {
+ tst_resm(TPASS, "test 2 (%s): success\n",
+ tsttype);
+ tst_exit();
+ }
+ tst_resm(TFAIL, "test 2 (%s) hostname 1 %s, hostname 2 %s\n",
+ tsttype, newhostname, rhostname);
+ tst_exit();
+ case 3:
+ gethostname(hostname, HLEN);
+ picknewhostname(hostname, newhostname);
+ err = sethostname(newhostname, strlen(newhostname));
+ write(p2fd[1], "1", 1);
+ if (err == -1) {
+ tst_resm(TFAIL, "test 3 (%s): failed to sethostname",
+ tsttype);
+ tst_exit();
+ }
+
+ zeroize(rhostname);
+ len = read(p1fd[0], rhostname, HLEN);
+ if (strcmp(newhostname, rhostname) == 0) {
+ tst_resm(TFAIL, "test 3 (%s): hostname 1 %s, hostname 2 %s, these should have been different\n",
+ tsttype, newhostname, rhostname);
+ tst_exit();
+ }
+ if (strcmp(hostname, rhostname) == 0) {
+ tst_resm(TPASS, "test 3 (%s): success\n", tsttype);
+ tst_exit();
+ }
+ tst_resm(TFAIL, "test 3 (%s): hostname 1 %s, hostname 2 %s, should have been same\n",
+ tsttype, hostname, rhostname);
+ tst_exit();
+
+ case 4:
+ gethostname(hostname, HLEN);
+ write(p2fd[1], "1", 1); /* tell p2 to go ahead and sethostname */
+ zeroize(rhostname);
+ len = read(p1fd[0], rhostname, HLEN);
+ gethostname(newhostname, HLEN);
+ if (strcmp(hostname, newhostname) != 0) {
+ tst_resm(TFAIL, "test 4 (%s): hostname 1 %s, hostname 2 %s, should be same\n",
+ tsttype, hostname, newhostname);
+ tst_exit();
+ }
+ if (strcmp(hostname, rhostname) == 0) {
+ tst_resm(TFAIL, "test 4 (%s): hostname 1 %s, hostname 2 %s, should be different",
+ tsttype, hostname, rhostname);
+ tst_exit();
+ }
+ tst_resm(TPASS, "test 4 (%s): successful\n", tsttype);
+ tst_exit();
+ case 5:
+ write(p2fd[1], "1", 1); /* tell p2 to go ahead and sethostname */
+ zeroize(rhostname);
+ len = read(p1fd[0], rhostname, HLEN);
+ gethostname(newhostname, HLEN);
+ if (strcmp(rhostname, newhostname) != 0) {
+ tst_resm(TFAIL, "test 5 (%s): hostnames %s and %s should be same\n",
+ tsttype, rhostname, newhostname);
+ tst_exit();
+ }
+ tst_resm(TPASS, "test 5 (%s): successful", tsttype);
+ tst_exit();
+ default:
+ break;
+ }
+ return -1;
+}
+
+int P2(void *vtest)
+{
+ char hostname[HLEN], newhostname[HLEN];
+ int len;
+ int testnum;
+
+ testnum = atoi((char *)vtest);
+
+ close(p1fd[0]);
+ close(p2fd[1]);
+
+ switch(testnum) {
+ case 1:
+ gethostname(hostname, HLEN);
+ write(p1fd[1], hostname, strlen(hostname));
+ break;
+ case 2:
+ case 3:
+ len = 0;
+ while (!len) {
+ len = read(p2fd[0], hostname, 1);
+ }
+ gethostname(hostname, HLEN);
+ write(p1fd[1], hostname, strlen(hostname));
+ break;
+ case 4:
+ case 5:
+ len = 0;
+ while (!len) {
+ len = read(p2fd[0], hostname, 1);
+ }
+ if (hostname[0] == '0') {
+ tst_resm(TPASS, "P2: P1 claims error\n");
+ tst_exit();
+ exit(0);
+ }
+ gethostname(hostname, HLEN);
+ picknewhostname(hostname, newhostname);
+ sethostname(newhostname, strlen(newhostname));
+ write(p1fd[1], newhostname, strlen(newhostname));
+ break;
+ default:
+ tst_resm(TFAIL, "undefined test: %d\n", testnum);
+ break;
+ }
+ tst_exit();
+ return 0;
+}
+
+#define UNSHARESTR "unshare"
+#define CLONESTR "clone"
+int main(int argc, char *argv[])
+{
+ int r, pid, use_clone = T_UNSHARE;
+ int testnum;
+ void *vtest;
+
+ if (argc != 3) {
+ tst_resm(TFAIL, "Usage: %s <clone|unshare> <testnum>\n", argv[0]);
+ tst_resm(TFAIL, " where clone or unshare specifies unshare method,");
+ tst_resm(TFAIL, " and testnum is between 1 and 5 inclusive\n");
+ exit(2);
+ }
+ if (pipe(p1fd) == -1) { perror("pipe"); exit(EXIT_FAILURE); }
+ if (pipe(p2fd) == -1) { perror("pipe"); exit(EXIT_FAILURE); }
+
+ tsttype = UNSHARESTR;
+ if (strcmp(argv[1], "clone") == 0) {
+ use_clone = T_CLONE;
+ tsttype = CLONESTR;
+ }
+
+ testnum = atoi(argv[2]);
+
+ vtest = (void *)argv[2];
+ switch(testnum) {
+ case 1:
+ case 2: r = do_clone_unshare_tests(T_NONE, 0,
+ P1, vtest, P2, vtest);
+ break;
+ case 3:
+ case 4:
+ r = do_clone_unshare_tests(use_clone, CLONE_NEWUTS,
+ P1, vtest, P2, vtest);
+ break;
+ case 5:
+ pid = fork();
+ if (pid == -1) {
+ perror("fork");
+ exit(2);
+ }
+ if (pid == 0) {
+ if (!drop_root()) {
+ tst_resm(TFAIL, "failed to drop root.\n");
+ tst_exit();
+ exit(1);
+ }
+ r = do_clone_unshare_test(use_clone, CLONE_NEWUTS,
+ P1, vtest);
+ write(p2fd[1], "0", 1); /* don't let p2 hang */
+ exit(0);
+ } else {
+ P2(vtest);
+ }
+ break;
+ default:
+ tst_resm(TFAIL, "testnum should be between 1 and 5 inclusive.\n");
+ break;
+ }
+
+ tst_exit();
+}
diff --git a/testscripts/test_containers.sh b/testscripts/test_containers.sh
new file mode 100755
index 0000000..bc0cfaf
--- /dev/null
+++ b/testscripts/test_containers.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+#
+# Copyright 2007 IBM
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+#
+# test_containers.sh - Run the containers test suite.
+
+# Must be root to run the containers testsuite
+if [ $UID != 0 ]
+then
+ echo "FAILED: Must be root to execute this script"
+ exit 1
+fi
+
+# set the LTPROOT directory
+cd `dirname $0`
+LTPROOT=${PWD}
+echo $LTPROOT | grep testscripts > /dev/null 2>&1
+if [ $? -eq 0 ]
+then
+ cd ..
+ LTPROOT=${PWD}
+fi
+
+# set the PATH to include testcase/bin
+
+export PATH=$PATH:/usr/sbin:$LTPROOT/testcases/bin
+export LTPBIN=$LTPROOT/testcases/bin
+
+# We will store the logfiles in $LTPROOT/results, so make sure
+# it exists.
+if [ ! -d $LTPROOT/results ]
+then
+ mkdir $LTPROOT/results
+fi
+
+# Check the role and mode testsuite is being executed under.
+echo "Running the containers testsuite..."
+
+$LTPROOT/pan/pan -S -a $LTPROOT/results/containers -n ltp-containers -l $LTPROOT/results/containers.logfile -o $LTPROOT/results/containers.outfile -p -f $LTPROOT/runtest/containers
+
+echo "Done."
+exit 0