1 /* 2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. 3 * AUTHOR : Glen Overby 4 * CO-PILOT : William Roske 5 * Copyright (c) 2014 Cyril Hrubis <chrubis (at) suse.cz> 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of version 2 of the GNU General Public License as 9 * published by the Free Software Foundation. 10 * 11 * This program is distributed in the hope that it would be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 14 * 15 * Further, this software is distributed without any warranty that it is 16 * free of the rightful claim of any third person regarding infringement 17 * or the like. Any license provided herein, whether implied or 18 * otherwise, applies only to this software file. Patent licenses, if 19 * any, provided herein do not apply to combinations of this program with 20 * other software, or any other product whatsoever. 21 * 22 * You should have received a copy of the GNU General Public License along 23 * with this program; if not, write the Free Software Foundation, Inc., 24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 25 * 26 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 27 * Mountain View, CA 94043, or: 28 * 29 * http://www.sgi.com 30 * 31 * For further information regarding this notice, see: 32 * 33 * http://oss.sgi.com/projects/GenInfo/NoticeExplan/ 34 */ 35 /* 36 * TEST CASES 37 * 38 * 1. test close-on-exec with a regular file 39 * 2. test close-on-exec with a pipe 40 * 3. test close-on-exec with a fifo 41 */ 42 43 #include <errno.h> 44 #include <string.h> 45 #include <signal.h> 46 #include <sys/types.h> 47 #include <unistd.h> 48 #include <stdlib.h> 49 #include <fcntl.h> 50 #include <sys/wait.h> 51 #include <limits.h> 52 53 #include "test.h" 54 #include "safe_macros.h" 55 56 static void setup(void); 57 static void cleanup(void); 58 static void help(void); 59 60 char *TCID = "fcntl07"; 61 62 static char *t_opt; 63 64 option_t options[] = { 65 {"T:", NULL, &t_opt}, 66 {NULL, NULL, NULL} 67 }; 68 69 static int file_fd, pipe_fds[2], fifo_fd; 70 71 #define FIFONAME "fifo" 72 73 static struct tcase { 74 int *fd; 75 const char *msg; 76 } tcases[] = { 77 {&file_fd, "regular file"}, 78 {pipe_fds, "pipe (write end)"}, 79 {pipe_fds+1, "pipe (read end)"}, 80 {&fifo_fd, "fifo"}, 81 }; 82 83 int TST_TOTAL = ARRAY_SIZE(tcases); 84 85 static int test_open(char *arg); 86 87 static void verify_cloexec(struct tcase *tc) 88 { 89 int fd = *(tc->fd); 90 char pidname[255]; 91 int status, pid; 92 93 TEST(fcntl(fd, F_SETFD, FD_CLOEXEC)); 94 95 if (TEST_RETURN == -1) { 96 tst_resm(TFAIL | TTERRNO, 97 "fcntl(%s[%d], F_SETFD, FD_CLOEXEC) failed", 98 tc->msg, fd); 99 return; 100 } 101 102 sprintf(pidname, "%d", fd); 103 104 switch (pid = FORK_OR_VFORK()) { 105 case -1: 106 tst_resm(TBROK | TERRNO, "fork() failed"); 107 return; 108 case 0: 109 execlp(TCID, TCID, "-T", pidname, NULL); 110 111 /* the ONLY reason to do this is to get the errno printed out */ 112 fprintf(stderr, "exec(%s, %s, -T, %s) failed. Errno %s [%d]\n", 113 TCID, TCID, pidname, strerror(errno), errno); 114 exit(2); 115 default: 116 break; 117 } 118 119 waitpid(pid, &status, 0); 120 121 if (!WIFEXITED(status)) { 122 tst_resm(TBROK, "waitpid return was 0%o", status); 123 return; 124 } 125 126 switch ((WEXITSTATUS(status))) { 127 case 2: 128 tst_resm(TBROK, "exec failed"); 129 break; 130 case 0: 131 tst_resm(TPASS, "%s CLOEXEC fd was closed after exec()", 132 tc->msg); 133 break; 134 default: 135 tst_resm(TFAIL, "%s child exited non-zero, %d", 136 tc->msg, WEXITSTATUS(status)); 137 } 138 } 139 140 int main(int ac, char **av) 141 { 142 int lc, i; 143 144 tst_parse_opts(ac, av, options, &help); 145 146 if (t_opt) 147 exit(test_open(t_opt)); 148 149 setup(); 150 151 for (lc = 0; TEST_LOOPING(lc); lc++) { 152 tst_count = 0; 153 154 for (i = 0; i < TST_TOTAL; i++) 155 verify_cloexec(tcases + i); 156 } 157 158 cleanup(); 159 tst_exit(); 160 } 161 162 void setup(void) 163 { 164 tst_sig(FORK, DEF_HANDLER, cleanup); 165 166 TEST_PAUSE; 167 168 tst_tmpdir(); 169 170 file_fd = SAFE_OPEN(cleanup, "test_file", O_CREAT | O_RDWR, 0666); 171 SAFE_PIPE(cleanup, pipe_fds); 172 SAFE_MKFIFO(cleanup, FIFONAME, 0666); 173 fifo_fd = SAFE_OPEN(cleanup, FIFONAME, O_RDWR, 0666); 174 } 175 176 void cleanup(void) 177 { 178 if (file_fd > 0 && close(file_fd)) 179 tst_resm(TWARN | TERRNO, "close(file_fd) failed"); 180 181 if (pipe_fds[0] > 0 && close(pipe_fds[0])) 182 tst_resm(TWARN | TERRNO, "close(pipe_fds[0]) failed"); 183 184 if (pipe_fds[1] > 0 && close(pipe_fds[1])) 185 tst_resm(TWARN | TERRNO, "close(pipe_fds[1]) failed"); 186 187 if (fifo_fd > 0 && close(fifo_fd)) 188 tst_resm(TWARN | TERRNO, "close(fifo_fd) failed"); 189 190 tst_rmdir(); 191 } 192 193 void help(void) 194 { 195 printf(" -T fd The program runs as 'test_open()'\n"); 196 } 197 198 int test_open(char *arg) 199 { 200 int fd, rc; 201 int status; 202 203 fd = atoi(arg); 204 205 rc = fcntl(fd, F_GETFD, &status); 206 207 if (rc == -1 && errno == EBADF) 208 return 0; 209 210 fprintf(stderr, "fcntl() returned %i, errno %s(%i)\n", 211 rc, tst_strerrno(errno), errno); 212 213 return 1; 214 } 215