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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 15 * 16 ***************************************************************************/ 17 #include "libclone.h" 18 19 int 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 38 int 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 = ltp_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 89 int 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 exit(fn1(arg1)); 101 if (fn2) 102 ret = fn2(arg2); 103 return ret; 104 } 105 106 int 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 * Run fn1 in a unshared environmnent, and fn2 in the original context 125 */ 126 int do_clone_unshare_tests(int use_clone, unsigned long clone_flags, 127 int (*fn1) (void *arg), void *arg1, 128 int (*fn2) (void *arg), void *arg2) 129 { 130 switch (use_clone) { 131 case T_NONE: 132 return do_plain_tests(fn1, arg1, fn2, arg2); 133 case T_CLONE: 134 return do_clone_tests(clone_flags, fn1, arg1, fn2, arg2); 135 case T_UNSHARE: 136 return do_unshare_tests(clone_flags, fn1, arg1, fn2, arg2); 137 default: 138 printf("%s: bad use_clone option: %d\n", __FUNCTION__, 139 use_clone); 140 return -1; 141 } 142 } 143