1 /* 2 * Automated Testing Framework (atf) 3 * 4 * Copyright (c) 2007 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 17 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 18 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 23 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #if defined(HAVE_CONFIG_H) 31 #include "bconfig.h" 32 #endif 33 34 #include <sys/types.h> 35 #include <sys/param.h> 36 #include <sys/mount.h> 37 #include <sys/stat.h> 38 #include <sys/wait.h> 39 40 #include <dirent.h> 41 #include <errno.h> 42 #include <libgen.h> 43 #include <stdarg.h> 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <string.h> 47 #include <unistd.h> 48 49 #include "atf-c/defs.h" 50 #include "atf-c/error.h" 51 52 #include "fs.h" 53 #include "sanity.h" 54 #include "text.h" 55 #include "user.h" 56 57 /* --------------------------------------------------------------------- 58 * Prototypes for auxiliary functions. 59 * --------------------------------------------------------------------- */ 60 61 static bool check_umask(const mode_t, const mode_t); 62 static atf_error_t copy_contents(const atf_fs_path_t *, char **); 63 static mode_t current_umask(void); 64 static atf_error_t do_mkdtemp(char *); 65 static atf_error_t normalize(atf_dynstr_t *, char *); 66 static atf_error_t normalize_ap(atf_dynstr_t *, const char *, va_list) 67 ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(2, 0); 68 static void replace_contents(atf_fs_path_t *, const char *); 69 static const char *stat_type_to_string(const int); 70 71 /* --------------------------------------------------------------------- 72 * The "invalid_umask" error type. 73 * --------------------------------------------------------------------- */ 74 75 struct invalid_umask_error_data { 76 /* One of atf_fs_stat_*_type. */ 77 int m_type; 78 79 /* The original path causing the error. */ 80 /* XXX: Ideally this would be an atf_fs_path_t, but if we create it 81 * from the error constructor, we cannot delete the path later on. 82 * Can't remember why atf_error_new does not take a hook for 83 * deletion. */ 84 char m_path[1024]; 85 86 /* The umask that caused the error. */ 87 mode_t m_umask; 88 }; 89 typedef struct invalid_umask_error_data invalid_umask_error_data_t; 90 91 static 92 void 93 invalid_umask_format(const atf_error_t err, char *buf, size_t buflen) 94 { 95 const invalid_umask_error_data_t *data; 96 97 PRE(atf_error_is(err, "invalid_umask")); 98 99 data = atf_error_data(err); 100 snprintf(buf, buflen, "Could not create the temporary %s %s because " 101 "it will not have enough access rights due to the current " 102 "umask %05o", stat_type_to_string(data->m_type), 103 data->m_path, (unsigned int)data->m_umask); 104 } 105 106 static 107 atf_error_t 108 invalid_umask_error(const atf_fs_path_t *path, const int type, 109 const mode_t failing_mask) 110 { 111 atf_error_t err; 112 invalid_umask_error_data_t data; 113 114 data.m_type = type; 115 116 strncpy(data.m_path, atf_fs_path_cstring(path), sizeof(data.m_path)); 117 data.m_path[sizeof(data.m_path) - 1] = '\0'; 118 119 data.m_umask = failing_mask; 120 121 err = atf_error_new("invalid_umask", &data, sizeof(data), 122 invalid_umask_format); 123 124 return err; 125 } 126 127 /* --------------------------------------------------------------------- 128 * The "unknown_file_type" error type. 129 * --------------------------------------------------------------------- */ 130 131 struct unknown_type_error_data { 132 const char *m_path; 133 int m_type; 134 }; 135 typedef struct unknown_type_error_data unknown_type_error_data_t; 136 137 static 138 void 139 unknown_type_format(const atf_error_t err, char *buf, size_t buflen) 140 { 141 const unknown_type_error_data_t *data; 142 143 PRE(atf_error_is(err, "unknown_type")); 144 145 data = atf_error_data(err); 146 snprintf(buf, buflen, "Unknown file type %d of %s", data->m_type, 147 data->m_path); 148 } 149 150 static 151 atf_error_t 152 unknown_type_error(const char *path, int type) 153 { 154 atf_error_t err; 155 unknown_type_error_data_t data; 156 157 data.m_path = path; 158 data.m_type = type; 159 160 err = atf_error_new("unknown_type", &data, sizeof(data), 161 unknown_type_format); 162 163 return err; 164 } 165 166 /* --------------------------------------------------------------------- 167 * Auxiliary functions. 168 * --------------------------------------------------------------------- */ 169 170 static 171 bool 172 check_umask(const mode_t exp_mode, const mode_t min_mode) 173 { 174 const mode_t actual_mode = (~current_umask() & exp_mode); 175 return (actual_mode & min_mode) == min_mode; 176 } 177 178 static 179 atf_error_t 180 copy_contents(const atf_fs_path_t *p, char **buf) 181 { 182 atf_error_t err; 183 char *str; 184 185 str = (char *)malloc(atf_dynstr_length(&p->m_data) + 1); 186 if (str == NULL) 187 err = atf_no_memory_error(); 188 else { 189 strcpy(str, atf_dynstr_cstring(&p->m_data)); 190 *buf = str; 191 err = atf_no_error(); 192 } 193 194 return err; 195 } 196 197 static 198 mode_t 199 current_umask(void) 200 { 201 const mode_t current = umask(0); 202 (void)umask(current); 203 return current; 204 } 205 206 static 207 atf_error_t 208 do_mkdtemp(char *tmpl) 209 { 210 atf_error_t err; 211 212 PRE(strstr(tmpl, "XXXXXX") != NULL); 213 214 if (mkdtemp(tmpl) == NULL) 215 err = atf_libc_error(errno, "Cannot create temporary directory " 216 "with template '%s'", tmpl); 217 else 218 err = atf_no_error(); 219 220 return err; 221 } 222 223 static 224 atf_error_t 225 do_mkstemp(char *tmpl, int *fdout) 226 { 227 atf_error_t err; 228 229 PRE(strstr(tmpl, "XXXXXX") != NULL); 230 231 *fdout = mkstemp(tmpl); 232 if (*fdout == -1) 233 err = atf_libc_error(errno, "Cannot create temporary file " 234 "with template '%s'", tmpl); 235 236 else 237 err = atf_no_error(); 238 239 return err; 240 } 241 242 static 243 atf_error_t 244 normalize(atf_dynstr_t *d, char *p) 245 { 246 const char *ptr; 247 char *last; 248 atf_error_t err; 249 bool first; 250 251 PRE(strlen(p) > 0); 252 PRE(atf_dynstr_length(d) == 0); 253 254 if (p[0] == '/') 255 err = atf_dynstr_append_fmt(d, "/"); 256 else 257 err = atf_no_error(); 258 259 first = true; 260 last = NULL; /* Silence GCC warning. */ 261 ptr = strtok_r(p, "/", &last); 262 while (!atf_is_error(err) && ptr != NULL) { 263 if (strlen(ptr) > 0) { 264 err = atf_dynstr_append_fmt(d, "%s%s", first ? "" : "/", ptr); 265 first = false; 266 } 267 268 ptr = strtok_r(NULL, "/", &last); 269 } 270 271 return err; 272 } 273 274 static 275 atf_error_t 276 normalize_ap(atf_dynstr_t *d, const char *p, va_list ap) 277 { 278 char *str; 279 atf_error_t err; 280 va_list ap2; 281 282 err = atf_dynstr_init(d); 283 if (atf_is_error(err)) 284 goto out; 285 286 va_copy(ap2, ap); 287 err = atf_text_format_ap(&str, p, ap2); 288 va_end(ap2); 289 if (atf_is_error(err)) 290 atf_dynstr_fini(d); 291 else { 292 err = normalize(d, str); 293 free(str); 294 } 295 296 out: 297 return err; 298 } 299 300 static 301 void 302 replace_contents(atf_fs_path_t *p, const char *buf) 303 { 304 atf_error_t err; 305 306 PRE(atf_dynstr_length(&p->m_data) == strlen(buf)); 307 308 atf_dynstr_clear(&p->m_data); 309 err = atf_dynstr_append_fmt(&p->m_data, "%s", buf); 310 311 INV(!atf_is_error(err)); 312 } 313 314 static 315 const char * 316 stat_type_to_string(const int type) 317 { 318 const char *str; 319 320 if (type == atf_fs_stat_blk_type) 321 str = "block device"; 322 else if (type == atf_fs_stat_chr_type) 323 str = "character device"; 324 else if (type == atf_fs_stat_dir_type) 325 str = "directory"; 326 else if (type == atf_fs_stat_fifo_type) 327 str = "named pipe"; 328 else if (type == atf_fs_stat_lnk_type) 329 str = "symbolic link"; 330 else if (type == atf_fs_stat_reg_type) 331 str = "regular file"; 332 else if (type == atf_fs_stat_sock_type) 333 str = "socket"; 334 else if (type == atf_fs_stat_wht_type) 335 str = "whiteout"; 336 else { 337 UNREACHABLE; 338 str = NULL; 339 } 340 341 return str; 342 } 343 344 /* --------------------------------------------------------------------- 345 * The "atf_fs_path" type. 346 * --------------------------------------------------------------------- */ 347 348 /* 349 * Constructors/destructors. 350 */ 351 352 atf_error_t 353 atf_fs_path_init_ap(atf_fs_path_t *p, const char *fmt, va_list ap) 354 { 355 atf_error_t err; 356 va_list ap2; 357 358 va_copy(ap2, ap); 359 err = normalize_ap(&p->m_data, fmt, ap2); 360 va_end(ap2); 361 362 return err; 363 } 364 365 atf_error_t 366 atf_fs_path_init_fmt(atf_fs_path_t *p, const char *fmt, ...) 367 { 368 va_list ap; 369 atf_error_t err; 370 371 va_start(ap, fmt); 372 err = atf_fs_path_init_ap(p, fmt, ap); 373 va_end(ap); 374 375 return err; 376 } 377 378 atf_error_t 379 atf_fs_path_copy(atf_fs_path_t *dest, const atf_fs_path_t *src) 380 { 381 return atf_dynstr_copy(&dest->m_data, &src->m_data); 382 } 383 384 void 385 atf_fs_path_fini(atf_fs_path_t *p) 386 { 387 atf_dynstr_fini(&p->m_data); 388 } 389 390 /* 391 * Getters. 392 */ 393 394 atf_error_t 395 atf_fs_path_branch_path(const atf_fs_path_t *p, atf_fs_path_t *bp) 396 { 397 const size_t endpos = atf_dynstr_rfind_ch(&p->m_data, '/'); 398 atf_error_t err; 399 400 if (endpos == atf_dynstr_npos) 401 err = atf_fs_path_init_fmt(bp, "."); 402 else if (endpos == 0) 403 err = atf_fs_path_init_fmt(bp, "/"); 404 else 405 err = atf_dynstr_init_substr(&bp->m_data, &p->m_data, 0, endpos); 406 407 #if defined(HAVE_CONST_DIRNAME) 408 INV(atf_equal_dynstr_cstring(&bp->m_data, 409 dirname(atf_dynstr_cstring(&p->m_data)))); 410 #endif /* defined(HAVE_CONST_DIRNAME) */ 411 412 return err; 413 } 414 415 const char * 416 atf_fs_path_cstring(const atf_fs_path_t *p) 417 { 418 return atf_dynstr_cstring(&p->m_data); 419 } 420 421 atf_error_t 422 atf_fs_path_leaf_name(const atf_fs_path_t *p, atf_dynstr_t *ln) 423 { 424 size_t begpos = atf_dynstr_rfind_ch(&p->m_data, '/'); 425 atf_error_t err; 426 427 if (begpos == atf_dynstr_npos) 428 begpos = 0; 429 else 430 begpos++; 431 432 err = atf_dynstr_init_substr(ln, &p->m_data, begpos, atf_dynstr_npos); 433 434 #if defined(HAVE_CONST_BASENAME) 435 INV(atf_equal_dynstr_cstring(ln, 436 basename(atf_dynstr_cstring(&p->m_data)))); 437 #endif /* defined(HAVE_CONST_BASENAME) */ 438 439 return err; 440 } 441 442 bool 443 atf_fs_path_is_absolute(const atf_fs_path_t *p) 444 { 445 return atf_dynstr_cstring(&p->m_data)[0] == '/'; 446 } 447 448 bool 449 atf_fs_path_is_root(const atf_fs_path_t *p) 450 { 451 return atf_equal_dynstr_cstring(&p->m_data, "/"); 452 } 453 454 /* 455 * Modifiers. 456 */ 457 458 atf_error_t 459 atf_fs_path_append_ap(atf_fs_path_t *p, const char *fmt, va_list ap) 460 { 461 atf_dynstr_t aux; 462 atf_error_t err; 463 va_list ap2; 464 465 va_copy(ap2, ap); 466 err = normalize_ap(&aux, fmt, ap2); 467 va_end(ap2); 468 if (!atf_is_error(err)) { 469 const char *auxstr = atf_dynstr_cstring(&aux); 470 const bool needslash = auxstr[0] != '/'; 471 472 err = atf_dynstr_append_fmt(&p->m_data, "%s%s", 473 needslash ? "/" : "", auxstr); 474 475 atf_dynstr_fini(&aux); 476 } 477 478 return err; 479 } 480 481 atf_error_t 482 atf_fs_path_append_fmt(atf_fs_path_t *p, const char *fmt, ...) 483 { 484 va_list ap; 485 atf_error_t err; 486 487 va_start(ap, fmt); 488 err = atf_fs_path_append_ap(p, fmt, ap); 489 va_end(ap); 490 491 return err; 492 } 493 494 atf_error_t 495 atf_fs_path_append_path(atf_fs_path_t *p, const atf_fs_path_t *p2) 496 { 497 return atf_fs_path_append_fmt(p, "%s", atf_dynstr_cstring(&p2->m_data)); 498 } 499 500 atf_error_t 501 atf_fs_path_to_absolute(const atf_fs_path_t *p, atf_fs_path_t *pa) 502 { 503 atf_error_t err; 504 505 PRE(!atf_fs_path_is_absolute(p)); 506 507 err = atf_fs_getcwd(pa); 508 if (atf_is_error(err)) 509 goto out; 510 511 err = atf_fs_path_append_path(pa, p); 512 if (atf_is_error(err)) 513 atf_fs_path_fini(pa); 514 515 out: 516 return err; 517 } 518 519 /* 520 * Operators. 521 */ 522 523 bool atf_equal_fs_path_fs_path(const atf_fs_path_t *p1, 524 const atf_fs_path_t *p2) 525 { 526 return atf_equal_dynstr_dynstr(&p1->m_data, &p2->m_data); 527 } 528 529 /* --------------------------------------------------------------------- 530 * The "atf_fs_path" type. 531 * --------------------------------------------------------------------- */ 532 533 /* 534 * Constants. 535 */ 536 537 const int atf_fs_stat_blk_type = 1; 538 const int atf_fs_stat_chr_type = 2; 539 const int atf_fs_stat_dir_type = 3; 540 const int atf_fs_stat_fifo_type = 4; 541 const int atf_fs_stat_lnk_type = 5; 542 const int atf_fs_stat_reg_type = 6; 543 const int atf_fs_stat_sock_type = 7; 544 const int atf_fs_stat_wht_type = 8; 545 546 /* 547 * Constructors/destructors. 548 */ 549 550 atf_error_t 551 atf_fs_stat_init(atf_fs_stat_t *st, const atf_fs_path_t *p) 552 { 553 atf_error_t err; 554 const char *pstr = atf_fs_path_cstring(p); 555 556 if (lstat(pstr, &st->m_sb) == -1) { 557 err = atf_libc_error(errno, "Cannot get information of %s; " 558 "lstat(2) failed", pstr); 559 } else { 560 int type = st->m_sb.st_mode & S_IFMT; 561 err = atf_no_error(); 562 switch (type) { 563 case S_IFBLK: st->m_type = atf_fs_stat_blk_type; break; 564 case S_IFCHR: st->m_type = atf_fs_stat_chr_type; break; 565 case S_IFDIR: st->m_type = atf_fs_stat_dir_type; break; 566 case S_IFIFO: st->m_type = atf_fs_stat_fifo_type; break; 567 case S_IFLNK: st->m_type = atf_fs_stat_lnk_type; break; 568 case S_IFREG: st->m_type = atf_fs_stat_reg_type; break; 569 case S_IFSOCK: st->m_type = atf_fs_stat_sock_type; break; 570 #if defined(S_IFWHT) 571 case S_IFWHT: st->m_type = atf_fs_stat_wht_type; break; 572 #endif 573 default: 574 err = unknown_type_error(pstr, type); 575 } 576 } 577 578 return err; 579 } 580 581 void 582 atf_fs_stat_copy(atf_fs_stat_t *dest, const atf_fs_stat_t *src) 583 { 584 dest->m_type = src->m_type; 585 dest->m_sb = src->m_sb; 586 } 587 588 void 589 atf_fs_stat_fini(atf_fs_stat_t *st ATF_DEFS_ATTRIBUTE_UNUSED) 590 { 591 } 592 593 /* 594 * Getters. 595 */ 596 597 dev_t 598 atf_fs_stat_get_device(const atf_fs_stat_t *st) 599 { 600 return st->m_sb.st_dev; 601 } 602 603 ino_t 604 atf_fs_stat_get_inode(const atf_fs_stat_t *st) 605 { 606 return st->m_sb.st_ino; 607 } 608 609 mode_t 610 atf_fs_stat_get_mode(const atf_fs_stat_t *st) 611 { 612 return st->m_sb.st_mode & ~S_IFMT; 613 } 614 615 off_t 616 atf_fs_stat_get_size(const atf_fs_stat_t *st) 617 { 618 return st->m_sb.st_size; 619 } 620 621 int 622 atf_fs_stat_get_type(const atf_fs_stat_t *st) 623 { 624 return st->m_type; 625 } 626 627 bool 628 atf_fs_stat_is_owner_readable(const atf_fs_stat_t *st) 629 { 630 return st->m_sb.st_mode & S_IRUSR; 631 } 632 633 bool 634 atf_fs_stat_is_owner_writable(const atf_fs_stat_t *st) 635 { 636 return st->m_sb.st_mode & S_IWUSR; 637 } 638 639 bool 640 atf_fs_stat_is_owner_executable(const atf_fs_stat_t *st) 641 { 642 return st->m_sb.st_mode & S_IXUSR; 643 } 644 645 bool 646 atf_fs_stat_is_group_readable(const atf_fs_stat_t *st) 647 { 648 return st->m_sb.st_mode & S_IRGRP; 649 } 650 651 bool 652 atf_fs_stat_is_group_writable(const atf_fs_stat_t *st) 653 { 654 return st->m_sb.st_mode & S_IWGRP; 655 } 656 657 bool 658 atf_fs_stat_is_group_executable(const atf_fs_stat_t *st) 659 { 660 return st->m_sb.st_mode & S_IXGRP; 661 } 662 663 bool 664 atf_fs_stat_is_other_readable(const atf_fs_stat_t *st) 665 { 666 return st->m_sb.st_mode & S_IROTH; 667 } 668 669 bool 670 atf_fs_stat_is_other_writable(const atf_fs_stat_t *st) 671 { 672 return st->m_sb.st_mode & S_IWOTH; 673 } 674 675 bool 676 atf_fs_stat_is_other_executable(const atf_fs_stat_t *st) 677 { 678 return st->m_sb.st_mode & S_IXOTH; 679 } 680 681 /* --------------------------------------------------------------------- 682 * Free functions. 683 * --------------------------------------------------------------------- */ 684 685 const int atf_fs_access_f = 1 << 0; 686 const int atf_fs_access_r = 1 << 1; 687 const int atf_fs_access_w = 1 << 2; 688 const int atf_fs_access_x = 1 << 3; 689 690 /* 691 * An implementation of access(2) but using the effective user value 692 * instead of the real one. Also avoids false positives for root when 693 * asking for execute permissions, which appear in SunOS. 694 */ 695 atf_error_t 696 atf_fs_eaccess(const atf_fs_path_t *p, int mode) 697 { 698 atf_error_t err; 699 struct stat st; 700 bool ok; 701 702 PRE(mode & atf_fs_access_f || mode & atf_fs_access_r || 703 mode & atf_fs_access_w || mode & atf_fs_access_x); 704 705 if (lstat(atf_fs_path_cstring(p), &st) == -1) { 706 err = atf_libc_error(errno, "Cannot get information from file %s", 707 atf_fs_path_cstring(p)); 708 goto out; 709 } 710 711 err = atf_no_error(); 712 713 /* Early return if we are only checking for existence and the file 714 * exists (stat call returned). */ 715 if (mode & atf_fs_access_f) 716 goto out; 717 718 ok = false; 719 if (atf_user_is_root()) { 720 if (!ok && !(mode & atf_fs_access_x)) { 721 /* Allow root to read/write any file. */ 722 ok = true; 723 } 724 725 if (!ok && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) { 726 /* Allow root to execute the file if any of its execution bits 727 * are set. */ 728 ok = true; 729 } 730 } else { 731 if (!ok && (atf_user_euid() == st.st_uid)) { 732 ok = ((mode & atf_fs_access_r) && (st.st_mode & S_IRUSR)) || 733 ((mode & atf_fs_access_w) && (st.st_mode & S_IWUSR)) || 734 ((mode & atf_fs_access_x) && (st.st_mode & S_IXUSR)); 735 } 736 if (!ok && atf_user_is_member_of_group(st.st_gid)) { 737 ok = ((mode & atf_fs_access_r) && (st.st_mode & S_IRGRP)) || 738 ((mode & atf_fs_access_w) && (st.st_mode & S_IWGRP)) || 739 ((mode & atf_fs_access_x) && (st.st_mode & S_IXGRP)); 740 } 741 if (!ok && ((atf_user_euid() != st.st_uid) && 742 !atf_user_is_member_of_group(st.st_gid))) { 743 ok = ((mode & atf_fs_access_r) && (st.st_mode & S_IROTH)) || 744 ((mode & atf_fs_access_w) && (st.st_mode & S_IWOTH)) || 745 ((mode & atf_fs_access_x) && (st.st_mode & S_IXOTH)); 746 } 747 } 748 749 if (!ok) 750 err = atf_libc_error(EACCES, "Access check failed"); 751 752 out: 753 return err; 754 } 755 756 atf_error_t 757 atf_fs_exists(const atf_fs_path_t *p, bool *b) 758 { 759 atf_error_t err; 760 761 err = atf_fs_eaccess(p, atf_fs_access_f); 762 if (atf_is_error(err)) { 763 if (atf_error_is(err, "libc") && atf_libc_error_code(err) == ENOENT) { 764 atf_error_free(err); 765 err = atf_no_error(); 766 *b = false; 767 } 768 } else 769 *b = true; 770 771 return err; 772 } 773 774 atf_error_t 775 atf_fs_getcwd(atf_fs_path_t *p) 776 { 777 atf_error_t err; 778 char *cwd; 779 780 #if defined(HAVE_GETCWD_DYN) 781 cwd = getcwd(NULL, 0); 782 #else 783 cwd = getcwd(NULL, MAXPATHLEN); 784 #endif 785 if (cwd == NULL) { 786 err = atf_libc_error(errno, "Cannot determine current directory"); 787 goto out; 788 } 789 790 err = atf_fs_path_init_fmt(p, "%s", cwd); 791 free(cwd); 792 793 out: 794 return err; 795 } 796 797 atf_error_t 798 atf_fs_mkdtemp(atf_fs_path_t *p) 799 { 800 atf_error_t err; 801 char *buf; 802 803 if (!check_umask(S_IRWXU, S_IRWXU)) { 804 err = invalid_umask_error(p, atf_fs_stat_dir_type, current_umask()); 805 goto out; 806 } 807 808 err = copy_contents(p, &buf); 809 if (atf_is_error(err)) 810 goto out; 811 812 err = do_mkdtemp(buf); 813 if (atf_is_error(err)) 814 goto out_buf; 815 816 replace_contents(p, buf); 817 818 INV(!atf_is_error(err)); 819 out_buf: 820 free(buf); 821 out: 822 return err; 823 } 824 825 atf_error_t 826 atf_fs_mkstemp(atf_fs_path_t *p, int *fdout) 827 { 828 atf_error_t err; 829 char *buf; 830 int fd; 831 832 if (!check_umask(S_IRWXU, S_IRWXU)) { 833 err = invalid_umask_error(p, atf_fs_stat_reg_type, current_umask()); 834 goto out; 835 } 836 837 err = copy_contents(p, &buf); 838 if (atf_is_error(err)) 839 goto out; 840 841 err = do_mkstemp(buf, &fd); 842 if (atf_is_error(err)) 843 goto out_buf; 844 845 replace_contents(p, buf); 846 *fdout = fd; 847 848 INV(!atf_is_error(err)); 849 out_buf: 850 free(buf); 851 out: 852 return err; 853 } 854 855 atf_error_t 856 atf_fs_rmdir(const atf_fs_path_t *p) 857 { 858 atf_error_t err; 859 860 if (rmdir(atf_fs_path_cstring(p))) { 861 if (errno == EEXIST) { 862 /* Some operating systems (e.g. OpenSolaris 200906) return 863 * EEXIST instead of ENOTEMPTY for non-empty directories. 864 * Homogenize the return value so that callers don't need 865 * to bother about differences in operating systems. */ 866 errno = ENOTEMPTY; 867 } 868 err = atf_libc_error(errno, "Cannot remove directory"); 869 } else 870 err = atf_no_error(); 871 872 return err; 873 } 874 875 atf_error_t 876 atf_fs_unlink(const atf_fs_path_t *p) 877 { 878 atf_error_t err; 879 const char *path; 880 881 path = atf_fs_path_cstring(p); 882 883 if (unlink(path) != 0) 884 err = atf_libc_error(errno, "Cannot unlink file: '%s'", path); 885 else 886 err = atf_no_error(); 887 888 return err; 889 } 890