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 * open07.c
23 *
24 * DESCRIPTION
25 * Test the open(2) system call to ensure that it sets ELOOP correctly.
26 *
27 * CALLS
28 * open()
29 *
30 * ALGORITHM
31 * 1. Create a symbolic link to a file, and call open(O_NOFOLLOW). Check
32 * that it returns ELOOP.
33 *
34 * 2. Create a symbolic link to a directory, and call open(O_NOFOLLOW).
35 * Check that it returns ELOOP.
36 *
37 * 3. Create a symbolic link to a symbolic link, and call open(O_NOFOLLOW).
38 * Check that it returns ELOOP.
39 *
40 * 4. Create a symbolic link to a symbolically linked directory, and call
41 * open(O_NOFOLLOW). Check that it returns ELOOP.
42 *
43 * 5. Create a symbolic link to a directory, and call
44 * open("link/", O_NOFOLLOW). Check that it succeeds.
45 *
46 * USAGE: <for command-line>
47 * open07 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
48 * where, -c n : Run n copies concurrently.
49 * -e : Turn on errno logging.
50 * -i n : Execute test n times.
51 * -I x : Execute test for x seconds.
52 * -P x : Pause for x seconds between iterations.
53 * -t : Turn on syscall timing.
54 *
55 * HISTORY
56 * 07/2001 Ported by Wayne Boyer
57 *
58 * RESTRICTIONS
59 * None
60 */
61 #define _GNU_SOURCE /* for O_NOFOLLOW */
62 #include <stdio.h>
63 #include <errno.h>
64 #include <sys/types.h>
65 #include <sys/stat.h>
66 #include <fcntl.h>
67 #include "test.h"
68 #include "safe_macros.h"
69
70 static void setup(void);
71 static void cleanup(void);
72 static void setupfunc_test1();
73 static void setupfunc_test2();
74 static void setupfunc_test3();
75 static void setupfunc_test4();
76 static void setupfunc_test5();
77
78 char *TCID = "open07";
79 int TST_TOTAL = 5;
80
81 static int fd1, fd2;
82
83 static struct test_case_t {
84 char *desc;
85 char filename[100];
86 int flags;
87 int mode;
88 void (*setupfunc) ();
89 int exp_errno;
90 } TC[] = {
91 {"Test for ELOOP on f2: f1 -> f2", {},
92 O_NOFOLLOW, 00700, setupfunc_test1, ELOOP},
93 {"Test for ELOOP on d2: d1 -> d2", {},
94 O_NOFOLLOW, 00700, setupfunc_test2, ELOOP},
95 {"Test for ELOOP on f3: f1 -> f2 -> f3", {},
96 O_NOFOLLOW, 00700, setupfunc_test3, ELOOP},
97 {"Test for ELOOP on d3: d1 -> d2 -> d3", {},
98 O_NOFOLLOW, 00700, setupfunc_test4, ELOOP},
99 {"Test for success on d2: d1 -> d2", {},
100 O_NOFOLLOW, 00700, setupfunc_test5, 0},
101 {NULL, {}, 0, 0, NULL, 0}
102 };
103
main(int ac,char ** av)104 int main(int ac, char **av)
105 {
106 int lc;
107 int i;
108
109 tst_parse_opts(ac, av, NULL, NULL);
110
111 setup();
112
113 /* run the setup routines for the individual tests */
114 for (i = 0; i < TST_TOTAL; i++) {
115 if (TC[i].setupfunc != NULL)
116 TC[i].setupfunc();
117 }
118
119 for (lc = 0; TEST_LOOPING(lc); lc++) {
120 tst_count = 0;
121
122 for (i = 0; TC[i].desc != NULL; ++i) {
123 TEST(open(TC[i].filename, TC[i].flags, TC[i].mode));
124
125 if (TC[i].exp_errno != 0) {
126 if (TEST_RETURN != -1) {
127 tst_resm(TFAIL, "open succeeded "
128 "unexpectedly");
129 }
130
131 if (TEST_ERRNO != TC[i].exp_errno) {
132 tst_resm(TFAIL, "open returned "
133 "unexpected errno, expected: "
134 "%d, got: %d",
135 TC[i].exp_errno, TEST_ERRNO);
136 } else {
137 tst_resm(TPASS, "open returned "
138 "expected ELOOP error");
139 }
140 } else {
141 if (TEST_RETURN == -1) {
142 tst_resm(TFAIL, "open failed "
143 "unexpectedly with errno %d",
144 TEST_ERRNO);
145 } else {
146 tst_resm(TPASS, "open succeeded as "
147 "expected");
148 }
149 }
150
151 if (TEST_RETURN != -1)
152 close(TEST_RETURN);
153 }
154 }
155
156 cleanup();
157 tst_exit();
158 }
159
setupfunc_test1(void)160 static void setupfunc_test1(void)
161 {
162 char file1[100], file2[100];
163
164 sprintf(file1, "open03.1.%d", getpid());
165 sprintf(file2, "open03.2.%d", getpid());
166 fd1 = SAFE_CREAT(cleanup, file1, 00700);
167
168 SAFE_SYMLINK(cleanup, file1, file2);
169
170 strcpy(TC[0].filename, file2);
171 }
172
setupfunc_test2(void)173 static void setupfunc_test2(void)
174 {
175 char file1[100], file2[100];
176
177 sprintf(file1, "open03.3.%d", getpid());
178 sprintf(file2, "open03.4.%d", getpid());
179 SAFE_MKDIR(cleanup, file1, 00700);
180
181 SAFE_SYMLINK(cleanup, file1, file2);
182
183 strcpy(TC[1].filename, file2);
184 }
185
setupfunc_test3(void)186 static void setupfunc_test3(void)
187 {
188 char file1[100], file2[100], file3[100];
189
190 sprintf(file1, "open03.5.%d", getpid());
191 sprintf(file2, "open03.6.%d", getpid());
192 sprintf(file3, "open03.7.%d", getpid());
193 fd2 = SAFE_CREAT(cleanup, file1, 00700);
194
195 SAFE_SYMLINK(cleanup, file1, file2);
196
197 SAFE_SYMLINK(cleanup, file2, file3);
198
199 strcpy(TC[2].filename, file3);
200 }
201
setupfunc_test4(void)202 static void setupfunc_test4(void)
203 {
204 char file1[100], file2[100], file3[100];
205
206 sprintf(file1, "open03.8.%d", getpid());
207 sprintf(file2, "open03.9.%d", getpid());
208 sprintf(file3, "open03.10.%d", getpid());
209 SAFE_MKDIR(cleanup, file1, 00700);
210
211 SAFE_SYMLINK(cleanup, file1, file2);
212
213 SAFE_SYMLINK(cleanup, file2, file3);
214
215 strcpy(TC[3].filename, file3);
216 }
217
setupfunc_test5(void)218 static void setupfunc_test5(void)
219 {
220 char file1[100], file2[100];
221
222 sprintf(file1, "open11.3.%d", getpid());
223 sprintf(file2, "open12.4.%d", getpid());
224 SAFE_MKDIR(cleanup, file1, 00700);
225
226 SAFE_SYMLINK(cleanup, file1, file2);
227
228 strcpy(TC[4].filename, file2);
229 strcat(TC[4].filename, "/");
230 }
231
setup(void)232 static void setup(void)
233 {
234 umask(0);
235
236 tst_sig(NOFORK, DEF_HANDLER, cleanup);
237
238 TEST_PAUSE;
239
240 tst_tmpdir();
241 }
242
cleanup(void)243 static void cleanup(void)
244 {
245 close(fd1);
246 close(fd2);
247
248 tst_rmdir();
249 }
250