1 /* Copyright (c) 2007 The NetBSD Foundation, Inc. 2 * All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 14 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 15 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 20 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 24 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 25 26 #include "atf-c/detail/fs.h" 27 28 #include <sys/types.h> 29 #include <sys/stat.h> 30 31 #include <errno.h> 32 #include <fcntl.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <unistd.h> 37 38 #include <atf-c.h> 39 40 #include "atf-c/detail/test_helpers.h" 41 #include "atf-c/detail/user.h" 42 43 /* --------------------------------------------------------------------- 44 * Auxiliary functions. 45 * --------------------------------------------------------------------- */ 46 47 static 48 void 49 create_dir(const char *p, int mode) 50 { 51 int ret; 52 53 ret = mkdir(p, mode); 54 if (ret == -1) 55 atf_tc_fail("Could not create helper directory %s", p); 56 } 57 58 static 59 void 60 create_file(const char *p, int mode) 61 { 62 int fd; 63 64 fd = open(p, O_CREAT | O_WRONLY | O_TRUNC, mode); 65 if (fd == -1) 66 atf_tc_fail("Could not create helper file %s", p); 67 close(fd); 68 } 69 70 static 71 bool 72 exists(const atf_fs_path_t *p) 73 { 74 return access(atf_fs_path_cstring(p), F_OK) == 0; 75 } 76 77 static 78 atf_error_t 79 mkstemp_discard_fd(atf_fs_path_t *p) 80 { 81 int fd; 82 atf_error_t err = atf_fs_mkstemp(p, &fd); 83 if (!atf_is_error(err)) 84 close(fd); 85 return err; 86 } 87 88 /* --------------------------------------------------------------------- 89 * Test cases for the "atf_fs_path" type. 90 * --------------------------------------------------------------------- */ 91 92 ATF_TC(path_normalize); 93 ATF_TC_HEAD(path_normalize, tc) 94 { 95 atf_tc_set_md_var(tc, "descr", "Tests the path's normalization"); 96 } 97 ATF_TC_BODY(path_normalize, tc) 98 { 99 struct test { 100 const char *in; 101 const char *out; 102 } tests[] = { 103 { ".", ".", }, 104 { "..", "..", }, 105 106 { "/", "/", }, 107 { "//", "/", }, /* NO_CHECK_STYLE */ 108 { "///", "/", }, /* NO_CHECK_STYLE */ 109 110 { "foo", "foo", }, 111 { "foo/", "foo", }, 112 { "foo/bar", "foo/bar", }, 113 { "foo/bar/", "foo/bar", }, 114 115 { "/foo", "/foo", }, 116 { "/foo/bar", "/foo/bar", }, 117 { "/foo/bar/", "/foo/bar", }, 118 119 { "///foo", "/foo", }, /* NO_CHECK_STYLE */ 120 { "///foo///bar", "/foo/bar", }, /* NO_CHECK_STYLE */ 121 { "///foo///bar///", "/foo/bar", }, /* NO_CHECK_STYLE */ 122 123 { NULL, NULL } 124 }; 125 struct test *t; 126 127 for (t = &tests[0]; t->in != NULL; t++) { 128 atf_fs_path_t p; 129 130 printf("Input : >%s<\n", t->in); 131 printf("Expected output: >%s<\n", t->out); 132 133 RE(atf_fs_path_init_fmt(&p, "%s", t->in)); 134 printf("Output : >%s<\n", atf_fs_path_cstring(&p)); 135 ATF_REQUIRE(strcmp(atf_fs_path_cstring(&p), t->out) == 0); 136 atf_fs_path_fini(&p); 137 138 printf("\n"); 139 } 140 } 141 142 ATF_TC(path_copy); 143 ATF_TC_HEAD(path_copy, tc) 144 { 145 atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_path_copy constructor"); 146 } 147 ATF_TC_BODY(path_copy, tc) 148 { 149 atf_fs_path_t str, str2; 150 151 RE(atf_fs_path_init_fmt(&str, "foo")); 152 RE(atf_fs_path_copy(&str2, &str)); 153 154 ATF_REQUIRE(atf_equal_fs_path_fs_path(&str, &str2)); 155 156 RE(atf_fs_path_append_fmt(&str2, "bar")); 157 158 ATF_REQUIRE(!atf_equal_fs_path_fs_path(&str, &str2)); 159 160 atf_fs_path_fini(&str2); 161 atf_fs_path_fini(&str); 162 } 163 164 ATF_TC(path_is_absolute); 165 ATF_TC_HEAD(path_is_absolute, tc) 166 { 167 atf_tc_set_md_var(tc, "descr", "Tests the path::is_absolute function"); 168 } 169 ATF_TC_BODY(path_is_absolute, tc) 170 { 171 struct test { 172 const char *in; 173 bool abs; 174 } tests[] = { 175 { "/", true }, 176 { "////", true }, /* NO_CHECK_STYLE */ 177 { "////a", true }, /* NO_CHECK_STYLE */ 178 { "//a//", true }, /* NO_CHECK_STYLE */ 179 { "a////", false }, /* NO_CHECK_STYLE */ 180 { "../foo", false }, 181 { NULL, false }, 182 }; 183 struct test *t; 184 185 for (t = &tests[0]; t->in != NULL; t++) { 186 atf_fs_path_t p; 187 188 printf("Input : %s\n", t->in); 189 printf("Expected result: %s\n", t->abs ? "true" : "false"); 190 191 RE(atf_fs_path_init_fmt(&p, "%s", t->in)); 192 printf("Result : %s\n", 193 atf_fs_path_is_absolute(&p) ? "true" : "false"); 194 if (t->abs) 195 ATF_REQUIRE(atf_fs_path_is_absolute(&p)); 196 else 197 ATF_REQUIRE(!atf_fs_path_is_absolute(&p)); 198 atf_fs_path_fini(&p); 199 200 printf("\n"); 201 } 202 } 203 204 ATF_TC(path_is_root); 205 ATF_TC_HEAD(path_is_root, tc) 206 { 207 atf_tc_set_md_var(tc, "descr", "Tests the path::is_root function"); 208 } 209 ATF_TC_BODY(path_is_root, tc) 210 { 211 struct test { 212 const char *in; 213 bool root; 214 } tests[] = { 215 { "/", true }, 216 { "////", true }, /* NO_CHECK_STYLE */ 217 { "////a", false }, /* NO_CHECK_STYLE */ 218 { "//a//", false }, /* NO_CHECK_STYLE */ 219 { "a////", false }, /* NO_CHECK_STYLE */ 220 { "../foo", false }, 221 { NULL, false }, 222 }; 223 struct test *t; 224 225 for (t = &tests[0]; t->in != NULL; t++) { 226 atf_fs_path_t p; 227 228 printf("Input : %s\n", t->in); 229 printf("Expected result: %s\n", t->root ? "true" : "false"); 230 231 RE(atf_fs_path_init_fmt(&p, "%s", t->in)); 232 printf("Result : %s\n", 233 atf_fs_path_is_root(&p) ? "true" : "false"); 234 if (t->root) 235 ATF_REQUIRE(atf_fs_path_is_root(&p)); 236 else 237 ATF_REQUIRE(!atf_fs_path_is_root(&p)); 238 atf_fs_path_fini(&p); 239 240 printf("\n"); 241 } 242 } 243 244 ATF_TC(path_branch_path); 245 ATF_TC_HEAD(path_branch_path, tc) 246 { 247 atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_path_branch_path " 248 "function"); 249 } 250 ATF_TC_BODY(path_branch_path, tc) 251 { 252 struct test { 253 const char *in; 254 const char *branch; 255 } tests[] = { 256 { ".", "." }, 257 { "foo", "." }, 258 { "foo/bar", "foo" }, 259 { "/foo", "/" }, 260 { "/foo/bar", "/foo" }, 261 { NULL, NULL }, 262 }; 263 struct test *t; 264 265 for (t = &tests[0]; t->in != NULL; t++) { 266 atf_fs_path_t p, bp; 267 268 printf("Input : %s\n", t->in); 269 printf("Expected output: %s\n", t->branch); 270 271 RE(atf_fs_path_init_fmt(&p, "%s", t->in)); 272 RE(atf_fs_path_branch_path(&p, &bp)); 273 printf("Output : %s\n", atf_fs_path_cstring(&bp)); 274 ATF_REQUIRE(strcmp(atf_fs_path_cstring(&bp), t->branch) == 0); 275 atf_fs_path_fini(&bp); 276 atf_fs_path_fini(&p); 277 278 printf("\n"); 279 } 280 } 281 282 ATF_TC(path_leaf_name); 283 ATF_TC_HEAD(path_leaf_name, tc) 284 { 285 atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_path_leaf_name " 286 "function"); 287 } 288 ATF_TC_BODY(path_leaf_name, tc) 289 { 290 struct test { 291 const char *in; 292 const char *leaf; 293 } tests[] = { 294 { ".", "." }, 295 { "foo", "foo" }, 296 { "foo/bar", "bar" }, 297 { "/foo", "foo" }, 298 { "/foo/bar", "bar" }, 299 { NULL, NULL }, 300 }; 301 struct test *t; 302 303 for (t = &tests[0]; t->in != NULL; t++) { 304 atf_fs_path_t p; 305 atf_dynstr_t ln; 306 307 printf("Input : %s\n", t->in); 308 printf("Expected output: %s\n", t->leaf); 309 310 RE(atf_fs_path_init_fmt(&p, "%s", t->in)); 311 RE(atf_fs_path_leaf_name(&p, &ln)); 312 printf("Output : %s\n", atf_dynstr_cstring(&ln)); 313 ATF_REQUIRE(atf_equal_dynstr_cstring(&ln, t->leaf)); 314 atf_dynstr_fini(&ln); 315 atf_fs_path_fini(&p); 316 317 printf("\n"); 318 } 319 } 320 321 ATF_TC(path_append); 322 ATF_TC_HEAD(path_append, tc) 323 { 324 atf_tc_set_md_var(tc, "descr", "Tests the concatenation of multiple " 325 "paths"); 326 } 327 ATF_TC_BODY(path_append, tc) 328 { 329 struct test { 330 const char *in; 331 const char *ap; 332 const char *out; 333 } tests[] = { 334 { "foo", "bar", "foo/bar" }, 335 { "foo/", "/bar", "foo/bar" }, 336 { "foo/", "/bar/baz", "foo/bar/baz" }, 337 { "foo/", "///bar///baz", "foo/bar/baz" }, /* NO_CHECK_STYLE */ 338 339 { NULL, NULL, NULL } 340 }; 341 struct test *t; 342 343 for (t = &tests[0]; t->in != NULL; t++) { 344 atf_fs_path_t p; 345 346 printf("Input : >%s<\n", t->in); 347 printf("Append : >%s<\n", t->ap); 348 printf("Expected output: >%s<\n", t->out); 349 350 RE(atf_fs_path_init_fmt(&p, "%s", t->in)); 351 352 RE(atf_fs_path_append_fmt(&p, "%s", t->ap)); 353 354 printf("Output : >%s<\n", atf_fs_path_cstring(&p)); 355 ATF_REQUIRE(strcmp(atf_fs_path_cstring(&p), t->out) == 0); 356 357 atf_fs_path_fini(&p); 358 359 printf("\n"); 360 } 361 } 362 363 ATF_TC(path_to_absolute); 364 ATF_TC_HEAD(path_to_absolute, tc) 365 { 366 atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_path_to_absolute " 367 "function"); 368 } 369 ATF_TC_BODY(path_to_absolute, tc) 370 { 371 const char *names[] = { ".", "dir", NULL }; 372 const char **n; 373 374 ATF_REQUIRE(mkdir("dir", 0755) != -1); 375 376 for (n = names; *n != NULL; n++) { 377 atf_fs_path_t p, p2; 378 atf_fs_stat_t st1, st2; 379 380 RE(atf_fs_path_init_fmt(&p, "%s", *n)); 381 RE(atf_fs_stat_init(&st1, &p)); 382 printf("Relative path: %s\n", atf_fs_path_cstring(&p)); 383 384 RE(atf_fs_path_to_absolute(&p, &p2)); 385 printf("Absolute path: %s\n", atf_fs_path_cstring(&p2)); 386 387 ATF_REQUIRE(atf_fs_path_is_absolute(&p2)); 388 RE(atf_fs_stat_init(&st2, &p2)); 389 390 ATF_REQUIRE_EQ(atf_fs_stat_get_device(&st1), 391 atf_fs_stat_get_device(&st2)); 392 ATF_REQUIRE_EQ(atf_fs_stat_get_inode(&st1), 393 atf_fs_stat_get_inode(&st2)); 394 395 atf_fs_stat_fini(&st2); 396 atf_fs_stat_fini(&st1); 397 atf_fs_path_fini(&p2); 398 atf_fs_path_fini(&p); 399 400 printf("\n"); 401 } 402 } 403 404 ATF_TC(path_equal); 405 ATF_TC_HEAD(path_equal, tc) 406 { 407 atf_tc_set_md_var(tc, "descr", "Tests the equality operators for paths"); 408 } 409 ATF_TC_BODY(path_equal, tc) 410 { 411 atf_fs_path_t p1, p2; 412 413 RE(atf_fs_path_init_fmt(&p1, "foo")); 414 415 RE(atf_fs_path_init_fmt(&p2, "foo")); 416 ATF_REQUIRE(atf_equal_fs_path_fs_path(&p1, &p2)); 417 atf_fs_path_fini(&p2); 418 419 RE(atf_fs_path_init_fmt(&p2, "bar")); 420 ATF_REQUIRE(!atf_equal_fs_path_fs_path(&p1, &p2)); 421 atf_fs_path_fini(&p2); 422 423 atf_fs_path_fini(&p1); 424 } 425 426 /* --------------------------------------------------------------------- 427 * Test cases for the "atf_fs_stat" type. 428 * --------------------------------------------------------------------- */ 429 430 ATF_TC(stat_mode); 431 ATF_TC_HEAD(stat_mode, tc) 432 { 433 atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_stat_get_mode function " 434 "and, indirectly, the constructor"); 435 } 436 ATF_TC_BODY(stat_mode, tc) 437 { 438 atf_fs_path_t p; 439 atf_fs_stat_t st; 440 441 create_file("f1", 0400); 442 create_file("f2", 0644); 443 444 RE(atf_fs_path_init_fmt(&p, "f1")); 445 RE(atf_fs_stat_init(&st, &p)); 446 ATF_CHECK_EQ(0400, atf_fs_stat_get_mode(&st)); 447 atf_fs_stat_fini(&st); 448 atf_fs_path_fini(&p); 449 450 RE(atf_fs_path_init_fmt(&p, "f2")); 451 RE(atf_fs_stat_init(&st, &p)); 452 ATF_CHECK_EQ(0644, atf_fs_stat_get_mode(&st)); 453 atf_fs_stat_fini(&st); 454 atf_fs_path_fini(&p); 455 } 456 457 ATF_TC(stat_type); 458 ATF_TC_HEAD(stat_type, tc) 459 { 460 atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_stat_get_type function " 461 "and, indirectly, the constructor"); 462 } 463 ATF_TC_BODY(stat_type, tc) 464 { 465 atf_fs_path_t p; 466 atf_fs_stat_t st; 467 468 create_dir("dir", 0755); 469 create_file("reg", 0644); 470 471 RE(atf_fs_path_init_fmt(&p, "dir")); 472 RE(atf_fs_stat_init(&st, &p)); 473 ATF_REQUIRE_EQ(atf_fs_stat_get_type(&st), atf_fs_stat_dir_type); 474 atf_fs_stat_fini(&st); 475 atf_fs_path_fini(&p); 476 477 RE(atf_fs_path_init_fmt(&p, "reg")); 478 RE(atf_fs_stat_init(&st, &p)); 479 ATF_REQUIRE_EQ(atf_fs_stat_get_type(&st), atf_fs_stat_reg_type); 480 atf_fs_stat_fini(&st); 481 atf_fs_path_fini(&p); 482 } 483 484 ATF_TC(stat_perms); 485 ATF_TC_HEAD(stat_perms, tc) 486 { 487 atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_stat_is_* functions"); 488 } 489 ATF_TC_BODY(stat_perms, tc) 490 { 491 atf_fs_path_t p; 492 atf_fs_stat_t st; 493 494 create_file("reg", 0); 495 496 RE(atf_fs_path_init_fmt(&p, "reg")); 497 498 #define perms(ur, uw, ux, gr, gw, gx, othr, othw, othx) \ 499 { \ 500 RE(atf_fs_stat_init(&st, &p)); \ 501 ATF_REQUIRE(atf_fs_stat_is_owner_readable(&st) == ur); \ 502 ATF_REQUIRE(atf_fs_stat_is_owner_writable(&st) == uw); \ 503 ATF_REQUIRE(atf_fs_stat_is_owner_executable(&st) == ux); \ 504 ATF_REQUIRE(atf_fs_stat_is_group_readable(&st) == gr); \ 505 ATF_REQUIRE(atf_fs_stat_is_group_writable(&st) == gw); \ 506 ATF_REQUIRE(atf_fs_stat_is_group_executable(&st) == gx); \ 507 ATF_REQUIRE(atf_fs_stat_is_other_readable(&st) == othr); \ 508 ATF_REQUIRE(atf_fs_stat_is_other_writable(&st) == othw); \ 509 ATF_REQUIRE(atf_fs_stat_is_other_executable(&st) == othx); \ 510 atf_fs_stat_fini(&st); \ 511 } 512 513 chmod("reg", 0000); 514 perms(false, false, false, false, false, false, false, false, false); 515 516 chmod("reg", 0001); 517 perms(false, false, false, false, false, false, false, false, true); 518 519 chmod("reg", 0010); 520 perms(false, false, false, false, false, true, false, false, false); 521 522 chmod("reg", 0100); 523 perms(false, false, true, false, false, false, false, false, false); 524 525 chmod("reg", 0002); 526 perms(false, false, false, false, false, false, false, true, false); 527 528 chmod("reg", 0020); 529 perms(false, false, false, false, true, false, false, false, false); 530 531 chmod("reg", 0200); 532 perms(false, true, false, false, false, false, false, false, false); 533 534 chmod("reg", 0004); 535 perms(false, false, false, false, false, false, true, false, false); 536 537 chmod("reg", 0040); 538 perms(false, false, false, true, false, false, false, false, false); 539 540 chmod("reg", 0400); 541 perms(true, false, false, false, false, false, false, false, false); 542 543 chmod("reg", 0644); 544 perms(true, true, false, true, false, false, true, false, false); 545 546 chmod("reg", 0755); 547 perms(true, true, true, true, false, true, true, false, true); 548 549 chmod("reg", 0777); 550 perms(true, true, true, true, true, true, true, true, true); 551 552 #undef perms 553 554 atf_fs_path_fini(&p); 555 } 556 557 /* --------------------------------------------------------------------- 558 * Test cases for the free functions. 559 * --------------------------------------------------------------------- */ 560 561 ATF_TC(exists); 562 ATF_TC_HEAD(exists, tc) 563 { 564 atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_exists function"); 565 } 566 ATF_TC_BODY(exists, tc) 567 { 568 atf_error_t err; 569 atf_fs_path_t pdir, pfile; 570 bool b; 571 572 RE(atf_fs_path_init_fmt(&pdir, "dir")); 573 RE(atf_fs_path_init_fmt(&pfile, "dir/file")); 574 575 create_dir(atf_fs_path_cstring(&pdir), 0755); 576 create_file(atf_fs_path_cstring(&pfile), 0644); 577 578 printf("Checking existence of a directory\n"); 579 RE(atf_fs_exists(&pdir, &b)); 580 ATF_REQUIRE(b); 581 582 printf("Checking existence of a file\n"); 583 RE(atf_fs_exists(&pfile, &b)); 584 ATF_REQUIRE(b); 585 586 /* XXX: This should probably be a separate test case to let the user 587 * be aware that some tests were skipped because privileges were not 588 * correct. */ 589 if (!atf_user_is_root()) { 590 printf("Checking existence of a file inside a directory without " 591 "permissions\n"); 592 ATF_REQUIRE(chmod(atf_fs_path_cstring(&pdir), 0000) != -1); 593 err = atf_fs_exists(&pfile, &b); 594 ATF_REQUIRE(atf_is_error(err)); 595 ATF_REQUIRE(atf_error_is(err, "libc")); 596 ATF_REQUIRE(chmod(atf_fs_path_cstring(&pdir), 0755) != -1); 597 atf_error_free(err); 598 } 599 600 printf("Checking existence of a non-existent file\n"); 601 ATF_REQUIRE(unlink(atf_fs_path_cstring(&pfile)) != -1); 602 RE(atf_fs_exists(&pfile, &b)); 603 ATF_REQUIRE(!b); 604 605 atf_fs_path_fini(&pfile); 606 atf_fs_path_fini(&pdir); 607 } 608 609 ATF_TC(eaccess); 610 ATF_TC_HEAD(eaccess, tc) 611 { 612 atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_eaccess function"); 613 } 614 ATF_TC_BODY(eaccess, tc) 615 { 616 const int modes[] = { atf_fs_access_f, atf_fs_access_r, atf_fs_access_w, 617 atf_fs_access_x, 0 }; 618 const int *m; 619 struct tests { 620 mode_t fmode; 621 int amode; 622 int uerror; 623 int rerror; 624 } tests[] = { 625 { 0000, atf_fs_access_r, EACCES, 0 }, 626 { 0000, atf_fs_access_w, EACCES, 0 }, 627 { 0000, atf_fs_access_x, EACCES, EACCES }, 628 629 { 0001, atf_fs_access_r, EACCES, 0 }, 630 { 0001, atf_fs_access_w, EACCES, 0 }, 631 { 0001, atf_fs_access_x, EACCES, 0 }, 632 { 0002, atf_fs_access_r, EACCES, 0 }, 633 { 0002, atf_fs_access_w, EACCES, 0 }, 634 { 0002, atf_fs_access_x, EACCES, EACCES }, 635 { 0004, atf_fs_access_r, EACCES, 0 }, 636 { 0004, atf_fs_access_w, EACCES, 0 }, 637 { 0004, atf_fs_access_x, EACCES, EACCES }, 638 639 { 0010, atf_fs_access_r, EACCES, 0 }, 640 { 0010, atf_fs_access_w, EACCES, 0 }, 641 { 0010, atf_fs_access_x, 0, 0 }, 642 { 0020, atf_fs_access_r, EACCES, 0 }, 643 { 0020, atf_fs_access_w, 0, 0 }, 644 { 0020, atf_fs_access_x, EACCES, EACCES }, 645 { 0040, atf_fs_access_r, 0, 0 }, 646 { 0040, atf_fs_access_w, EACCES, 0 }, 647 { 0040, atf_fs_access_x, EACCES, EACCES }, 648 649 { 0100, atf_fs_access_r, EACCES, 0 }, 650 { 0100, atf_fs_access_w, EACCES, 0 }, 651 { 0100, atf_fs_access_x, 0, 0 }, 652 { 0200, atf_fs_access_r, EACCES, 0 }, 653 { 0200, atf_fs_access_w, 0, 0 }, 654 { 0200, atf_fs_access_x, EACCES, EACCES }, 655 { 0400, atf_fs_access_r, 0, 0 }, 656 { 0400, atf_fs_access_w, EACCES, 0 }, 657 { 0400, atf_fs_access_x, EACCES, EACCES }, 658 659 { 0, 0, 0, 0 } 660 }; 661 struct tests *t; 662 atf_fs_path_t p; 663 atf_error_t err; 664 665 RE(atf_fs_path_init_fmt(&p, "the-file")); 666 667 printf("Non-existent file checks\n"); 668 for (m = &modes[0]; *m != 0; m++) { 669 err = atf_fs_eaccess(&p, *m); 670 ATF_REQUIRE(atf_is_error(err)); 671 ATF_REQUIRE(atf_error_is(err, "libc")); 672 ATF_REQUIRE_EQ(atf_libc_error_code(err), ENOENT); 673 atf_error_free(err); 674 } 675 676 create_file(atf_fs_path_cstring(&p), 0000); 677 ATF_REQUIRE(chown(atf_fs_path_cstring(&p), geteuid(), getegid()) != -1); 678 679 for (t = &tests[0]; t->amode != 0; t++) { 680 const int experr = atf_user_is_root() ? t->rerror : t->uerror; 681 682 printf("\n"); 683 printf("File mode : %04o\n", (unsigned int)t->fmode); 684 printf("Access mode : 0x%02x\n", t->amode); 685 686 ATF_REQUIRE(chmod(atf_fs_path_cstring(&p), t->fmode) != -1); 687 688 /* First, existence check. */ 689 err = atf_fs_eaccess(&p, atf_fs_access_f); 690 ATF_REQUIRE(!atf_is_error(err)); 691 692 /* Now do the specific test case. */ 693 printf("Expected error: %d\n", experr); 694 err = atf_fs_eaccess(&p, t->amode); 695 if (atf_is_error(err)) { 696 if (atf_error_is(err, "libc")) 697 printf("Error : %d\n", atf_libc_error_code(err)); 698 else 699 printf("Error : Non-libc error\n"); 700 } else 701 printf("Error : None\n"); 702 if (experr == 0) { 703 ATF_REQUIRE(!atf_is_error(err)); 704 } else { 705 ATF_REQUIRE(atf_is_error(err)); 706 ATF_REQUIRE(atf_error_is(err, "libc")); 707 ATF_REQUIRE_EQ(atf_libc_error_code(err), experr); 708 atf_error_free(err); 709 } 710 } 711 712 atf_fs_path_fini(&p); 713 } 714 715 ATF_TC(getcwd); 716 ATF_TC_HEAD(getcwd, tc) 717 { 718 atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_getcwd function"); 719 } 720 ATF_TC_BODY(getcwd, tc) 721 { 722 atf_fs_path_t cwd1, cwd2; 723 724 create_dir ("root", 0755); 725 726 RE(atf_fs_getcwd(&cwd1)); 727 ATF_REQUIRE(chdir("root") != -1); 728 RE(atf_fs_getcwd(&cwd2)); 729 730 RE(atf_fs_path_append_fmt(&cwd1, "root")); 731 732 ATF_REQUIRE(atf_equal_fs_path_fs_path(&cwd1, &cwd2)); 733 734 atf_fs_path_fini(&cwd2); 735 atf_fs_path_fini(&cwd1); 736 } 737 738 ATF_TC(rmdir_empty); 739 ATF_TC_HEAD(rmdir_empty, tc) 740 { 741 atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_rmdir function"); 742 } 743 ATF_TC_BODY(rmdir_empty, tc) 744 { 745 atf_fs_path_t p; 746 747 RE(atf_fs_path_init_fmt(&p, "test-dir")); 748 749 ATF_REQUIRE(mkdir("test-dir", 0755) != -1); 750 ATF_REQUIRE(exists(&p)); 751 RE(atf_fs_rmdir(&p)); 752 ATF_REQUIRE(!exists(&p)); 753 754 atf_fs_path_fini(&p); 755 } 756 757 ATF_TC(rmdir_enotempty); 758 ATF_TC_HEAD(rmdir_enotempty, tc) 759 { 760 atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_rmdir function"); 761 } 762 ATF_TC_BODY(rmdir_enotempty, tc) 763 { 764 atf_fs_path_t p; 765 atf_error_t err; 766 767 RE(atf_fs_path_init_fmt(&p, "test-dir")); 768 769 ATF_REQUIRE(mkdir("test-dir", 0755) != -1); 770 ATF_REQUIRE(exists(&p)); 771 create_file("test-dir/foo", 0644); 772 773 err = atf_fs_rmdir(&p); 774 ATF_REQUIRE(atf_is_error(err)); 775 ATF_REQUIRE(atf_error_is(err, "libc")); 776 ATF_REQUIRE_EQ(atf_libc_error_code(err), ENOTEMPTY); 777 atf_error_free(err); 778 779 atf_fs_path_fini(&p); 780 } 781 782 ATF_TC_WITH_CLEANUP(rmdir_eperm); 783 ATF_TC_HEAD(rmdir_eperm, tc) 784 { 785 atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_rmdir function"); 786 } 787 ATF_TC_BODY(rmdir_eperm, tc) 788 { 789 atf_fs_path_t p; 790 atf_error_t err; 791 792 RE(atf_fs_path_init_fmt(&p, "test-dir/foo")); 793 794 ATF_REQUIRE(mkdir("test-dir", 0755) != -1); 795 ATF_REQUIRE(mkdir("test-dir/foo", 0755) != -1); 796 ATF_REQUIRE(chmod("test-dir", 0555) != -1); 797 ATF_REQUIRE(exists(&p)); 798 799 err = atf_fs_rmdir(&p); 800 if (atf_user_is_root()) { 801 ATF_REQUIRE(!atf_is_error(err)); 802 } else { 803 ATF_REQUIRE(atf_is_error(err)); 804 ATF_REQUIRE(atf_error_is(err, "libc")); 805 ATF_REQUIRE_EQ(atf_libc_error_code(err), EACCES); 806 atf_error_free(err); 807 } 808 809 atf_fs_path_fini(&p); 810 } 811 ATF_TC_CLEANUP(rmdir_eperm, tc) 812 { 813 if (chmod("test-dir", 0755) == -1) { 814 fprintf(stderr, "Failed to unprotect test-dir; test directory " 815 "cleanup will fail\n"); 816 } 817 } 818 819 ATF_TC(mkdtemp_ok); 820 ATF_TC_HEAD(mkdtemp_ok, tc) 821 { 822 atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkdtemp function, " 823 "successful execution"); 824 } 825 ATF_TC_BODY(mkdtemp_ok, tc) 826 { 827 atf_fs_path_t p1, p2; 828 atf_fs_stat_t s1, s2; 829 830 RE(atf_fs_path_init_fmt(&p1, "testdir.XXXXXX")); 831 RE(atf_fs_path_init_fmt(&p2, "testdir.XXXXXX")); 832 RE(atf_fs_mkdtemp(&p1)); 833 RE(atf_fs_mkdtemp(&p2)); 834 ATF_REQUIRE(!atf_equal_fs_path_fs_path(&p1, &p2)); 835 ATF_REQUIRE(exists(&p1)); 836 ATF_REQUIRE(exists(&p2)); 837 838 RE(atf_fs_stat_init(&s1, &p1)); 839 ATF_REQUIRE_EQ(atf_fs_stat_get_type(&s1), atf_fs_stat_dir_type); 840 ATF_REQUIRE( atf_fs_stat_is_owner_readable(&s1)); 841 ATF_REQUIRE( atf_fs_stat_is_owner_writable(&s1)); 842 ATF_REQUIRE( atf_fs_stat_is_owner_executable(&s1)); 843 ATF_REQUIRE(!atf_fs_stat_is_group_readable(&s1)); 844 ATF_REQUIRE(!atf_fs_stat_is_group_writable(&s1)); 845 ATF_REQUIRE(!atf_fs_stat_is_group_executable(&s1)); 846 ATF_REQUIRE(!atf_fs_stat_is_other_readable(&s1)); 847 ATF_REQUIRE(!atf_fs_stat_is_other_writable(&s1)); 848 ATF_REQUIRE(!atf_fs_stat_is_other_executable(&s1)); 849 850 RE(atf_fs_stat_init(&s2, &p2)); 851 ATF_REQUIRE_EQ(atf_fs_stat_get_type(&s2), atf_fs_stat_dir_type); 852 ATF_REQUIRE( atf_fs_stat_is_owner_readable(&s2)); 853 ATF_REQUIRE( atf_fs_stat_is_owner_writable(&s2)); 854 ATF_REQUIRE( atf_fs_stat_is_owner_executable(&s2)); 855 ATF_REQUIRE(!atf_fs_stat_is_group_readable(&s2)); 856 ATF_REQUIRE(!atf_fs_stat_is_group_writable(&s2)); 857 ATF_REQUIRE(!atf_fs_stat_is_group_executable(&s2)); 858 ATF_REQUIRE(!atf_fs_stat_is_other_readable(&s2)); 859 ATF_REQUIRE(!atf_fs_stat_is_other_writable(&s2)); 860 ATF_REQUIRE(!atf_fs_stat_is_other_executable(&s2)); 861 862 atf_fs_stat_fini(&s2); 863 atf_fs_stat_fini(&s1); 864 atf_fs_path_fini(&p2); 865 atf_fs_path_fini(&p1); 866 } 867 868 ATF_TC(mkdtemp_err); 869 ATF_TC_HEAD(mkdtemp_err, tc) 870 { 871 atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkdtemp function, " 872 "error conditions"); 873 atf_tc_set_md_var(tc, "require.user", "unprivileged"); 874 } 875 ATF_TC_BODY(mkdtemp_err, tc) 876 { 877 atf_error_t err; 878 atf_fs_path_t p; 879 880 ATF_REQUIRE(mkdir("dir", 0555) != -1); 881 882 RE(atf_fs_path_init_fmt(&p, "dir/testdir.XXXXXX")); 883 884 err = atf_fs_mkdtemp(&p); 885 ATF_REQUIRE(atf_is_error(err)); 886 ATF_REQUIRE(atf_error_is(err, "libc")); 887 ATF_CHECK_EQ(atf_libc_error_code(err), EACCES); 888 atf_error_free(err); 889 890 ATF_CHECK(!exists(&p)); 891 ATF_CHECK(strcmp(atf_fs_path_cstring(&p), "dir/testdir.XXXXXX") == 0); 892 893 atf_fs_path_fini(&p); 894 } 895 896 static 897 void 898 do_umask_check(atf_error_t (*const mk_func)(atf_fs_path_t *), 899 atf_fs_path_t *path, const mode_t test_mask, 900 const char *str_mask, const char *exp_name) 901 { 902 char buf[1024]; 903 int old_umask; 904 atf_error_t err; 905 906 printf("Creating temporary %s with umask %s\n", exp_name, str_mask); 907 908 old_umask = umask(test_mask); 909 err = mk_func(path); 910 (void)umask(old_umask); 911 912 ATF_REQUIRE(atf_is_error(err)); 913 ATF_REQUIRE(atf_error_is(err, "invalid_umask")); 914 atf_error_format(err, buf, sizeof(buf)); 915 ATF_CHECK(strstr(buf, exp_name) != NULL); 916 ATF_CHECK(strstr(buf, str_mask) != NULL); 917 atf_error_free(err); 918 } 919 920 ATF_TC(mkdtemp_umask); 921 ATF_TC_HEAD(mkdtemp_umask, tc) 922 { 923 atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkdtemp function " 924 "causing an error due to a too strict umask"); 925 } 926 ATF_TC_BODY(mkdtemp_umask, tc) 927 { 928 atf_fs_path_t p; 929 930 RE(atf_fs_path_init_fmt(&p, "testdir.XXXXXX")); 931 932 do_umask_check(atf_fs_mkdtemp, &p, 00100, "00100", "directory"); 933 do_umask_check(atf_fs_mkdtemp, &p, 00200, "00200", "directory"); 934 do_umask_check(atf_fs_mkdtemp, &p, 00400, "00400", "directory"); 935 do_umask_check(atf_fs_mkdtemp, &p, 00500, "00500", "directory"); 936 do_umask_check(atf_fs_mkdtemp, &p, 00600, "00600", "directory"); 937 938 atf_fs_path_fini(&p); 939 } 940 941 ATF_TC(mkstemp_ok); 942 ATF_TC_HEAD(mkstemp_ok, tc) 943 { 944 atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkstemp function, " 945 "successful execution"); 946 } 947 ATF_TC_BODY(mkstemp_ok, tc) 948 { 949 int fd1, fd2; 950 atf_fs_path_t p1, p2; 951 atf_fs_stat_t s1, s2; 952 953 RE(atf_fs_path_init_fmt(&p1, "testfile.XXXXXX")); 954 RE(atf_fs_path_init_fmt(&p2, "testfile.XXXXXX")); 955 fd1 = fd2 = -1; 956 RE(atf_fs_mkstemp(&p1, &fd1)); 957 RE(atf_fs_mkstemp(&p2, &fd2)); 958 ATF_REQUIRE(!atf_equal_fs_path_fs_path(&p1, &p2)); 959 ATF_REQUIRE(exists(&p1)); 960 ATF_REQUIRE(exists(&p2)); 961 962 ATF_CHECK(fd1 != -1); 963 ATF_CHECK(fd2 != -1); 964 ATF_CHECK(write(fd1, "foo", 3) == 3); 965 ATF_CHECK(write(fd2, "bar", 3) == 3); 966 close(fd1); 967 close(fd2); 968 969 RE(atf_fs_stat_init(&s1, &p1)); 970 ATF_CHECK_EQ(atf_fs_stat_get_type(&s1), atf_fs_stat_reg_type); 971 ATF_CHECK( atf_fs_stat_is_owner_readable(&s1)); 972 ATF_CHECK( atf_fs_stat_is_owner_writable(&s1)); 973 ATF_CHECK(!atf_fs_stat_is_owner_executable(&s1)); 974 ATF_CHECK(!atf_fs_stat_is_group_readable(&s1)); 975 ATF_CHECK(!atf_fs_stat_is_group_writable(&s1)); 976 ATF_CHECK(!atf_fs_stat_is_group_executable(&s1)); 977 ATF_CHECK(!atf_fs_stat_is_other_readable(&s1)); 978 ATF_CHECK(!atf_fs_stat_is_other_writable(&s1)); 979 ATF_CHECK(!atf_fs_stat_is_other_executable(&s1)); 980 981 RE(atf_fs_stat_init(&s2, &p2)); 982 ATF_CHECK_EQ(atf_fs_stat_get_type(&s2), atf_fs_stat_reg_type); 983 ATF_CHECK( atf_fs_stat_is_owner_readable(&s2)); 984 ATF_CHECK( atf_fs_stat_is_owner_writable(&s2)); 985 ATF_CHECK(!atf_fs_stat_is_owner_executable(&s2)); 986 ATF_CHECK(!atf_fs_stat_is_group_readable(&s2)); 987 ATF_CHECK(!atf_fs_stat_is_group_writable(&s2)); 988 ATF_CHECK(!atf_fs_stat_is_group_executable(&s2)); 989 ATF_CHECK(!atf_fs_stat_is_other_readable(&s2)); 990 ATF_CHECK(!atf_fs_stat_is_other_writable(&s2)); 991 ATF_CHECK(!atf_fs_stat_is_other_executable(&s2)); 992 993 atf_fs_stat_fini(&s2); 994 atf_fs_stat_fini(&s1); 995 atf_fs_path_fini(&p2); 996 atf_fs_path_fini(&p1); 997 } 998 999 ATF_TC(mkstemp_err); 1000 ATF_TC_HEAD(mkstemp_err, tc) 1001 { 1002 atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkstemp function, " 1003 "error conditions"); 1004 atf_tc_set_md_var(tc, "require.user", "unprivileged"); 1005 } 1006 ATF_TC_BODY(mkstemp_err, tc) 1007 { 1008 int fd; 1009 atf_error_t err; 1010 atf_fs_path_t p; 1011 1012 ATF_REQUIRE(mkdir("dir", 0555) != -1); 1013 1014 RE(atf_fs_path_init_fmt(&p, "dir/testfile.XXXXXX")); 1015 fd = 1234; 1016 1017 err = atf_fs_mkstemp(&p, &fd); 1018 ATF_REQUIRE(atf_is_error(err)); 1019 ATF_REQUIRE(atf_error_is(err, "libc")); 1020 ATF_CHECK_EQ(atf_libc_error_code(err), EACCES); 1021 atf_error_free(err); 1022 1023 ATF_CHECK(!exists(&p)); 1024 ATF_CHECK(strcmp(atf_fs_path_cstring(&p), "dir/testfile.XXXXXX") == 0); 1025 ATF_CHECK_EQ(fd, 1234); 1026 1027 atf_fs_path_fini(&p); 1028 } 1029 1030 ATF_TC(mkstemp_umask); 1031 ATF_TC_HEAD(mkstemp_umask, tc) 1032 { 1033 atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkstemp function " 1034 "causing an error due to a too strict umask"); 1035 } 1036 ATF_TC_BODY(mkstemp_umask, tc) 1037 { 1038 atf_fs_path_t p; 1039 1040 RE(atf_fs_path_init_fmt(&p, "testfile.XXXXXX")); 1041 1042 do_umask_check(mkstemp_discard_fd, &p, 00100, "00100", "regular file"); 1043 do_umask_check(mkstemp_discard_fd, &p, 00200, "00200", "regular file"); 1044 do_umask_check(mkstemp_discard_fd, &p, 00400, "00400", "regular file"); 1045 1046 atf_fs_path_fini(&p); 1047 } 1048 1049 /* --------------------------------------------------------------------- 1050 * Main. 1051 * --------------------------------------------------------------------- */ 1052 1053 ATF_TP_ADD_TCS(tp) 1054 { 1055 /* Add the tests for the "atf_fs_path" type. */ 1056 ATF_TP_ADD_TC(tp, path_normalize); 1057 ATF_TP_ADD_TC(tp, path_copy); 1058 ATF_TP_ADD_TC(tp, path_is_absolute); 1059 ATF_TP_ADD_TC(tp, path_is_root); 1060 ATF_TP_ADD_TC(tp, path_branch_path); 1061 ATF_TP_ADD_TC(tp, path_leaf_name); 1062 ATF_TP_ADD_TC(tp, path_append); 1063 ATF_TP_ADD_TC(tp, path_to_absolute); 1064 ATF_TP_ADD_TC(tp, path_equal); 1065 1066 /* Add the tests for the "atf_fs_stat" type. */ 1067 ATF_TP_ADD_TC(tp, stat_mode); 1068 ATF_TP_ADD_TC(tp, stat_type); 1069 ATF_TP_ADD_TC(tp, stat_perms); 1070 1071 /* Add the tests for the free functions. */ 1072 ATF_TP_ADD_TC(tp, eaccess); 1073 ATF_TP_ADD_TC(tp, exists); 1074 ATF_TP_ADD_TC(tp, getcwd); 1075 ATF_TP_ADD_TC(tp, rmdir_empty); 1076 ATF_TP_ADD_TC(tp, rmdir_enotempty); 1077 ATF_TP_ADD_TC(tp, rmdir_eperm); 1078 ATF_TP_ADD_TC(tp, mkdtemp_ok); 1079 ATF_TP_ADD_TC(tp, mkdtemp_err); 1080 ATF_TP_ADD_TC(tp, mkdtemp_umask); 1081 ATF_TP_ADD_TC(tp, mkstemp_ok); 1082 ATF_TP_ADD_TC(tp, mkstemp_err); 1083 ATF_TP_ADD_TC(tp, mkstemp_umask); 1084 1085 return atf_no_error(); 1086 } 1087