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 #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
main(int ac,char ** av)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
setup(void)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
cleanup(void)169 static void cleanup(void)
170 {
171 tst_rmdir();
172 }
173