1/*
2 * NAME
3 *	fcntl01.c
4 *
5 * DESCRIPTION
6 *	Test F_DUPFD, F_SETFL cmds of fcntl
7 *
8 * CALLS
9 *	fcntl
10 *
11 * ALGORITHM
12 *
13 *	1. Testing F_DUPFD cmd with arg less than, equal to, and greater
14 *	   than the next available file descriptor.
15 *
16 *	2. Checking F_SETFL cmd with each valid flag (O_NDELAY, O_APPEND).
17 *
18 *	3. Checking, setting and reading `close on exec' flag.
19 *
20 * USAGE
21 *	fcntl01
22 *
23 * HISTORY
24 *	07/2001 Ported by Wayne Boyer
25 *	09/2002 added fd2 array to remove statid fds
26 *
27 * RESTRICTIONS
28 *	None
29 *
30 */
31
32#include <fcntl.h>
33#include <errno.h>
34#include <sys/types.h>
35#include <sys/stat.h>
36#include "test.h"
37
38void setup(void);
39void cleanup(void);
40
41char *TCID = "fcntl01";
42int TST_TOTAL = 1;
43
44int main(int ac, char **av)
45{
46	int flags;
47	char fname[40];
48	int fd[10], fd2[10];
49	int mypid;
50	unsigned int i;
51	int lc;
52
53	tst_parse_opts(ac, av, NULL, NULL);
54
55	setup();
56
57	/* check for looping state if -i option is given */
58	for (lc = 0; TEST_LOOPING(lc); lc++) {
59
60		tst_count = 0;
61
62		mypid = getpid();
63		for (i = 0; i < 8; i++) {
64			sprintf(fname, "./fcntl%d.%d", i, mypid);
65			if ((fd[i] =
66			     open(fname, O_WRONLY | O_CREAT, 0666)) == -1)
67				tst_resm(TBROK | TERRNO, "open failed");
68			fd2[i] = fd[i];
69		}
70
71		close(fd[2]);
72		close(fd[3]);
73		close(fd[4]);
74		close(fd[5]);
75
76		if ((fd[2] = fcntl(fd[1], F_DUPFD, 1)) == -1)
77			tst_resm(TFAIL | TERRNO, "fcntl(.., 1) failed");
78
79		if (fd[2] < fd2[2])
80			tst_resm(TFAIL, "new fd has unexpected value: "
81				 "got %d, expected greater than %d", fd[2], 5);
82
83		if ((fd[4] = fcntl(fd[1], F_DUPFD, fd2[3])) < 0)
84			tst_resm(TFAIL | TERRNO, "fcntl(.., fd2[3]) failed");
85
86		if (fd[4] < fd2[3])
87			tst_resm(TFAIL, "new fd has unexpected value, got %d, "
88				 "expect greater than %d", fd[4], fd2[3]);
89
90		if ((fd[8] = fcntl(fd[1], F_DUPFD, fd2[5])) < 0)
91			tst_resm(TFAIL | TERRNO, "fcntl(.., fd2[5]) failed");
92
93		if (fd[8] != fd2[5])
94			tst_resm(TFAIL, "new fd has unexpected value: "
95				 "got %d, expected %d", fd[8], fd2[5]);
96/* //block1: */
97		flags = fcntl(fd[2], F_GETFL, 0);
98		if ((flags & O_WRONLY) == 0)
99			tst_resm(TFAIL, "unexpected flag 0x%x, expected 0x%x",
100				 flags, O_WRONLY);
101
102		/* Check setting of no_delay flag */
103		if (fcntl(fd[2], F_SETFL, O_NDELAY) == -1)
104			tst_resm(TBROK | TERRNO, "fcntl(.., O_NDELAY) failed");
105
106		flags = fcntl(fd[2], F_GETFL, 0);
107		if ((flags & (O_NDELAY | O_WRONLY)) == 0)
108			tst_resm(TFAIL, "unexpected flag 0x%x, expected 0x%x",
109				 flags, O_NDELAY | O_WRONLY);
110
111		/* Check of setting append flag */
112		if (fcntl(fd[2], F_SETFL, O_APPEND) == -1)
113			tst_resm(TFAIL | TERRNO, "fcntl(.., O_APPEND) failed");
114
115		flags = fcntl(fd[2], F_GETFL, 0);
116		if ((flags & (O_APPEND | O_WRONLY)) == 0)
117			tst_resm(TFAIL, "unexpected flag ox%x, expected 0x%x",
118				 flags, O_APPEND | O_WRONLY);
119
120		/* Check setting flags together */
121		if (fcntl(fd[2], F_SETFL, O_NDELAY | O_APPEND) < 0)
122			tst_resm(TFAIL, "fcntl(.., O_NDELAY|O_APPEND) failed");
123
124		flags = fcntl(fd[2], F_GETFL, 0);
125		if ((flags & (O_NDELAY | O_APPEND | O_WRONLY)) == 0)
126			tst_resm(TFAIL, "unexpected flag 0x%x, expected 0x%x",
127				 flags,
128				 O_NDELAY | O_APPEND | O_SYNC | O_WRONLY);
129
130		/* Check that flags are not cummulative */
131		if (fcntl(fd[2], F_SETFL, 0) == -1)
132			tst_resm(TFAIL, "fcntl(.., 0) failed");
133
134		flags = fcntl(fd[2], F_GETFL, 0);
135		if ((flags & O_WRONLY) == 0)
136			tst_resm(TFAIL, "unexpected flag 0x%x, expected 0x%x",
137				 flags, O_WRONLY);
138
139/* //block2: */
140		/*
141		 * Check ability to set (F_SETFD) the close on exec flag
142		 */
143		if ((flags = fcntl(fd[2], F_GETFD, 0)) < 0)
144			tst_resm(TFAIL | TERRNO,
145				 "fcntl(.., F_GETFD, ..) #1 failed");
146		if (flags != 0)
147			tst_resm(TFAIL, "unexpected flags got 0x%x expected "
148				 "0x%x", flags, 0);
149		if ((flags = fcntl(fd[2], F_SETFD, 1)) == -1)
150			tst_resm(TFAIL, "fcntl(.., F_SETFD, ..) failed");
151		if ((flags = fcntl(fd[2], F_GETFD, 0)) == -1)
152			tst_resm(TFAIL | TERRNO,
153				 "fcntl(.., F_GETFD, ..) #2 failed");
154		if (flags != 1)
155			tst_resm(TFAIL, "unexpected flags, got 0x%x, "
156				 "expected 0x%x", flags, 1);
157
158		for (i = 0; i < ARRAY_SIZE(fd); i++)
159			close(fd[i]);
160		for (i = 0; i < 8; i++) {
161			sprintf(fname, "./fcntl%u.%d", i, mypid);
162			if ((unlink(fname)) == -1)
163				tst_resm(TFAIL | TERRNO,
164					 "unlinking %s failed", fname);
165		}
166	}
167	cleanup();
168	tst_exit();
169}
170
171/*
172 * setup
173 *	performs all ONE TIME setup for this test
174 */
175void setup(void)
176{
177	tst_sig(FORK, DEF_HANDLER, cleanup);
178	umask(0);
179	TEST_PAUSE;
180	tst_tmpdir();
181}
182
183void cleanup(void)
184{
185	tst_rmdir();
186
187}
188