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/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 
    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 
    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 
    417 static void cleanup(void)
    418 {
    419 	tst_rmdir();
    420 }
    421