1 /*
2 * Copyright (C) 2013 Red Hat, Inc.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of version 2 of the GNU General Public
6 * License as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it
13 * is free of the rightful claim of any third person regarding
14 * infringement or the like. Any license provided herein, whether
15 * implied or otherwise, applies only to this software file. Patent
16 * licenses, if any, provided herein do not apply to combinations of
17 * this program with other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 * 02110-1301, USA.
23 */
24
25 /*
26 * Basic tests for open(2) and make sure open(2) works and handles error
27 * conditions correctly.
28 *
29 * There are 28 test cases:
30 * 1. Open regular file O_RDONLY
31 * 2. Open regular file O_WRONLY
32 * 3. Open regular file O_RDWR
33 * 4. Open regular file O_RDWR | O_SYNC
34 * 5. Open regular file O_RDWR | O_TRUNC
35 * 6. Open dir O_RDONLY
36 * 7. Open dir O_RDWR, expect EISDIR
37 * 8. Open regular file O_DIRECTORY, expect ENOTDIR
38 * 9. Open hard link file O_RDONLY
39 * 10. Open hard link file O_WRONLY
40 * 11. Open hard link file O_RDWR
41 * 12. Open sym link file O_RDONLY
42 * 13. Open sym link file O_WRONLY
43 * 14. Open sym link file O_RDWR
44 * 15. Open sym link dir O_RDONLY
45 * 16. Open sym link dir O_WRONLY, expect EISDIR
46 * 17. Open sym link dir O_RDWR, expect EISDIR
47 * 18. Open device special file O_RDONLY
48 * 19. Open device special file O_WRONLY
49 * 20. Open device special file O_RDWR
50 * 21. Open non-existing regular file in existing dir
51 * 22. Open link file O_RDONLY | O_CREAT
52 * 23. Open symlink file O_RDONLY | O_CREAT
53 * 24. Open regular file O_RDONLY | O_CREAT
54 * 25. Open symlink dir O_RDONLY | O_CREAT, expect EISDIR
55 * 26. Open dir O_RDONLY | O_CREAT, expect EISDIR
56 * 27. Open regular file O_RDONLY | O_TRUNC, behaviour is undefined but should
57 * not oops or hang
58 * 28. Open regular file(non-empty) O_RDONLY | O_TRUNC, behaviour is undefined
59 * but should not oops or hang
60 */
61
62 #define _GNU_SOURCE
63 #include "config.h"
64 #include <sys/types.h>
65 #include <sys/stat.h>
66 #include <sys/wait.h>
67 #include <errno.h>
68 #include <fcntl.h>
69 #include <unistd.h>
70 #include <signal.h>
71 #include <stdio.h>
72 #include <stdlib.h>
73 #include <string.h>
74
75 #include "test.h"
76
77 char *TCID = "open11";
78
79 /* Define test files */
80 #define T_REG "t_reg" /* regular file with content */
81 #define T_REG_EMPTY "t_reg_empty" /* empty regular file */
82 #define T_LINK_REG "t_link_reg" /* hard link to T_REG */
83 #define T_NEW_REG "t_new_reg" /* new regular file to be created */
84 #define T_SYMLINK_REG "t_symlink_reg" /* symlink to T_REG */
85 #define T_DIR "t_dir" /* test dir */
86 #define T_SYMLINK_DIR "t_symlink_dir" /* symlink to T_DIR */
87 #define T_DEV "t_dev" /* test device special file */
88
89 #define T_MSG "this is a test string"
90
91 static void setup(void);
92 static void cleanup(void);
93
94 struct test_case {
95 char *desc;
96 char *path;
97 int flags;
98 mode_t mode;
99 int err;
100 };
101 struct test_case tc[] = {
102 /*
103 * Test open(2) regular file
104 */
105 { /* open regular file O_RDONLY */
106 .desc = "Open regular file O_RDONLY",
107 .path = T_REG_EMPTY,
108 .flags = O_RDONLY,
109 .mode = 0644,
110 .err = 0,
111 },
112 { /* open regular file O_WRONLY */
113 .desc = "Open regular file O_WRONLY",
114 .path = T_REG_EMPTY,
115 .flags = O_WRONLY,
116 .mode = 0644,
117 .err = 0,
118 },
119 { /* open regular file O_RDWR */
120 .desc = "Open regular file O_RDWR",
121 .path = T_REG_EMPTY,
122 .flags = O_RDWR,
123 .mode = 0644,
124 .err = 0,
125 },
126 { /* open regular file O_RDWR | O_SYNC*/
127 .desc = "Open regular file O_RDWR | O_SYNC",
128 .path = T_REG_EMPTY,
129 .flags = O_RDWR | O_SYNC,
130 .mode = 0644,
131 .err = 0,
132 },
133 { /* open regular file O_RDWR | O_TRUNC */
134 .desc = "Open regular file O_RDWR | O_TRUNC",
135 .path = T_REG_EMPTY,
136 .flags = O_RDWR | O_TRUNC,
137 .mode = 0644,
138 .err = 0,
139 },
140 /*
141 * Test open(2) directory
142 */
143 { /* open dir O_RDONLY */
144 .desc = "Open dir O_RDONLY",
145 .path = T_DIR,
146 .flags = O_RDONLY,
147 .mode = 0755,
148 .err = 0,
149 },
150 { /* open dir O_RDWR */
151 .desc = "Open dir O_RDWR, expect EISDIR",
152 .path = T_DIR,
153 .flags = O_RDWR,
154 .mode = 0755,
155 .err = EISDIR,
156 },
157 { /* open regular file O_DIRECTORY */
158 .desc = "Open regular file O_DIRECTORY, expect ENOTDIR",
159 .path = T_REG_EMPTY,
160 .flags = O_RDONLY | O_DIRECTORY,
161 .mode = 0644,
162 .err = ENOTDIR,
163 },
164 /*
165 * Test open(2) hard link
166 */
167 { /* open hard link file O_RDONLY */
168 .desc = "Open hard link file O_RDONLY",
169 .path = T_LINK_REG,
170 .flags = O_RDONLY,
171 .mode = 0644,
172 .err = 0,
173 },
174 { /* open hard link file O_WRONLY */
175 .desc = "Open hard link file O_WRONLY",
176 .path = T_LINK_REG,
177 .flags = O_WRONLY,
178 .mode = 0644,
179 .err = 0,
180 },
181 { /* open hard link file O_RDWR */
182 .desc = "Open hard link file O_RDWR",
183 .path = T_LINK_REG,
184 .flags = O_RDWR,
185 .mode = 0644,
186 .err = 0,
187 },
188 /*
189 * Test open(2) sym link
190 */
191 { /* open sym link file O_RDONLY */
192 .desc = "Open sym link file O_RDONLY",
193 .path = T_SYMLINK_REG,
194 .flags = O_RDONLY,
195 .mode = 0644,
196 .err = 0,
197 },
198 { /* open sym link file O_WRONLY */
199 .desc = "Open sym link file O_WRONLY",
200 .path = T_SYMLINK_REG,
201 .flags = O_WRONLY,
202 .mode = 0644,
203 .err = 0,
204 },
205 { /* open sym link file O_RDWR */
206 .desc = "Open sym link file O_RDWR",
207 .path = T_SYMLINK_REG,
208 .flags = O_RDWR,
209 .mode = 0644,
210 .err = 0,
211 },
212 { /* open sym link dir O_RDONLY */
213 .desc = "Open sym link dir O_RDONLY",
214 .path = T_SYMLINK_DIR,
215 .flags = O_RDONLY,
216 .mode = 0644,
217 .err = 0,
218 },
219 { /* open sym link dir O_WRONLY */
220 .desc = "Open sym link dir O_WRONLY, expect EISDIR",
221 .path = T_SYMLINK_DIR,
222 .flags = O_WRONLY,
223 .mode = 0644,
224 .err = EISDIR,
225 },
226 { /* open sym link dir O_RDWR */
227 .desc = "Open sym link dir O_RDWR, expect EISDIR",
228 .path = T_SYMLINK_DIR,
229 .flags = O_RDWR,
230 .mode = 0644,
231 .err = EISDIR,
232 },
233 /*
234 * Test open(2) device special
235 */
236 { /* open device special file O_RDONLY */
237 .desc = "Open device special file O_RDONLY",
238 .path = T_DEV,
239 .flags = O_RDONLY,
240 .mode = 0644,
241 .err = 0,
242 },
243 { /* open device special file O_WRONLY */
244 .desc = "Open device special file O_WRONLY",
245 .path = T_DEV,
246 .flags = O_WRONLY,
247 .mode = 0644,
248 .err = 0,
249 },
250 { /* open device special file O_RDWR */
251 .desc = "Open device special file O_RDWR",
252 .path = T_DEV,
253 .flags = O_RDWR,
254 .mode = 0644,
255 .err = 0,
256 },
257 /*
258 * Test open(2) non-existing file
259 */
260 { /* open non-existing regular file in existing dir */
261 .desc = "Open non-existing regular file in existing dir",
262 .path = T_DIR"/"T_NEW_REG,
263 .flags = O_RDWR | O_CREAT,
264 .mode = 0644,
265 .err = 0,
266 },
267 /*
268 * test open(2) with O_CREAT
269 */
270 { /* open hard link file O_RDONLY | O_CREAT */
271 .desc = "Open link file O_RDONLY | O_CREAT",
272 .path = T_LINK_REG,
273 .flags = O_RDONLY | O_CREAT,
274 .mode = 0644,
275 .err = 0,
276 },
277 { /* open sym link file O_RDONLY | O_CREAT */
278 .desc = "Open symlink file O_RDONLY | O_CREAT",
279 .path = T_SYMLINK_REG,
280 .flags = O_RDONLY | O_CREAT,
281 .mode = 0644,
282 .err = 0,
283 },
284 { /* open regular file O_RDONLY | O_CREAT */
285 .desc = "Open regular file O_RDONLY | O_CREAT",
286 .path = T_REG_EMPTY,
287 .flags = O_RDONLY | O_CREAT,
288 .mode = 0644,
289 .err = 0,
290 },
291 { /* open symlink dir O_RDONLY | O_CREAT */
292 .desc = "Open symlink dir O_RDONLY | O_CREAT, expect EISDIR",
293 .path = T_SYMLINK_DIR,
294 .flags = O_RDONLY | O_CREAT,
295 .mode = 0644,
296 .err = EISDIR,
297 },
298 { /* open dir O_RDONLY | O_CREAT */
299 .desc = "Open dir O_RDONLY | O_CREAT, expect EISDIR",
300 .path = T_DIR,
301 .flags = O_RDONLY | O_CREAT,
302 .mode = 0644,
303 .err = EISDIR,
304 },
305 /*
306 * Other random open(2) tests
307 */
308 { /* open regular file O_RDONLY | O_TRUNC */
309 .desc = "Open regular file O_RDONLY | O_TRUNC, "
310 "behaviour is undefined but should not oops or hang",
311 .path = T_REG_EMPTY,
312 .flags = O_RDONLY | O_TRUNC,
313 .mode = 0644,
314 .err = -1,
315 },
316 { /* open regular(non-empty) file O_RDONLY | O_TRUNC */
317 .desc = "Open regular file(non-empty) O_RDONLY | O_TRUNC, "
318 "behaviour is undefined but should not oops or hang",
319 .path = T_REG,
320 .flags = O_RDONLY | O_TRUNC,
321 .mode = 0644,
322 .err = -1,
323 },
324 };
325
326 int TST_TOTAL = sizeof(tc) / sizeof(tc[0]);
327
main(int argc,char * argv[])328 int main(int argc, char *argv[])
329 {
330 int lc;
331 int i;
332 int fd;
333 int ret;
334
335 tst_parse_opts(argc, argv, NULL, NULL);
336
337 setup();
338
339 for (lc = 0; TEST_LOOPING(lc); lc++) {
340 for (i = 0; i < TST_TOTAL; i++) {
341 TEST(open(tc[i].path, tc[i].flags, tc[i].mode));
342 fd = TEST_RETURN;
343
344 if (tc[i].err == -1 || TEST_ERRNO == tc[i].err) {
345 tst_resm(TPASS, "%s", tc[i].desc);
346 } else {
347 tst_resm(TFAIL | TTERRNO,
348 "%s - expected errno %d - Got",
349 tc[i].desc, tc[i].err);
350 }
351 if (fd > 0) {
352 ret = close(fd);
353 if (ret < 0)
354 tst_resm(TWARN, "%s - close failed: %s",
355 tc[i].desc, strerror(errno));
356 }
357 }
358 }
359
360 cleanup();
361 tst_exit();
362 }
363
setup(void)364 static void setup(void)
365 {
366 int fd;
367 int ret;
368
369 tst_require_root();
370
371 tst_tmpdir();
372
373 /* Create test files */
374 fd = open(T_REG, O_WRONLY | O_CREAT, 0644);
375 if (fd == -1)
376 tst_brkm(TBROK | TERRNO, cleanup, "Create %s failed", T_REG);
377 ret = write(fd, T_MSG, sizeof(T_MSG));
378 if (ret == -1) {
379 close(fd);
380 tst_brkm(TBROK | TERRNO, cleanup, "Write %s failed", T_REG);
381 }
382 close(fd);
383
384 fd = creat(T_REG_EMPTY, 0644);
385 if (fd == -1)
386 tst_brkm(TBROK | TERRNO, cleanup, "Create %s failed",
387 T_REG_EMPTY);
388 close(fd);
389
390 ret = link(T_REG, T_LINK_REG);
391 if (ret == -1)
392 tst_brkm(TBROK | TERRNO, cleanup, "Hard link %s -> %s failed",
393 T_REG, T_LINK_REG);
394
395 ret = symlink(T_REG, T_SYMLINK_REG);
396 if (ret == -1)
397 tst_brkm(TBROK | TERRNO, cleanup, "Symlink %s -> %s failed",
398 T_REG, T_SYMLINK_REG);
399
400 ret = mkdir(T_DIR, 0755);
401 if (ret == -1)
402 tst_brkm(TBROK | TERRNO, cleanup, "mkdir %s failed", T_DIR);
403
404 ret = symlink(T_DIR, T_SYMLINK_DIR);
405 if (ret == -1)
406 tst_brkm(TBROK | TERRNO, cleanup, "Symlink %s -> %s failed",
407 T_DIR, T_SYMLINK_DIR);
408
409 ret = mknod(T_DEV, S_IFCHR, makedev(1, 5));
410 if (ret == -1)
411 tst_brkm(TBROK | TERRNO, cleanup, "Create char dev %s failed",
412 T_DEV);
413
414 TEST_PAUSE;
415 }
416
cleanup(void)417 static void cleanup(void)
418 {
419 tst_rmdir();
420 }
421