libclone.c revision 7f140ab215a66e7ed9a195591b756cf6cdfde38c
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 19int do_clone_tests(unsigned long clone_flags, 20 int(*fn1)(void *arg), void *arg1, 21 int(*fn2)(void *arg), void *arg2) 22{ 23 int ret; 24 25 ret = ltp_clone_quick(clone_flags | SIGCHLD, fn1, arg1); 26 27 if (ret == -1) { 28 return -1; 29 } 30 if (fn2) 31 ret = fn2(arg2); 32 else 33 ret = 0; 34 35 return ret; 36} 37 38int do_unshare_tests(unsigned long clone_flags, 39 int (*fn1)(void *arg), void *arg1, 40 int (*fn2)(void *arg), void *arg2) 41{ 42 int pid, ret = 0; 43 int retpipe[2]; 44 char buf[2]; 45 46 if (pipe(retpipe) == -1) { 47 perror("pipe"); 48 return -1; 49 } 50 pid = fork(); 51 if (pid == -1) { 52 perror("fork"); 53 close(retpipe[0]); 54 close(retpipe[1]); 55 return -1; 56 } 57 if (pid == 0) { 58 close(retpipe[0]); 59 ret = syscall(SYS_unshare, clone_flags); 60 if (ret == -1) { 61 if (write(retpipe[1], "0", 2) < 0) { 62 perror("unshare:write(retpipe[1], ..)"); 63 } 64 close(retpipe[1]); 65 exit(1); 66 } else { 67 if (write(retpipe[1], "1", 2) < 0) { 68 perror("unshare:write(retpipe[1], ..)"); 69 } 70 } 71 close(retpipe[1]); 72 ret = fn1(arg1); 73 exit(ret); 74 } else { 75 close(retpipe[1]); 76 if (read(retpipe[0], &buf, 2) < 0) { 77 perror("unshare:read(retpipe[0], ..)"); 78 } 79 close(retpipe[0]); 80 if (*buf == '0') 81 return -1; 82 if (fn2) 83 ret = fn2(arg2); 84 } 85 86 return ret; 87} 88 89int do_plain_tests(int (*fn1)(void *arg), void *arg1, 90 int (*fn2)(void *arg), void *arg2) 91{ 92 int ret = 0, pid; 93 94 pid = fork(); 95 if (pid == -1) { 96 perror("fork"); 97 return -1; 98 } 99 if (pid == 0) 100 return fn1(arg1); 101 if (fn2) 102 ret = fn2(arg2); 103 return ret; 104} 105 106int do_clone_unshare_test(int use_clone, unsigned long clone_flags, 107 int (*fn1)(void *arg), void *arg1) 108{ 109 switch (use_clone) { 110 case T_NONE: 111 return do_plain_tests(fn1, arg1, NULL, NULL); 112 case T_CLONE: 113 return do_clone_tests(clone_flags, fn1, arg1, NULL, NULL); 114 case T_UNSHARE: 115 return do_unshare_tests(clone_flags, fn1, arg1, NULL, NULL); 116 default: 117 printf("%s: bad use_clone option: %d\n", __FUNCTION__, 118 use_clone); 119 return -1; 120 } 121} 122 123 124/* 125 * Run fn1 in a unshared environmnent, and fn2 in the original context 126 */ 127int do_clone_unshare_tests(int use_clone, unsigned long clone_flags, 128 int (*fn1)(void *arg), void *arg1, 129 int (*fn2)(void *arg), void *arg2) 130{ 131 switch (use_clone) { 132 case T_NONE: 133 return do_plain_tests(fn1, arg1, fn2, arg2); 134 case T_CLONE: 135 return do_clone_tests(clone_flags, fn1, arg1, fn2, arg2); 136 case T_UNSHARE: 137 return do_unshare_tests(clone_flags, fn1, arg1, fn2, arg2); 138 default: 139 printf("%s: bad use_clone option: %d\n", __FUNCTION__, 140 use_clone); 141 return -1; 142 } 143} 144