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