Home | History | Annotate | Download | only in open
      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 
    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 
    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 
    400 static void cleanup(void)
    401 {
    402 	tst_rmdir();
    403 }
    404