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