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