1 /* 2 * Copyright (c) International Business Machines Corp., 2001 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 12 * the GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 * 18 * NAME 19 * fork09.c 20 * 21 * DESCRIPTION 22 * Check that child has access to a full set of files. 23 * 24 * ALGORITHM 25 * Parent opens a maximum number of files 26 * Child closes one and attempts to open another, it should be 27 * available 28 * 29 * USAGE 30 * fork09 31 * 32 * HISTORY 33 * 07/2001 Ported by Wayne Boyer 34 * 35 * 10/2008 Suzuki K P <suzuki (at) in.ibm.com> 36 * Fix maximum number of files open logic. 37 * 38 * RESTRICTIONS 39 * None 40 */ 41 42 #include <sys/types.h> 43 #include <sys/wait.h> 44 #include <sys/stat.h> 45 #include <fcntl.h> 46 #include <stdio.h> 47 #include <errno.h> 48 #include <unistd.h> /* for _SC_OPEN_MAX */ 49 #include "test.h" 50 #include "safe_macros.h" 51 52 char *TCID = "fork09"; 53 int TST_TOTAL = 1; 54 55 static void setup(void); 56 static void cleanup(void); 57 58 static char filname[40], childfile[40]; 59 static int first; 60 static FILE **fildeses; /* file streams */ 61 static int mypid, nfiles; 62 63 #define OPEN_MAX (sysconf(_SC_OPEN_MAX)) 64 65 int main(int ac, char **av) 66 { 67 int pid, status, nf; 68 69 int lc; 70 71 tst_parse_opts(ac, av, NULL, NULL); 72 73 setup(); 74 75 fildeses = malloc((OPEN_MAX + 10) * sizeof(FILE *)); 76 if (fildeses == NULL) 77 tst_brkm(TBROK, cleanup, "malloc failed"); 78 79 for (lc = 0; TEST_LOOPING(lc); lc++) { 80 tst_count = 0; 81 mypid = getpid(); 82 83 tst_resm(TINFO, "OPEN_MAX is %ld", OPEN_MAX); 84 85 /* establish first free file */ 86 sprintf(filname, "fork09.%d", mypid); 87 first = SAFE_CREAT(cleanup, filname, 0660); 88 close(first); 89 90 tst_resm(TINFO, "first file descriptor is %d ", first); 91 92 SAFE_UNLINK(cleanup, filname); 93 94 /* 95 * now open all the files for the test 96 */ 97 for (nfiles = first; nfiles < OPEN_MAX; nfiles++) { 98 sprintf(filname, "file%d.%d", nfiles, mypid); 99 fildeses[nfiles] = fopen(filname, "a"); 100 if (fildeses[nfiles] == NULL) { 101 /* Did we already reach OPEN_MAX ? */ 102 if (errno == EMFILE) 103 break; 104 tst_brkm(TBROK, cleanup, "Parent: cannot open " 105 "file %d %s errno = %d", nfiles, 106 filname, errno); 107 } 108 #ifdef DEBUG 109 tst_resm(TINFO, "filname: %s", filname); 110 #endif 111 } 112 113 tst_resm(TINFO, "Parent reporting %d files open", nfiles - 1); 114 115 pid = fork(); 116 if (pid == -1) 117 tst_brkm(TBROK, cleanup, "Fork failed"); 118 119 if (pid == 0) { /* child */ 120 nfiles--; 121 if (fclose(fildeses[nfiles]) == -1) { 122 tst_resm(TINFO, "Child could not close file " 123 "#%d, errno = %d", nfiles, errno); 124 exit(1); 125 } else { 126 sprintf(childfile, "cfile.%d", getpid()); 127 fildeses[nfiles] = fopen(childfile, "a"); 128 if (fildeses[nfiles] == NULL) { 129 tst_resm(TINFO, "Child could not open " 130 "file %s, errno = %d", 131 childfile, errno); 132 exit(1); 133 } else { 134 tst_resm(TINFO, "Child opened new " 135 "file #%d", nfiles); 136 unlink(childfile); 137 exit(0); 138 } 139 } 140 } else { /* parent */ 141 wait(&status); 142 if (status >> 8 != 0) 143 tst_resm(TFAIL, "test 1 FAILED"); 144 else 145 tst_resm(TPASS, "test 1 PASSED"); 146 } 147 148 /* clean up things in case we are looping */ 149 for (nf = first; nf < nfiles; nf++) { 150 fclose(fildeses[nf]); 151 sprintf(filname, "file%d.%d", nf, mypid); 152 unlink(filname); 153 } 154 } 155 156 cleanup(); 157 tst_exit(); 158 } 159 160 static void setup(void) 161 { 162 tst_sig(FORK, DEF_HANDLER, cleanup); 163 umask(0); 164 165 TEST_PAUSE; 166 tst_tmpdir(); 167 } 168 169 static void cleanup(void) 170 { 171 tst_rmdir(); 172 } 173