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@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
51 char *TCID = "fork09";
52 int TST_TOTAL = 1;
53
54 static void setup(void);
55 static void cleanup(void);
56
57 static char filname[40], childfile[40];
58 static int first;
59 static FILE **fildeses; /* file streams */
60 static int mypid, nfiles;
61
62 #define OPEN_MAX (sysconf(_SC_OPEN_MAX))
63
main(int ac,char ** av)64 int main(int ac, char **av)
65 {
66 int pid, status, nf;
67
68 int lc;
69
70 tst_parse_opts(ac, av, NULL, NULL);
71
72 setup();
73
74 fildeses = malloc((OPEN_MAX + 10) * sizeof(FILE *));
75 if (fildeses == NULL)
76 tst_brkm(TBROK, cleanup, "malloc failed");
77
78 for (lc = 0; TEST_LOOPING(lc); lc++) {
79 tst_count = 0;
80 mypid = getpid();
81
82 tst_resm(TINFO, "OPEN_MAX is %ld", OPEN_MAX);
83
84 /* establish first free file */
85 sprintf(filname, "fork09.%d", mypid);
86 first = creat(filname, 0660);
87 if (first == -1)
88 tst_brkm(TBROK, cleanup, "Cannot open first file %s, "
89 "errno = %d", filname, errno);
90 close(first);
91
92 tst_resm(TINFO, "first file descriptor is %d ", first);
93
94 if (unlink(filname) == -1)
95 tst_brkm(TBROK, cleanup, "Cannot unlink file %s, "
96 "errno = %d", filname, errno);
97
98 /*
99 * now open all the files for the test
100 */
101 for (nfiles = first; nfiles < OPEN_MAX; nfiles++) {
102 sprintf(filname, "file%d.%d", nfiles, mypid);
103 fildeses[nfiles] = fopen(filname, "a");
104 if (fildeses[nfiles] == NULL) {
105 /* Did we already reach OPEN_MAX ? */
106 if (errno == EMFILE)
107 break;
108 tst_brkm(TBROK, cleanup, "Parent: cannot open "
109 "file %d %s errno = %d", nfiles,
110 filname, errno);
111 }
112 #ifdef DEBUG
113 tst_resm(TINFO, "filname: %s", filname);
114 #endif
115 }
116
117 tst_resm(TINFO, "Parent reporting %d files open", nfiles - 1);
118
119 pid = fork();
120 if (pid == -1)
121 tst_brkm(TBROK, cleanup, "Fork failed");
122
123 if (pid == 0) { /* child */
124 nfiles--;
125 if (fclose(fildeses[nfiles]) == -1) {
126 tst_resm(TINFO, "Child could not close file "
127 "#%d, errno = %d", nfiles, errno);
128 exit(1);
129 } else {
130 sprintf(childfile, "cfile.%d", getpid());
131 fildeses[nfiles] = fopen(childfile, "a");
132 if (fildeses[nfiles] == NULL) {
133 tst_resm(TINFO, "Child could not open "
134 "file %s, errno = %d",
135 childfile, errno);
136 exit(1);
137 } else {
138 tst_resm(TINFO, "Child opened new "
139 "file #%d", nfiles);
140 unlink(childfile);
141 exit(0);
142 }
143 }
144 } else { /* parent */
145 wait(&status);
146 if (status >> 8 != 0)
147 tst_resm(TFAIL, "test 1 FAILED");
148 else
149 tst_resm(TPASS, "test 1 PASSED");
150 }
151
152 /* clean up things in case we are looping */
153 for (nf = first; nf < nfiles; nf++) {
154 fclose(fildeses[nf]);
155 sprintf(filname, "file%d.%d", nf, mypid);
156 unlink(filname);
157 }
158 }
159
160 cleanup();
161 tst_exit();
162 }
163
setup(void)164 static void setup(void)
165 {
166 tst_sig(FORK, DEF_HANDLER, cleanup);
167 umask(0);
168
169 TEST_PAUSE;
170 tst_tmpdir();
171 }
172
cleanup(void)173 static void cleanup(void)
174 {
175 tst_rmdir();
176 }
177