Home | History | Annotate | Download | only in libclone
      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