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/sysmacros.h>
67 #include <sys/wait.h>
68 #include <errno.h>
69 #include <fcntl.h>
70 #include <unistd.h>
71 #include <signal.h>
72 #include <stdio.h>
73 #include <stdlib.h>
74 #include <string.h>
75
76 #include "test.h"
77 #include "safe_macros.h"
78
79 char *TCID = "open11";
80
81 /* Define test files */
82 #define T_REG "t_reg" /* regular file with content */
83 #define T_REG_EMPTY "t_reg_empty" /* empty regular file */
84 #define T_LINK_REG "t_link_reg" /* hard link to T_REG */
85 #define T_NEW_REG "t_new_reg" /* new regular file to be created */
86 #define T_SYMLINK_REG "t_symlink_reg" /* symlink to T_REG */
87 #define T_DIR "t_dir" /* test dir */
88 #define T_SYMLINK_DIR "t_symlink_dir" /* symlink to T_DIR */
89 #define T_DEV "t_dev" /* test device special file */
90
91 #define T_MSG "this is a test string"
92
93 static void setup(void);
94 static void cleanup(void);
95
96 struct test_case {
97 char *desc;
98 char *path;
99 int flags;
100 mode_t mode;
101 int err;
102 };
103 struct test_case tc[] = {
104 /*
105 * Test open(2) regular file
106 */
107 { /* open regular file O_RDONLY */
108 .desc = "Open regular file O_RDONLY",
109 .path = T_REG_EMPTY,
110 .flags = O_RDONLY,
111 .mode = 0644,
112 .err = 0,
113 },
114 { /* open regular file O_WRONLY */
115 .desc = "Open regular file O_WRONLY",
116 .path = T_REG_EMPTY,
117 .flags = O_WRONLY,
118 .mode = 0644,
119 .err = 0,
120 },
121 { /* open regular file O_RDWR */
122 .desc = "Open regular file O_RDWR",
123 .path = T_REG_EMPTY,
124 .flags = O_RDWR,
125 .mode = 0644,
126 .err = 0,
127 },
128 { /* open regular file O_RDWR | O_SYNC*/
129 .desc = "Open regular file O_RDWR | O_SYNC",
130 .path = T_REG_EMPTY,
131 .flags = O_RDWR | O_SYNC,
132 .mode = 0644,
133 .err = 0,
134 },
135 { /* open regular file O_RDWR | O_TRUNC */
136 .desc = "Open regular file O_RDWR | O_TRUNC",
137 .path = T_REG_EMPTY,
138 .flags = O_RDWR | O_TRUNC,
139 .mode = 0644,
140 .err = 0,
141 },
142 /*
143 * Test open(2) directory
144 */
145 { /* open dir O_RDONLY */
146 .desc = "Open dir O_RDONLY",
147 .path = T_DIR,
148 .flags = O_RDONLY,
149 .mode = 0755,
150 .err = 0,
151 },
152 { /* open dir O_RDWR */
153 .desc = "Open dir O_RDWR, expect EISDIR",
154 .path = T_DIR,
155 .flags = O_RDWR,
156 .mode = 0755,
157 .err = EISDIR,
158 },
159 { /* open regular file O_DIRECTORY */
160 .desc = "Open regular file O_DIRECTORY, expect ENOTDIR",
161 .path = T_REG_EMPTY,
162 .flags = O_RDONLY | O_DIRECTORY,
163 .mode = 0644,
164 .err = ENOTDIR,
165 },
166 /*
167 * Test open(2) hard link
168 */
169 { /* open hard link file O_RDONLY */
170 .desc = "Open hard link file O_RDONLY",
171 .path = T_LINK_REG,
172 .flags = O_RDONLY,
173 .mode = 0644,
174 .err = 0,
175 },
176 { /* open hard link file O_WRONLY */
177 .desc = "Open hard link file O_WRONLY",
178 .path = T_LINK_REG,
179 .flags = O_WRONLY,
180 .mode = 0644,
181 .err = 0,
182 },
183 { /* open hard link file O_RDWR */
184 .desc = "Open hard link file O_RDWR",
185 .path = T_LINK_REG,
186 .flags = O_RDWR,
187 .mode = 0644,
188 .err = 0,
189 },
190 /*
191 * Test open(2) sym link
192 */
193 { /* open sym link file O_RDONLY */
194 .desc = "Open sym link file O_RDONLY",
195 .path = T_SYMLINK_REG,
196 .flags = O_RDONLY,
197 .mode = 0644,
198 .err = 0,
199 },
200 { /* open sym link file O_WRONLY */
201 .desc = "Open sym link file O_WRONLY",
202 .path = T_SYMLINK_REG,
203 .flags = O_WRONLY,
204 .mode = 0644,
205 .err = 0,
206 },
207 { /* open sym link file O_RDWR */
208 .desc = "Open sym link file O_RDWR",
209 .path = T_SYMLINK_REG,
210 .flags = O_RDWR,
211 .mode = 0644,
212 .err = 0,
213 },
214 { /* open sym link dir O_RDONLY */
215 .desc = "Open sym link dir O_RDONLY",
216 .path = T_SYMLINK_DIR,
217 .flags = O_RDONLY,
218 .mode = 0644,
219 .err = 0,
220 },
221 { /* open sym link dir O_WRONLY */
222 .desc = "Open sym link dir O_WRONLY, expect EISDIR",
223 .path = T_SYMLINK_DIR,
224 .flags = O_WRONLY,
225 .mode = 0644,
226 .err = EISDIR,
227 },
228 { /* open sym link dir O_RDWR */
229 .desc = "Open sym link dir O_RDWR, expect EISDIR",
230 .path = T_SYMLINK_DIR,
231 .flags = O_RDWR,
232 .mode = 0644,
233 .err = EISDIR,
234 },
235 /*
236 * Test open(2) device special
237 */
238 { /* open device special file O_RDONLY */
239 .desc = "Open device special file O_RDONLY",
240 .path = T_DEV,
241 .flags = O_RDONLY,
242 .mode = 0644,
243 .err = 0,
244 },
245 { /* open device special file O_WRONLY */
246 .desc = "Open device special file O_WRONLY",
247 .path = T_DEV,
248 .flags = O_WRONLY,
249 .mode = 0644,
250 .err = 0,
251 },
252 { /* open device special file O_RDWR */
253 .desc = "Open device special file O_RDWR",
254 .path = T_DEV,
255 .flags = O_RDWR,
256 .mode = 0644,
257 .err = 0,
258 },
259 /*
260 * Test open(2) non-existing file
261 */
262 { /* open non-existing regular file in existing dir */
263 .desc = "Open non-existing regular file in existing dir",
264 .path = T_DIR"/"T_NEW_REG,
265 .flags = O_RDWR | O_CREAT,
266 .mode = 0644,
267 .err = 0,
268 },
269 /*
270 * test open(2) with O_CREAT
271 */
272 { /* open hard link file O_RDONLY | O_CREAT */
273 .desc = "Open link file O_RDONLY | O_CREAT",
274 .path = T_LINK_REG,
275 .flags = O_RDONLY | O_CREAT,
276 .mode = 0644,
277 .err = 0,
278 },
279 { /* open sym link file O_RDONLY | O_CREAT */
280 .desc = "Open symlink file O_RDONLY | O_CREAT",
281 .path = T_SYMLINK_REG,
282 .flags = O_RDONLY | O_CREAT,
283 .mode = 0644,
284 .err = 0,
285 },
286 { /* open regular file O_RDONLY | O_CREAT */
287 .desc = "Open regular file O_RDONLY | O_CREAT",
288 .path = T_REG_EMPTY,
289 .flags = O_RDONLY | O_CREAT,
290 .mode = 0644,
291 .err = 0,
292 },
293 { /* open symlink dir O_RDONLY | O_CREAT */
294 .desc = "Open symlink dir O_RDONLY | O_CREAT, expect EISDIR",
295 .path = T_SYMLINK_DIR,
296 .flags = O_RDONLY | O_CREAT,
297 .mode = 0644,
298 .err = EISDIR,
299 },
300 { /* open dir O_RDONLY | O_CREAT */
301 .desc = "Open dir O_RDONLY | O_CREAT, expect EISDIR",
302 .path = T_DIR,
303 .flags = O_RDONLY | O_CREAT,
304 .mode = 0644,
305 .err = EISDIR,
306 },
307 /*
308 * Other random open(2) tests
309 */
310 { /* open regular file O_RDONLY | O_TRUNC */
311 .desc = "Open regular file O_RDONLY | O_TRUNC, "
312 "behaviour is undefined but should not oops or hang",
313 .path = T_REG_EMPTY,
314 .flags = O_RDONLY | O_TRUNC,
315 .mode = 0644,
316 .err = -1,
317 },
318 { /* open regular(non-empty) file O_RDONLY | O_TRUNC */
319 .desc = "Open regular file(non-empty) O_RDONLY | O_TRUNC, "
320 "behaviour is undefined but should not oops or hang",
321 .path = T_REG,
322 .flags = O_RDONLY | O_TRUNC,
323 .mode = 0644,
324 .err = -1,
325 },
326 };
327
328 int TST_TOTAL = sizeof(tc) / sizeof(tc[0]);
329
main(int argc,char * argv[])330 int main(int argc, char *argv[])
331 {
332 int lc;
333 int i;
334 int fd;
335 int ret;
336
337 tst_parse_opts(argc, argv, NULL, NULL);
338
339 setup();
340
341 for (lc = 0; TEST_LOOPING(lc); lc++) {
342 for (i = 0; i < TST_TOTAL; i++) {
343 TEST(open(tc[i].path, tc[i].flags, tc[i].mode));
344 fd = TEST_RETURN;
345
346 if (tc[i].err == -1 || TEST_ERRNO == tc[i].err) {
347 tst_resm(TPASS, "%s", tc[i].desc);
348 } else {
349 tst_resm(TFAIL | TTERRNO,
350 "%s - expected errno %d - Got",
351 tc[i].desc, tc[i].err);
352 }
353 if (fd > 0) {
354 ret = close(fd);
355 if (ret < 0)
356 tst_resm(TWARN, "%s - close failed: %s",
357 tc[i].desc, strerror(errno));
358 }
359 }
360 }
361
362 cleanup();
363 tst_exit();
364 }
365
setup(void)366 static void setup(void)
367 {
368 int fd;
369 int ret;
370
371 tst_require_root();
372
373 tst_tmpdir();
374
375 /* Create test files */
376 fd = SAFE_OPEN(cleanup, T_REG, O_WRONLY | O_CREAT, 0644);
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 = SAFE_CREAT(cleanup, T_REG_EMPTY, 0644);
385 close(fd);
386
387 SAFE_LINK(cleanup, T_REG, T_LINK_REG);
388 SAFE_SYMLINK(cleanup, T_REG, T_SYMLINK_REG);
389 SAFE_MKDIR(cleanup, T_DIR, 0755);
390 SAFE_SYMLINK(cleanup, T_DIR, T_SYMLINK_DIR);
391
392 ret = mknod(T_DEV, S_IFCHR, makedev(1, 5));
393 if (ret == -1)
394 tst_brkm(TBROK | TERRNO, cleanup, "Create char dev %s failed",
395 T_DEV);
396
397 TEST_PAUSE;
398 }
399
cleanup(void)400 static void cleanup(void)
401 {
402 tst_rmdir();
403 }
404