1 /*
2  *
3  *   Copyright (c) International Business Machines  Corp., 2001
4  *
5  *   This program is free software;  you can redistribute it and/or modify
6  *   it under the terms of the GNU General Public License as published by
7  *   the Free Software Foundation; either version 2 of the License, or
8  *   (at your option) any later version.
9  *
10  *   This program is distributed in the hope that it will be useful,
11  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13  *   the GNU General Public License for more details.
14  *
15  *   You should have received a copy of the GNU General Public License
16  *   along with this program;  if not, write to the Free Software
17  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 /*
21  * NAME
22  *	dup203.c
23  *
24  * DESCRIPTION
25  *	Testcase to check the basic functionality of dup2().
26  *
27  * ALGORITHM
28  *	1.	Attempt to dup2() on an open file descriptor.
29  *	2.	Attempt to dup2() on a close file descriptor.
30  *
31  * USAGE:  <for command-line>
32  *  dup203 [-c n] [-f] [-i n] [-I x] [-P x] [-t]
33  *     where,  -c n : Run n copies concurrently.
34  *             -f   : Turn off functionality Testing.
35  *             -i n : Execute test n times.
36  *             -I x : Execute test for x seconds.
37  *             -P x : Pause for x seconds between iterations.
38  *             -t   : Turn on syscall timing.
39  *
40  * HISTORY
41  *	07/2001 Ported by Wayne Boyer
42  *
43  * RESTRICTIONS
44  *	NONE
45  */
46 
47 #include <fcntl.h>
48 #include <sys/param.h>
49 #include <errno.h>
50 #include <string.h>
51 #include "test.h"
52 #include "safe_macros.h"
53 
54 void setup(void);
55 void cleanup(void);
56 
57 char *TCID = "dup203";
58 int TST_TOTAL = 1;
59 
main(int ac,char ** av)60 int main(int ac, char **av)
61 {
62 	int fd0, fd1, fd2, rval;
63 	char filename0[40], filename1[40];
64 	char buf[40];
65 
66 	int lc;
67 
68 	tst_parse_opts(ac, av, NULL, NULL);
69 
70 	setup();
71 
72 	for (lc = 0; TEST_LOOPING(lc); lc++) {
73 
74 		tst_count = 0;
75 //block1:
76 		tst_resm(TINFO, "Enter block 1");
77 		tst_resm(TINFO, "Test duping over an open fd");
78 
79 		sprintf(filename0, "dup202.file0.%d\n", getpid());
80 		sprintf(filename1, "dup202.file1.%d\n", getpid());
81 		unlink(filename0);
82 		unlink(filename1);
83 
84 		if ((fd0 = creat(filename0, 0666)) == -1)
85 			tst_brkm(TBROK, cleanup, "cannot create first file");
86 		if (write(fd0, filename0, strlen(filename0)) == -1)
87 			tst_brkm(TBROK, cleanup, "filename0: write(2) failed");
88 
89 		if ((fd1 = creat(filename1, 0666)) == -1)
90 			tst_brkm(TBROK, cleanup, "Cannot create second file");
91 		if (write(fd1, filename1, strlen(filename1)) == -1)
92 			tst_brkm(TBROK, cleanup, "filename1: write(2) failed");
93 
94 		SAFE_CLOSE(cleanup, fd0);
95 		if ((fd0 = open(filename0, O_RDONLY)) == -1)
96 			tst_brkm(TBROK, cleanup, "open(2) on filename0 failed");
97 
98 		SAFE_CLOSE(cleanup, fd1);
99 		if ((fd1 = open(filename1, O_RDONLY)) == -1)
100 			tst_brkm(TBROK, cleanup, "open(2) on filename1 failed");
101 
102 		TEST(dup2(fd0, fd1));
103 
104 		if ((fd2 = TEST_RETURN) == -1) {
105 			tst_resm(TFAIL, "call failed unexpectedly");
106 		} else {
107 			if (fd1 != fd2) {
108 				tst_resm(TFAIL, "file descriptors don't match");
109 				break;
110 			}
111 
112 			memset(buf, 0, sizeof(buf));
113 			if (read(fd2, buf, sizeof(buf)) == -1)
114 				tst_brkm(TBROK, cleanup, "read(2) failed");
115 			if (strcmp(buf, filename0) != 0)
116 				tst_resm(TFAIL, "read from file got bad data");
117 			tst_resm(TPASS, "dup2 test 1 functionality is correct");
118 		}
119 
120 		close(fd0);
121 		close(fd1);
122 		close(fd2);
123 		unlink(filename0);
124 		unlink(filename1);
125 
126 		tst_resm(TINFO, "Exit block 1");
127 
128 //block2:
129 		tst_resm(TINFO, "Enter block 2");
130 		tst_resm(TINFO, "Test close on exec flag");
131 
132 		sprintf(filename0, "dup02.%d\n", getpid());
133 		unlink(filename0);
134 
135 		if ((fd0 = creat(filename0, 0666)) == -1) {
136 			tst_brkm(TBROK, cleanup, "Cannot create first file");
137 		}
138 		if (fcntl(fd0, F_SETFD, 1) == -1) {
139 			tst_brkm(TBROK, cleanup, "setting close on exec flag "
140 				 "on fd0 failed");
141 		}
142 
143 		if ((fd2 = creat(filename1, 0666)) == -1) {
144 			tst_brkm(TBROK, cleanup, "Cannot create second file");
145 		}
146 
147 		/* SAFE_CLOSE() sets the fd to -1 avoid it here */
148 		rval = fd2;
149 		SAFE_CLOSE(cleanup, rval);
150 
151 		TEST(dup2(fd0, fd2));
152 
153 		if ((fd1 = TEST_RETURN) == -1) {
154 			tst_resm(TFAIL, "call failed unexpectedly");
155 		} else {
156 			if (fd1 != fd2) {
157 				tst_resm(TFAIL, "bad dup2 descriptor %d", fd1);
158 				break;
159 			}
160 
161 			if ((rval = fcntl(fd1, F_GETFD, 0)) != 0) {
162 				tst_resm(TBROK | TERRNO,
163 					 "fcntl F_GETFD on fd1 failed; expected a "
164 					 "return value of 0x0, got %#x", rval);
165 				break;
166 			}
167 			if ((rval = (fcntl(fd0, F_GETFL, 0) & O_ACCMODE)) !=
168 			    O_WRONLY) {
169 				tst_resm(TFAIL, "fctnl F_GETFL bad rval on fd0 "
170 					 "Expected %#x got %#x", O_WRONLY,
171 					 rval);
172 			}
173 			tst_resm(TPASS, "dup2 test 2 functionality is correct");
174 		}
175 
176 		close(fd0);
177 		close(fd1);
178 
179 		unlink(filename0);
180 		unlink(filename1);
181 		tst_resm(TINFO, "Exit block 2");
182 	}
183 
184 	cleanup();
185 	tst_exit();
186 }
187 
188 /*
189  * setup() - performs all ONE TIME setup for this test.
190  */
setup(void)191 void setup(void)
192 {
193 
194 	tst_sig(NOFORK, DEF_HANDLER, cleanup);
195 
196 	TEST_PAUSE;
197 
198 	tst_tmpdir();
199 }
200 
201 /*
202  * cleanup() - performs all ONE TIME cleanup for this test at
203  *	       completion or premature exit.
204  */
cleanup(void)205 void cleanup(void)
206 {
207 	tst_rmdir();
208 }
209