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  *	dup202.c
23  *
24  * DESCRIPTION
25  *	Is the access mode the same for both file descriptors?
26  *		0: read only ?	"0444"
27  *		1: write only ? "0222"
28  *		2: read/write ? "0666"
29  *
30  * ALGORITHM
31  *	Creat a file with each access mode; dup each file descriptor;
32  *	stat each file descriptor and compare modes of each pair
33  *
34  * USAGE:  <for command-line>
35  *  dup202 [-c n] [-f] [-i n] [-I x] [-P x] [-t]
36  *     where,  -c n : Run n copies concurrently.
37  *             -f   : Turn off functionality Testing.
38  *             -i n : Execute test n times.
39  *             -I x : Execute test for x seconds.
40  *             -P x : Pause for x seconds between iterations.
41  *             -t   : Turn on syscall timing.
42  *
43  * HISTORY
44  *	07/2001 Ported by Wayne Boyer
45  *
46  * RESTRICTIONS
47  *	None
48  */
49 
50 #include <sys/types.h>
51 #include <sys/stat.h>
52 #include <errno.h>
53 #include <fcntl.h>
54 #include <stdio.h>
55 #include "test.h"
56 
57 char *TCID = "dup202";
58 int TST_TOTAL = 3;
59 
60 void setup(void);
61 void cleanup(void);
62 
63 char testfile[40];
64 int fail;
65 int newfd;
66 
67 /* set these to a known index into our local file descriptor table */
68 int duprdo = 10, dupwro = 20, duprdwr = 30;
69 
70 struct test_case_t {
71 	int *nfd;
72 	mode_t mode;
73 } TC[] = {
74 	/* The first test creat(es) a file with mode 0444 */
75 	{
76 	&duprdo, (S_IRUSR | S_IRGRP | S_IROTH)},
77 	    /* The second test creat(es) a file with mode 0222 */
78 	{
79 	&dupwro, (S_IWUSR | S_IWGRP | S_IWOTH)},
80 	    /* The third test creat(es) a file with mode 0666 */
81 	{
82 	&duprdwr,
83 		    (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH)}
84 };
85 
main(int ac,char ** av)86 int main(int ac, char **av)
87 {
88 	int lc;
89 	int i, ofd;
90 	struct stat oldbuf, newbuf;
91 
92 	tst_parse_opts(ac, av, NULL, NULL);
93 
94 	setup();
95 
96 	for (lc = 0; TEST_LOOPING(lc); lc++) {
97 
98 		tst_count = 0;
99 
100 		/* loop through the test cases */
101 		for (i = 0; i < TST_TOTAL; i++) {
102 
103 			if ((ofd = creat(testfile, TC[i].mode)) == -1)
104 				tst_brkm(TBROK | TERRNO, cleanup,
105 					 "creat failed");
106 
107 			TEST(dup2(ofd, *TC[i].nfd));
108 
109 			if (TEST_RETURN == -1) {
110 				tst_resm(TFAIL | TERRNO,
111 					 "call failed unexpectedly");
112 				continue;
113 			}
114 
115 			/* stat the original file */
116 			if (fstat(ofd, &oldbuf) == -1)
117 				tst_brkm(TBROK | TERRNO, cleanup,
118 					 "fstat #1 failed");
119 
120 			/* stat the duped file */
121 			if (fstat(*TC[i].nfd, &newbuf) == -1)
122 				tst_brkm(TBROK | TERRNO, cleanup,
123 					 "fstat #2 failed");
124 
125 			if (oldbuf.st_mode != newbuf.st_mode)
126 				tst_resm(TFAIL, "original and dup "
127 					 "modes do not match");
128 			else
129 				tst_resm(TPASS, "fstat shows new and "
130 					 "old modes are the same");
131 
132 			/* remove the file so that we can use it again */
133 			if (close(*TC[i].nfd) == -1)
134 				perror("close failed");
135 			if (close(ofd) == -1)
136 				perror("close failed");
137 			if (unlink(testfile) == -1)
138 				perror("unlink failed");
139 		}
140 	}
141 
142 	cleanup();
143 	tst_exit();
144 }
145 
146 /*
147  * setup() - performs all ONE TIME setup for this test.
148  */
setup(void)149 void setup(void)
150 {
151 
152 	tst_sig(NOFORK, DEF_HANDLER, cleanup);
153 
154 	TEST_PAUSE;
155 
156 	tst_tmpdir();
157 
158 	(void)umask(0);
159 
160 	sprintf(testfile, "dup202.%d", getpid());
161 }
162 
163 /*
164  * cleanup() - performs all ONE TIME cleanup for this test at
165  *	       completion or premature exit.
166  */
cleanup(void)167 void cleanup(void)
168 {
169 	tst_rmdir();
170 }
171