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