libclone.c revision 6aa2737d5de9256fcdb5b68a6aa6b12249005049
1/*
2* Copyright (c) International Business Machines Corp., 2007
3* This program is free software; you can redistribute it and/or modify
4* it under the terms of the GNU General Public License as published by
5* the Free Software Foundation; either version 2 of the License, or
6* (at your option) any later version.
7*
8* This program is distributed in the hope that it will be useful,
9* but WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
11* the GNU General Public License for more details.
12* You should have received a copy of the GNU General Public License
13* along with this program; if not, write to the Free Software
14* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15*
16***************************************************************************/
17#include "libclone.h"
18
19static void cleanup();
20
21int do_clone_tests(unsigned long clone_flags,
22			int(*fn1)(void *arg), void *arg1,
23			int(*fn2)(void *arg), void *arg2)
24{
25	int ret;
26
27	ret = ltp_clone_quick(clone_flags | SIGCHLD, fn1, arg1);
28
29	if (ret == -1) {
30		return -1;
31	}
32	if (fn2)
33		ret = fn2(arg2);
34	else
35		ret = 0;
36
37	return ret;
38}
39
40int do_unshare_tests(unsigned long clone_flags,
41			int (*fn1)(void *arg), void *arg1,
42			int (*fn2)(void *arg), void *arg2)
43{
44	int pid, ret = 0;
45	int retpipe[2];
46	char buf[2];
47
48	if (pipe(retpipe) == -1) {
49		perror("pipe");
50		return -1;
51	}
52	pid = fork();
53	if (pid == -1) {
54		perror("fork");
55		close(retpipe[0]);
56		close(retpipe[1]);
57		return -1;
58	}
59	if (pid == 0) {
60		close(retpipe[0]);
61		ret = syscall(SYS_unshare, clone_flags);
62		if (ret == -1) {
63			if (write(retpipe[1], "0", 2) < 0) {
64				perror("unshare:write(retpipe[1], ..)");
65			}
66			close(retpipe[1]);
67			exit(1);
68		} else {
69			if (write(retpipe[1], "1", 2) < 0) {
70				perror("unshare:write(retpipe[1], ..)");
71			}
72		}
73		close(retpipe[1]);
74		ret = fn1(arg1);
75		exit(ret);
76	} else {
77		close(retpipe[1]);
78		if (read(retpipe[0], &buf, 2) < 0) {
79			perror("unshare:read(retpipe[0], ..)");
80		}
81		close(retpipe[0]);
82		if (*buf == '0')
83			return -1;
84		if (fn2)
85			ret = fn2(arg2);
86	}
87
88	return ret;
89}
90
91int do_plain_tests(int (*fn1)(void *arg), void *arg1,
92			int (*fn2)(void *arg), void *arg2)
93{
94	int ret = 0, pid;
95
96	pid = fork();
97	if (pid == -1) {
98		perror("fork");
99		return -1;
100	}
101	if (pid == 0)
102		return fn1(arg1);
103	if (fn2)
104		ret = fn2(arg2);
105	return ret;
106}
107
108int do_clone_unshare_test(int use_clone, unsigned long clone_flags,
109			int (*fn1)(void *arg), void *arg1)
110{
111	switch (use_clone) {
112	case T_NONE:
113		return do_plain_tests(fn1, arg1, NULL, NULL);
114	case T_CLONE:
115		return do_clone_tests(clone_flags, fn1, arg1, NULL, NULL);
116	case T_UNSHARE:
117		return do_unshare_tests(clone_flags, fn1, arg1, NULL, NULL);
118	default:
119		printf("%s: bad use_clone option: %d\n", __FUNCTION__,
120							use_clone);
121		return -1;
122	}
123}
124
125
126/*
127 * Run fn1 in a unshared environmnent, and fn2 in the original context
128 */
129int do_clone_unshare_tests(int use_clone, unsigned long clone_flags,
130			int (*fn1)(void *arg), void *arg1,
131			int (*fn2)(void *arg), void *arg2)
132{
133	switch (use_clone) {
134	case T_NONE:
135		return do_plain_tests(fn1, arg1, fn2, arg2);
136	case T_CLONE:
137		return do_clone_tests(clone_flags, fn1, arg1, fn2, arg2);
138	case T_UNSHARE:
139		return do_unshare_tests(clone_flags, fn1, arg1, fn2, arg2);
140	default:
141		printf("%s: bad use_clone option: %d\n", __FUNCTION__,
142							use_clone);
143		return -1;
144	}
145}
146