• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2013 Red Hat, Inc.
4  *
5  * Basic tests for open(2) and make sure open(2) works and handles error
6  * conditions correctly.
7  *
8  * There are 28 test cases:
9  * 1. Open regular file O_RDONLY
10  * 2. Open regular file O_WRONLY
11  * 3. Open regular file O_RDWR
12  * 4. Open regular file O_RDWR | O_SYNC
13  * 5. Open regular file O_RDWR | O_TRUNC
14  * 6. Open dir O_RDONLY
15  * 7. Open dir O_RDWR, expect EISDIR
16  * 8. Open regular file O_DIRECTORY, expect ENOTDIR
17  * 9. Open hard link file O_RDONLY
18  * 10. Open hard link file O_WRONLY
19  * 11. Open hard link file O_RDWR
20  * 12. Open sym link file O_RDONLY
21  * 13. Open sym link file O_WRONLY
22  * 14. Open sym link file O_RDWR
23  * 15. Open sym link dir O_RDONLY
24  * 16. Open sym link dir O_WRONLY, expect EISDIR
25  * 17. Open sym link dir O_RDWR, expect EISDIR
26  * 18. Open device special file O_RDONLY
27  * 19. Open device special file O_WRONLY
28  * 20. Open device special file O_RDWR
29  * 21. Open non-existing regular file in existing dir
30  * 22. Open link file O_RDONLY | O_CREAT
31  * 23. Open symlink file O_RDONLY | O_CREAT
32  * 24. Open regular file O_RDONLY | O_CREAT
33  * 25. Open symlink dir O_RDONLY | O_CREAT, expect EISDIR
34  * 26. Open dir O_RDONLY | O_CREAT, expect EISDIR
35  * 27. Open regular file O_RDONLY | O_TRUNC, behaviour is undefined but should
36  *     not oops or hang
37  * 28. Open regular file(non-empty) O_RDONLY | O_TRUNC, behaviour is undefined
38  *     but should not oops or hang
39  */
40 
41 #define _GNU_SOURCE
42 #include <errno.h>
43 #include <sys/sysmacros.h>
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #include <fcntl.h>
47 #include <unistd.h>
48 
49 #include "tst_test.h"
50 
51 #define MNTPOINT "mntpoint"
52 #define T_REG "t_reg"			/* regular file with content */
53 #define T_REG_EMPTY "t_reg_empty"	/* empty regular file */
54 #define T_LINK_REG "t_link_reg"		/* hard link to T_REG */
55 #define T_NEW_REG "t_new_reg"		/* new regular file to be created */
56 #define T_SYMLINK_REG "t_symlink_reg"	/* symlink to T_REG */
57 #define T_DIR "t_dir"			/* test dir */
58 #define T_SYMLINK_DIR "t_symlink_dir"	/* symlink to T_DIR */
59 #define T_DEV MNTPOINT"/t_dev"		/* test device special file */
60 
61 #define T_MSG "this is a test string"
62 
63 static struct test_case {
64 	char *desc;
65 	char *path;
66 	int flags;
67 	mode_t mode;
68 	int err;
69 } tc[] = {
70 	/* Test open(2) regular file */
71 	{	/* open regular file O_RDONLY */
72 		.desc = "Open regular file O_RDONLY",
73 		.path = T_REG_EMPTY,
74 		.flags = O_RDONLY,
75 		.mode = 0644,
76 		.err = 0,
77 	},
78 	{	/* open regular file O_WRONLY */
79 		.desc = "Open regular file O_WRONLY",
80 		.path = T_REG_EMPTY,
81 		.flags = O_WRONLY,
82 		.mode = 0644,
83 		.err = 0,
84 	},
85 	{	/* open regular file O_RDWR */
86 		.desc = "Open regular file O_RDWR",
87 		.path = T_REG_EMPTY,
88 		.flags = O_RDWR,
89 		.mode = 0644,
90 		.err = 0,
91 	},
92 	{	/* open regular file O_RDWR | O_SYNC*/
93 		.desc = "Open regular file O_RDWR | O_SYNC",
94 		.path = T_REG_EMPTY,
95 		.flags = O_RDWR | O_SYNC,
96 		.mode = 0644,
97 		.err = 0,
98 	},
99 	{	/* open regular file O_RDWR | O_TRUNC */
100 		.desc = "Open regular file O_RDWR | O_TRUNC",
101 		.path = T_REG_EMPTY,
102 		.flags = O_RDWR | O_TRUNC,
103 		.mode = 0644,
104 		.err = 0,
105 	},
106 	/* Test open(2) directory */
107 	{	/* open dir O_RDONLY */
108 		.desc = "Open dir O_RDONLY",
109 		.path = T_DIR,
110 		.flags = O_RDONLY,
111 		.mode = 0755,
112 		.err = 0,
113 	},
114 	{	/* open dir O_RDWR */
115 		.desc = "Open dir O_RDWR, expect EISDIR",
116 		.path = T_DIR,
117 		.flags = O_RDWR,
118 		.mode = 0755,
119 		.err = EISDIR,
120 	},
121 	{	/* open regular file O_DIRECTORY */
122 		.desc = "Open regular file O_DIRECTORY, expect ENOTDIR",
123 		.path = T_REG_EMPTY,
124 		.flags = O_RDONLY | O_DIRECTORY,
125 		.mode = 0644,
126 		.err = ENOTDIR,
127 	},
128 	/* Test open(2) hard link */
129 	{	/* open hard link file O_RDONLY */
130 		.desc = "Open hard link file O_RDONLY",
131 		.path = T_LINK_REG,
132 		.flags = O_RDONLY,
133 		.mode = 0644,
134 		.err = 0,
135 	},
136 	{	/* open hard link file O_WRONLY */
137 		.desc = "Open hard link file O_WRONLY",
138 		.path = T_LINK_REG,
139 		.flags = O_WRONLY,
140 		.mode = 0644,
141 		.err = 0,
142 	},
143 	{	/* open hard link file O_RDWR */
144 		.desc = "Open hard link file O_RDWR",
145 		.path = T_LINK_REG,
146 		.flags = O_RDWR,
147 		.mode = 0644,
148 		.err = 0,
149 	},
150 	/* Test open(2) sym link */
151 	{	/* open sym link file O_RDONLY */
152 		.desc = "Open sym link file O_RDONLY",
153 		.path = T_SYMLINK_REG,
154 		.flags = O_RDONLY,
155 		.mode = 0644,
156 		.err = 0,
157 	},
158 	{	/* open sym link file O_WRONLY */
159 		.desc = "Open sym link file O_WRONLY",
160 		.path = T_SYMLINK_REG,
161 		.flags = O_WRONLY,
162 		.mode = 0644,
163 		.err = 0,
164 	},
165 	{	/* open sym link file O_RDWR */
166 		.desc = "Open sym link file O_RDWR",
167 		.path = T_SYMLINK_REG,
168 		.flags = O_RDWR,
169 		.mode = 0644,
170 		.err = 0,
171 	},
172 	{	/* open sym link dir O_RDONLY */
173 		.desc = "Open sym link dir O_RDONLY",
174 		.path = T_SYMLINK_DIR,
175 		.flags = O_RDONLY,
176 		.mode = 0644,
177 		.err = 0,
178 	},
179 	{	/* open sym link dir O_WRONLY */
180 		.desc = "Open sym link dir O_WRONLY, expect EISDIR",
181 		.path = T_SYMLINK_DIR,
182 		.flags = O_WRONLY,
183 		.mode = 0644,
184 		.err = EISDIR,
185 	},
186 	{	/* open sym link dir O_RDWR */
187 		.desc = "Open sym link dir O_RDWR, expect EISDIR",
188 		.path = T_SYMLINK_DIR,
189 		.flags = O_RDWR,
190 		.mode = 0644,
191 		.err = EISDIR,
192 	},
193 	/* * Test open(2) device special */
194 	{	/* open device special file O_RDONLY */
195 		.desc = "Open device special file O_RDONLY",
196 		.path = T_DEV,
197 		.flags = O_RDONLY,
198 		.mode = 0644,
199 		.err = 0,
200 	},
201 	{	/* open device special file O_WRONLY */
202 		.desc = "Open device special file O_WRONLY",
203 		.path = T_DEV,
204 		.flags = O_WRONLY,
205 		.mode = 0644,
206 		.err = 0,
207 	},
208 	{	/* open device special file O_RDWR */
209 		.desc = "Open device special file O_RDWR",
210 		.path = T_DEV,
211 		.flags = O_RDWR,
212 		.mode = 0644,
213 		.err = 0,
214 	},
215 	/* * Test open(2) non-existing file */
216 	{	/* open non-existing regular file in existing dir */
217 		.desc = "Open non-existing regular file in existing dir",
218 		.path = T_DIR"/"T_NEW_REG,
219 		.flags = O_RDWR | O_CREAT,
220 		.mode = 0644,
221 		.err = 0,
222 	},
223 	/* test open(2) with O_CREAT */
224 	{	/* open hard link file O_RDONLY | O_CREAT */
225 		.desc = "Open link file O_RDONLY | O_CREAT",
226 		.path = T_LINK_REG,
227 		.flags = O_RDONLY | O_CREAT,
228 		.mode = 0644,
229 		.err = 0,
230 	},
231 	{	/* open sym link file O_RDONLY | O_CREAT */
232 		.desc = "Open symlink file O_RDONLY | O_CREAT",
233 		.path = T_SYMLINK_REG,
234 		.flags = O_RDONLY | O_CREAT,
235 		.mode = 0644,
236 		.err = 0,
237 	},
238 	{	/* open regular file O_RDONLY | O_CREAT */
239 		.desc = "Open regular file O_RDONLY | O_CREAT",
240 		.path = T_REG_EMPTY,
241 		.flags = O_RDONLY | O_CREAT,
242 		.mode = 0644,
243 		.err = 0,
244 	},
245 	{	/* open symlink dir O_RDONLY | O_CREAT */
246 		.desc = "Open symlink dir O_RDONLY | O_CREAT, expect EISDIR",
247 		.path = T_SYMLINK_DIR,
248 		.flags = O_RDONLY | O_CREAT,
249 		.mode = 0644,
250 		.err = EISDIR,
251 	},
252 	{	/* open dir O_RDONLY | O_CREAT */
253 		.desc = "Open dir O_RDONLY | O_CREAT, expect EISDIR",
254 		.path = T_DIR,
255 		.flags = O_RDONLY | O_CREAT,
256 		.mode = 0644,
257 		.err = EISDIR,
258 	},
259 	/* Other random open(2) tests */
260 	{	/* open regular file O_RDONLY | O_TRUNC */
261 		.desc = "Open regular file O_RDONLY | O_TRUNC, "
262 			"behaviour is undefined but should not oops or hang",
263 		.path = T_REG_EMPTY,
264 		.flags = O_RDONLY | O_TRUNC,
265 		.mode = 0644,
266 		.err = -1,
267 	},
268 	{	/* open regular(non-empty) file O_RDONLY | O_TRUNC */
269 		.desc = "Open regular file(non-empty) O_RDONLY | O_TRUNC, "
270 			"behaviour is undefined but should not oops or hang",
271 		.path = T_REG,
272 		.flags = O_RDONLY | O_TRUNC,
273 		.mode = 0644,
274 		.err = -1,
275 	},
276 };
277 
verify_open(unsigned int n)278 static void verify_open(unsigned int n)
279 {
280 	if (tc[n].err > 0) {
281 		TST_EXP_FAIL2(open(tc[n].path, tc[n].flags, tc[n].mode),
282 		             tc[n].err, "%s", tc[n].desc);
283 	} else if (tc[n].err == 0) {
284 		TST_EXP_FD(open(tc[n].path, tc[n].flags, tc[n].mode),
285 		           "%s", tc[n].desc);
286 	} else {
287 		TEST(open(tc[n].path, tc[n].flags, tc[n].mode));
288 		tst_res(TPASS, "%s", tc[n].desc);
289 	}
290 
291 	if (TST_RET > 0)
292 		SAFE_CLOSE(TST_RET);
293 }
294 
setup(void)295 static void setup(void)
296 {
297 	int fd;
298 	int ret;
299 
300 	fd = SAFE_OPEN(T_REG, O_WRONLY | O_CREAT, 0644);
301 	ret = write(fd, T_MSG, sizeof(T_MSG));
302 	if (ret == -1) {
303 		SAFE_CLOSE(fd);
304 		tst_brk(TBROK | TERRNO, "Write %s failed", T_REG);
305 	}
306 	SAFE_CLOSE(fd);
307 
308 	SAFE_TOUCH(T_REG_EMPTY, 0644, NULL);
309 	SAFE_LINK(T_REG, T_LINK_REG);
310 	SAFE_SYMLINK(T_REG, T_SYMLINK_REG);
311 	SAFE_MKDIR(T_DIR, 0755);
312 	SAFE_SYMLINK(T_DIR, T_SYMLINK_DIR);
313 	SAFE_MKNOD(T_DEV, S_IFCHR, makedev(1, 5));
314 }
315 
316 static struct tst_test test = {
317 	.tcnt = ARRAY_SIZE(tc),
318 	.setup = setup,
319 	.test = verify_open,
320 	.needs_devfs = 1,
321 	.mntpoint = MNTPOINT,
322 	.needs_root = 1,
323 };
324