1 /*- 2 * Copyright (c) 1990, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $OpenBSD: fts.c,v 1.22 1999/10/03 19:22:22 millert Exp $ 30 */ 31 32 #if 0 33 #if defined(LIBC_SCCS) && !defined(lint) 34 static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94"; 35 #endif /* LIBC_SCCS and not lint */ 36 #endif 37 38 #include <sys/cdefs.h> 39 40 #ifdef __HAIKU__ 41 #include <sys/param.h> 42 #include <sys/stat.h> 43 44 #include <dirent.h> 45 #include <errno.h> 46 #include <fcntl.h> 47 #include <fts.h> 48 #include <stdlib.h> 49 #include <string.h> 50 #include <unistd.h> 51 #else 52 __FBSDID("$FreeBSD$"); 53 54 #include "namespace.h" 55 #include <sys/param.h> 56 #include <sys/mount.h> 57 #include <sys/stat.h> 58 59 #include <dirent.h> 60 #include <errno.h> 61 #include <fcntl.h> 62 #include <fts.h> 63 #include <stdlib.h> 64 #include <string.h> 65 #include <unistd.h> 66 #include "un-namespace.h" 67 68 #include "gen-private.h" 69 #endif 70 71 static FTSENT *fts_alloc(FTS *, char *, size_t); 72 static FTSENT *fts_build(FTS *, int); 73 static void fts_lfree(FTSENT *); 74 static void fts_load(FTS *, FTSENT *); 75 static size_t fts_maxarglen(char * const *); 76 static void fts_padjust(FTS *, FTSENT *); 77 static int fts_palloc(FTS *, size_t); 78 static FTSENT *fts_sort(FTS *, FTSENT *, size_t); 79 static int fts_stat(FTS *, FTSENT *, int); 80 static int fts_safe_changedir(FTS *, FTSENT *, int, char *); 81 static int fts_ufslinks(FTS *, const FTSENT *); 82 83 84 FTS * __fts_open(char * const *argv, int options, int (*compar)( 85 const FTSENT * const *, const FTSENT * const *)); 86 int __fts_close(FTS *sp); 87 FTSENT * __fts_read(FTS *sp); 88 int __fts_set(FTS *sp, FTSENT *p, int instr); 89 FTSENT * __fts_children(FTS *sp, int instr); 90 void *(__fts_get_clientptr)(FTS *sp); 91 FTS * (__fts_get_stream)(FTSENT *p); 92 void __fts_set_clientptr(FTS *sp, void *clientptr); 93 94 95 #define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2]))) 96 97 #define CLR(opt) (sp->fts_options &= ~(opt)) 98 #define ISSET(opt) (sp->fts_options & (opt)) 99 #define SET(opt) (sp->fts_options |= (opt)) 100 101 #define FCHDIR(sp, fd) (!ISSET(FTS_NOCHDIR) && fchdir(fd)) 102 103 /* fts_build flags */ 104 #define BCHILD 1 /* fts_children */ 105 #define BNAMES 2 /* fts_children, names only */ 106 #define BREAD 3 /* fts_read */ 107 108 /* 109 * Internal representation of an FTS, including extra implementation 110 * details. The FTS returned from fts_open points to this structure's 111 * ftsp_fts member (and can be cast to an _fts_private as required) 112 */ 113 struct _fts_private { 114 FTS ftsp_fts; 115 #ifndef __HAIKU__ 116 struct statfs ftsp_statfs; 117 #endif 118 dev_t ftsp_dev; 119 int ftsp_linksreliable; 120 }; 121 122 #ifndef __HAIKU__ 123 /* 124 * The "FTS_NOSTAT" option can avoid a lot of calls to stat(2) if it 125 * knows that a directory could not possibly have subdirectories. This 126 * is decided by looking at the link count: a subdirectory would 127 * increment its parent's link count by virtue of its own ".." entry. 128 * This assumption only holds for UFS-like filesystems that implement 129 * links and directories this way, so we must punt for others. 130 */ 131 132 static const char *ufslike_filesystems[] = { 133 "ufs", 134 "zfs", 135 "nfs", 136 "nfs4", 137 "ext2fs", 138 0 139 }; 140 #endif /* !__HAIKU__ */ 141 142 FTS * 143 __fts_open(argv, options, compar) 144 char * const *argv; 145 int options; 146 int (*compar)(const FTSENT * const *, const FTSENT * const *); 147 { 148 struct _fts_private *priv; 149 FTS *sp; 150 FTSENT *p, *root; 151 FTSENT *parent, *tmp; 152 size_t len, nitems; 153 154 /* Options check. */ 155 if (options & ~FTS_OPTIONMASK) { 156 errno = EINVAL; 157 return (NULL); 158 } 159 160 /* fts_open() requires at least one path */ 161 if (*argv == NULL) { 162 errno = EINVAL; 163 return (NULL); 164 } 165 166 /* Allocate/initialize the stream. */ 167 if ((priv = calloc(1, sizeof(*priv))) == NULL) 168 return (NULL); 169 sp = &priv->ftsp_fts; 170 sp->fts_compar = compar; 171 sp->fts_options = options; 172 173 /* Shush, GCC. */ 174 tmp = NULL; 175 176 /* Logical walks turn on NOCHDIR; symbolic links are too hard. */ 177 if (ISSET(FTS_LOGICAL)) 178 SET(FTS_NOCHDIR); 179 180 /* 181 * Start out with 1K of path space, and enough, in any case, 182 * to hold the user's paths. 183 */ 184 if (fts_palloc(sp, MAX(fts_maxarglen(argv), MAXPATHLEN))) 185 goto mem1; 186 187 /* Allocate/initialize root's parent. */ 188 if ((parent = fts_alloc(sp, "", 0)) == NULL) 189 goto mem2; 190 parent->fts_level = FTS_ROOTPARENTLEVEL; 191 192 /* Allocate/initialize root(s). */ 193 for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) { 194 /* Don't allow zero-length paths. */ 195 if ((len = strlen(*argv)) == 0) { 196 errno = ENOENT; 197 goto mem3; 198 } 199 200 p = fts_alloc(sp, *argv, len); 201 p->fts_level = FTS_ROOTLEVEL; 202 p->fts_parent = parent; 203 p->fts_accpath = p->fts_name; 204 p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW)); 205 206 /* Command-line "." and ".." are real directories. */ 207 if (p->fts_info == FTS_DOT) 208 p->fts_info = FTS_D; 209 210 /* 211 * If comparison routine supplied, traverse in sorted 212 * order; otherwise traverse in the order specified. 213 */ 214 if (compar) { 215 p->fts_link = root; 216 root = p; 217 } else { 218 p->fts_link = NULL; 219 if (root == NULL) 220 tmp = root = p; 221 else { 222 tmp->fts_link = p; 223 tmp = p; 224 } 225 } 226 } 227 if (compar && nitems > 1) 228 root = fts_sort(sp, root, nitems); 229 230 /* 231 * Allocate a dummy pointer and make fts_read think that we've just 232 * finished the node before the root(s); set p->fts_info to FTS_INIT 233 * so that everything about the "current" node is ignored. 234 */ 235 if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL) 236 goto mem3; 237 sp->fts_cur->fts_link = root; 238 sp->fts_cur->fts_info = FTS_INIT; 239 240 /* 241 * If using chdir(2), grab a file descriptor pointing to dot to ensure 242 * that we can get back here; this could be avoided for some paths, 243 * but almost certainly not worth the effort. Slashes, symbolic links, 244 * and ".." are all fairly nasty problems. Note, if we can't get the 245 * descriptor we run anyway, just more slowly. 246 */ 247 if (!ISSET(FTS_NOCHDIR) && 248 (sp->fts_rfd = open(".", O_RDONLY | O_CLOEXEC, 0)) < 0) 249 SET(FTS_NOCHDIR); 250 251 return (sp); 252 253 mem3: fts_lfree(root); 254 free(parent); 255 mem2: free(sp->fts_path); 256 mem1: free(sp); 257 return (NULL); 258 } 259 260 261 __weak_reference(__fts_open, fts_open); 262 263 264 static void 265 fts_load(FTS *sp, FTSENT *p) 266 { 267 size_t len; 268 char *cp; 269 270 /* 271 * Load the stream structure for the next traversal. Since we don't 272 * actually enter the directory until after the preorder visit, set 273 * the fts_accpath field specially so the chdir gets done to the right 274 * place and the user can access the first node. From fts_open it's 275 * known that the path will fit. 276 */ 277 len = p->fts_pathlen = p->fts_namelen; 278 memmove(sp->fts_path, p->fts_name, len + 1); 279 if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) { 280 len = strlen(++cp); 281 memmove(p->fts_name, cp, len + 1); 282 p->fts_namelen = len; 283 } 284 p->fts_accpath = p->fts_path = sp->fts_path; 285 sp->fts_dev = p->fts_dev; 286 } 287 288 int 289 __fts_close(FTS *sp) 290 { 291 FTSENT *freep, *p; 292 int saved_errno; 293 294 /* 295 * This still works if we haven't read anything -- the dummy structure 296 * points to the root list, so we step through to the end of the root 297 * list which has a valid parent pointer. 298 */ 299 if (sp->fts_cur) { 300 for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) { 301 freep = p; 302 p = p->fts_link != NULL ? p->fts_link : p->fts_parent; 303 free(freep); 304 } 305 free(p); 306 } 307 308 /* Free up child linked list, sort array, path buffer. */ 309 if (sp->fts_child) 310 fts_lfree(sp->fts_child); 311 if (sp->fts_array) 312 free(sp->fts_array); 313 free(sp->fts_path); 314 315 /* Return to original directory, save errno if necessary. */ 316 if (!ISSET(FTS_NOCHDIR)) { 317 saved_errno = fchdir(sp->fts_rfd) ? errno : 0; 318 (void)close(sp->fts_rfd); 319 320 /* Set errno and return. */ 321 if (saved_errno != 0) { 322 /* Free up the stream pointer. */ 323 free(sp); 324 errno = saved_errno; 325 return (-1); 326 } 327 } 328 329 /* Free up the stream pointer. */ 330 free(sp); 331 return (0); 332 } 333 334 335 __weak_reference(__fts_close, fts_close); 336 337 338 /* 339 * Special case of "/" at the end of the path so that slashes aren't 340 * appended which would cause paths to be written as "....//foo". 341 */ 342 #define NAPPEND(p) \ 343 (p->fts_path[p->fts_pathlen - 1] == '/' \ 344 ? p->fts_pathlen - 1 : p->fts_pathlen) 345 346 FTSENT * 347 __fts_read(FTS *sp) 348 { 349 FTSENT *p, *tmp; 350 int instr; 351 char *t; 352 int saved_errno; 353 354 /* If finished or unrecoverable error, return NULL. */ 355 if (sp->fts_cur == NULL || ISSET(FTS_STOP)) 356 return (NULL); 357 358 /* Set current node pointer. */ 359 p = sp->fts_cur; 360 361 /* Save and zero out user instructions. */ 362 instr = p->fts_instr; 363 p->fts_instr = FTS_NOINSTR; 364 365 /* Any type of file may be re-visited; re-stat and re-turn. */ 366 if (instr == FTS_AGAIN) { 367 p->fts_info = fts_stat(sp, p, 0); 368 return (p); 369 } 370 371 /* 372 * Following a symlink -- SLNONE test allows application to see 373 * SLNONE and recover. If indirecting through a symlink, have 374 * keep a pointer to current location. If unable to get that 375 * pointer, follow fails. 376 */ 377 if (instr == FTS_FOLLOW && 378 (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) { 379 p->fts_info = fts_stat(sp, p, 1); 380 if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { 381 if ((p->fts_symfd = open(".", O_RDONLY | O_CLOEXEC, 382 0)) < 0) { 383 p->fts_errno = errno; 384 p->fts_info = FTS_ERR; 385 } else 386 p->fts_flags |= FTS_SYMFOLLOW; 387 } 388 return (p); 389 } 390 391 /* Directory in pre-order. */ 392 if (p->fts_info == FTS_D) { 393 /* If skipped or crossed mount point, do post-order visit. */ 394 if (instr == FTS_SKIP || 395 (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) { 396 if (p->fts_flags & FTS_SYMFOLLOW) 397 (void)close(p->fts_symfd); 398 if (sp->fts_child) { 399 fts_lfree(sp->fts_child); 400 sp->fts_child = NULL; 401 } 402 p->fts_info = FTS_DP; 403 return (p); 404 } 405 406 /* Rebuild if only read the names and now traversing. */ 407 if (sp->fts_child != NULL && ISSET(FTS_NAMEONLY)) { 408 CLR(FTS_NAMEONLY); 409 fts_lfree(sp->fts_child); 410 sp->fts_child = NULL; 411 } 412 413 /* 414 * Cd to the subdirectory. 415 * 416 * If have already read and now fail to chdir, whack the list 417 * to make the names come out right, and set the parent errno 418 * so the application will eventually get an error condition. 419 * Set the FTS_DONTCHDIR flag so that when we logically change 420 * directories back to the parent we don't do a chdir. 421 * 422 * If haven't read do so. If the read fails, fts_build sets 423 * FTS_STOP or the fts_info field of the node. 424 */ 425 if (sp->fts_child != NULL) { 426 if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) { 427 p->fts_errno = errno; 428 p->fts_flags |= FTS_DONTCHDIR; 429 for (p = sp->fts_child; p != NULL; 430 p = p->fts_link) 431 p->fts_accpath = 432 p->fts_parent->fts_accpath; 433 } 434 } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) { 435 if (ISSET(FTS_STOP)) 436 return (NULL); 437 return (p); 438 } 439 p = sp->fts_child; 440 sp->fts_child = NULL; 441 goto name; 442 } 443 444 /* Move to the next node on this level. */ 445 next: tmp = p; 446 if ((p = p->fts_link) != NULL) { 447 free(tmp); 448 449 /* 450 * If reached the top, return to the original directory (or 451 * the root of the tree), and load the paths for the next root. 452 */ 453 if (p->fts_level == FTS_ROOTLEVEL) { 454 if (FCHDIR(sp, sp->fts_rfd)) { 455 SET(FTS_STOP); 456 return (NULL); 457 } 458 fts_load(sp, p); 459 return (sp->fts_cur = p); 460 } 461 462 /* 463 * User may have called fts_set on the node. If skipped, 464 * ignore. If followed, get a file descriptor so we can 465 * get back if necessary. 466 */ 467 if (p->fts_instr == FTS_SKIP) 468 goto next; 469 if (p->fts_instr == FTS_FOLLOW) { 470 p->fts_info = fts_stat(sp, p, 1); 471 if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { 472 if ((p->fts_symfd = 473 open(".", O_RDONLY | O_CLOEXEC, 0)) < 0) { 474 p->fts_errno = errno; 475 p->fts_info = FTS_ERR; 476 } else 477 p->fts_flags |= FTS_SYMFOLLOW; 478 } 479 p->fts_instr = FTS_NOINSTR; 480 } 481 482 name: t = sp->fts_path + NAPPEND(p->fts_parent); 483 *t++ = '/'; 484 memmove(t, p->fts_name, p->fts_namelen + 1); 485 return (sp->fts_cur = p); 486 } 487 488 /* Move up to the parent node. */ 489 p = tmp->fts_parent; 490 free(tmp); 491 492 if (p->fts_level == FTS_ROOTPARENTLEVEL) { 493 /* 494 * Done; free everything up and set errno to 0 so the user 495 * can distinguish between error and EOF. 496 */ 497 free(p); 498 errno = 0; 499 return (sp->fts_cur = NULL); 500 } 501 502 /* NUL terminate the pathname. */ 503 sp->fts_path[p->fts_pathlen] = '\0'; 504 505 /* 506 * Return to the parent directory. If at a root node or came through 507 * a symlink, go back through the file descriptor. Otherwise, cd up 508 * one directory. 509 */ 510 if (p->fts_level == FTS_ROOTLEVEL) { 511 if (FCHDIR(sp, sp->fts_rfd)) { 512 SET(FTS_STOP); 513 return (NULL); 514 } 515 } else if (p->fts_flags & FTS_SYMFOLLOW) { 516 if (FCHDIR(sp, p->fts_symfd)) { 517 saved_errno = errno; 518 (void)close(p->fts_symfd); 519 errno = saved_errno; 520 SET(FTS_STOP); 521 return (NULL); 522 } 523 (void)close(p->fts_symfd); 524 } else if (!(p->fts_flags & FTS_DONTCHDIR) && 525 fts_safe_changedir(sp, p->fts_parent, -1, "..")) { 526 SET(FTS_STOP); 527 return (NULL); 528 } 529 p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP; 530 return (sp->fts_cur = p); 531 } 532 533 534 __weak_reference(__fts_read, fts_read); 535 536 537 /* 538 * Fts_set takes the stream as an argument although it's not used in this 539 * implementation; it would be necessary if anyone wanted to add global 540 * semantics to fts using fts_set. An error return is allowed for similar 541 * reasons. 542 */ 543 /* ARGSUSED */ 544 int 545 __fts_set(FTS *sp, FTSENT *p, int instr) 546 { 547 if (instr != 0 && instr != FTS_AGAIN && instr != FTS_FOLLOW && 548 instr != FTS_NOINSTR && instr != FTS_SKIP) { 549 errno = EINVAL; 550 return (1); 551 } 552 p->fts_instr = instr; 553 return (0); 554 } 555 556 557 __weak_reference(__fts_set, fts_set); 558 559 560 FTSENT * 561 __fts_children(FTS *sp, int instr) 562 { 563 FTSENT *p; 564 int fd; 565 566 if (instr != 0 && instr != FTS_NAMEONLY) { 567 errno = EINVAL; 568 return (NULL); 569 } 570 571 /* Set current node pointer. */ 572 p = sp->fts_cur; 573 574 /* 575 * Errno set to 0 so user can distinguish empty directory from 576 * an error. 577 */ 578 errno = 0; 579 580 /* Fatal errors stop here. */ 581 if (ISSET(FTS_STOP)) 582 return (NULL); 583 584 /* Return logical hierarchy of user's arguments. */ 585 if (p->fts_info == FTS_INIT) 586 return (p->fts_link); 587 588 /* 589 * If not a directory being visited in pre-order, stop here. Could 590 * allow FTS_DNR, assuming the user has fixed the problem, but the 591 * same effect is available with FTS_AGAIN. 592 */ 593 if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */) 594 return (NULL); 595 596 /* Free up any previous child list. */ 597 if (sp->fts_child != NULL) 598 fts_lfree(sp->fts_child); 599 600 if (instr == FTS_NAMEONLY) { 601 SET(FTS_NAMEONLY); 602 instr = BNAMES; 603 } else 604 instr = BCHILD; 605 606 /* 607 * If using chdir on a relative path and called BEFORE fts_read does 608 * its chdir to the root of a traversal, we can lose -- we need to 609 * chdir into the subdirectory, and we don't know where the current 610 * directory is, so we can't get back so that the upcoming chdir by 611 * fts_read will work. 612 */ 613 if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' || 614 ISSET(FTS_NOCHDIR)) 615 return (sp->fts_child = fts_build(sp, instr)); 616 617 if ((fd = open(".", O_RDONLY | O_CLOEXEC, 0)) < 0) 618 return (NULL); 619 sp->fts_child = fts_build(sp, instr); 620 if (fchdir(fd)) { 621 (void)close(fd); 622 return (NULL); 623 } 624 (void)close(fd); 625 return (sp->fts_child); 626 } 627 628 629 __weak_reference(__fts_children, fts_children); 630 631 632 #ifndef fts_get_clientptr 633 #error "fts_get_clientptr not defined" 634 #endif 635 636 void * 637 (__fts_get_clientptr)(FTS *sp) 638 { 639 640 return (fts_get_clientptr(sp)); 641 } 642 643 644 __weak_reference(__fts_get_clientptr, fts_get_clientptr); 645 646 647 #ifndef fts_get_stream 648 #error "fts_get_stream not defined" 649 #endif 650 651 FTS * 652 (__fts_get_stream)(FTSENT *p) 653 { 654 return (fts_get_stream(p)); 655 } 656 657 658 __weak_reference(__fts_get_stream, fts_get_stream); 659 660 661 void 662 __fts_set_clientptr(FTS *sp, void *clientptr) 663 { 664 665 sp->fts_clientptr = clientptr; 666 } 667 668 669 __weak_reference(__fts_set_clientptr, fts_set_clientptr); 670 671 672 /* 673 * This is the tricky part -- do not casually change *anything* in here. The 674 * idea is to build the linked list of entries that are used by fts_children 675 * and fts_read. There are lots of special cases. 676 * 677 * The real slowdown in walking the tree is the stat calls. If FTS_NOSTAT is 678 * set and it's a physical walk (so that symbolic links can't be directories), 679 * we can do things quickly. First, if it's a 4.4BSD file system, the type 680 * of the file is in the directory entry. Otherwise, we assume that the number 681 * of subdirectories in a node is equal to the number of links to the parent. 682 * The former skips all stat calls. The latter skips stat calls in any leaf 683 * directories and for any files after the subdirectories in the directory have 684 * been found, cutting the stat calls by about 2/3. 685 */ 686 static FTSENT * 687 fts_build(FTS *sp, int type) 688 { 689 struct dirent *dp; 690 FTSENT *p, *head; 691 FTSENT *cur, *tail; 692 DIR *dirp; 693 void *oldaddr; 694 char *cp; 695 int cderrno, descend, saved_errno, nostat, doadjust; 696 #ifdef FTS_WHITEOUT 697 int oflag; 698 #endif 699 long level; 700 long nlinks; /* has to be signed because -1 is a magic value */ 701 size_t dnamlen, len, maxlen, nitems; 702 703 /* Set current node pointer. */ 704 cur = sp->fts_cur; 705 706 /* 707 * Open the directory for reading. If this fails, we're done. 708 * If being called from fts_read, set the fts_info field. 709 */ 710 #ifdef FTS_WHITEOUT 711 if (ISSET(FTS_WHITEOUT)) 712 oflag = DTF_NODUP | DTF_REWIND; 713 else 714 oflag = DTF_HIDEW | DTF_NODUP | DTF_REWIND; 715 #else 716 #define __opendir2(path, flag) opendir(path) 717 #endif 718 if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) { 719 if (type == BREAD) { 720 cur->fts_info = FTS_DNR; 721 cur->fts_errno = errno; 722 } 723 return (NULL); 724 } 725 726 /* 727 * Nlinks is the number of possible entries of type directory in the 728 * directory if we're cheating on stat calls, 0 if we're not doing 729 * any stat calls at all, -1 if we're doing stats on everything. 730 */ 731 if (type == BNAMES) { 732 nlinks = 0; 733 /* Be quiet about nostat, GCC. */ 734 nostat = 0; 735 } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) { 736 if (fts_ufslinks(sp, cur)) 737 nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2); 738 else 739 nlinks = -1; 740 nostat = 1; 741 } else { 742 nlinks = -1; 743 nostat = 0; 744 } 745 746 #ifdef notdef 747 (void)printf("nlinks == %d (cur: %d)\n", nlinks, cur->fts_nlink); 748 (void)printf("NOSTAT %d PHYSICAL %d SEEDOT %d\n", 749 ISSET(FTS_NOSTAT), ISSET(FTS_PHYSICAL), ISSET(FTS_SEEDOT)); 750 #endif 751 /* 752 * If we're going to need to stat anything or we want to descend 753 * and stay in the directory, chdir. If this fails we keep going, 754 * but set a flag so we don't chdir after the post-order visit. 755 * We won't be able to stat anything, but we can still return the 756 * names themselves. Note, that since fts_read won't be able to 757 * chdir into the directory, it will have to return different path 758 * names than before, i.e. "a/b" instead of "b". Since the node 759 * has already been visited in pre-order, have to wait until the 760 * post-order visit to return the error. There is a special case 761 * here, if there was nothing to stat then it's not an error to 762 * not be able to stat. This is all fairly nasty. If a program 763 * needed sorted entries or stat information, they had better be 764 * checking FTS_NS on the returned nodes. 765 */ 766 cderrno = 0; 767 if (nlinks || type == BREAD) { 768 if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) { 769 if (nlinks && type == BREAD) 770 cur->fts_errno = errno; 771 cur->fts_flags |= FTS_DONTCHDIR; 772 descend = 0; 773 cderrno = errno; 774 } else 775 descend = 1; 776 } else 777 descend = 0; 778 779 /* 780 * Figure out the max file name length that can be stored in the 781 * current path -- the inner loop allocates more path as necessary. 782 * We really wouldn't have to do the maxlen calculations here, we 783 * could do them in fts_read before returning the path, but it's a 784 * lot easier here since the length is part of the dirent structure. 785 * 786 * If not changing directories set a pointer so that can just append 787 * each new name into the path. 788 */ 789 len = NAPPEND(cur); 790 if (ISSET(FTS_NOCHDIR)) { 791 cp = sp->fts_path + len; 792 *cp++ = '/'; 793 } else { 794 /* GCC, you're too verbose. */ 795 cp = NULL; 796 } 797 len++; 798 maxlen = sp->fts_pathlen - len; 799 800 level = cur->fts_level + 1; 801 802 /* Read the directory, attaching each entry to the `link' pointer. */ 803 doadjust = 0; 804 for (head = tail = NULL, nitems = 0; dirp && (dp = readdir(dirp));) { 805 dnamlen = strlen(dp->d_name); 806 if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name)) 807 continue; 808 809 if ((p = fts_alloc(sp, dp->d_name, dnamlen)) == NULL) 810 goto mem1; 811 if (dnamlen >= maxlen) { /* include space for NUL */ 812 oldaddr = sp->fts_path; 813 if (fts_palloc(sp, dnamlen + len + 1)) { 814 /* 815 * No more memory for path or structures. Save 816 * errno, free up the current structure and the 817 * structures already allocated. 818 */ 819 mem1: saved_errno = errno; 820 if (p) 821 free(p); 822 fts_lfree(head); 823 (void)closedir(dirp); 824 cur->fts_info = FTS_ERR; 825 SET(FTS_STOP); 826 errno = saved_errno; 827 return (NULL); 828 } 829 /* Did realloc() change the pointer? */ 830 if (oldaddr != sp->fts_path) { 831 doadjust = 1; 832 if (ISSET(FTS_NOCHDIR)) 833 cp = sp->fts_path + len; 834 } 835 maxlen = sp->fts_pathlen - len; 836 } 837 838 p->fts_level = level; 839 p->fts_parent = sp->fts_cur; 840 p->fts_pathlen = len + dnamlen; 841 842 #ifdef FTS_WHITEOUT 843 if (dp->d_type == DT_WHT) 844 p->fts_flags |= FTS_ISW; 845 #endif 846 847 if (cderrno) { 848 if (nlinks) { 849 p->fts_info = FTS_NS; 850 p->fts_errno = cderrno; 851 } else 852 p->fts_info = FTS_NSOK; 853 p->fts_accpath = cur->fts_accpath; 854 } else if (nlinks == 0 855 #ifdef DT_DIR 856 || (nostat && 857 dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN) 858 #endif 859 ) { 860 p->fts_accpath = 861 ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name; 862 p->fts_info = FTS_NSOK; 863 } else { 864 /* Build a file name for fts_stat to stat. */ 865 if (ISSET(FTS_NOCHDIR)) { 866 p->fts_accpath = p->fts_path; 867 memmove(cp, p->fts_name, p->fts_namelen + 1); 868 } else 869 p->fts_accpath = p->fts_name; 870 /* Stat it. */ 871 p->fts_info = fts_stat(sp, p, 0); 872 873 /* Decrement link count if applicable. */ 874 if (nlinks > 0 && (p->fts_info == FTS_D || 875 p->fts_info == FTS_DC || p->fts_info == FTS_DOT)) 876 --nlinks; 877 } 878 879 /* We walk in directory order so "ls -f" doesn't get upset. */ 880 p->fts_link = NULL; 881 if (head == NULL) 882 head = tail = p; 883 else { 884 tail->fts_link = p; 885 tail = p; 886 } 887 ++nitems; 888 } 889 if (dirp) 890 (void)closedir(dirp); 891 892 /* 893 * If realloc() changed the address of the path, adjust the 894 * addresses for the rest of the tree and the dir list. 895 */ 896 if (doadjust) 897 fts_padjust(sp, head); 898 899 /* 900 * If not changing directories, reset the path back to original 901 * state. 902 */ 903 if (ISSET(FTS_NOCHDIR)) 904 sp->fts_path[cur->fts_pathlen] = '\0'; 905 906 /* 907 * If descended after called from fts_children or after called from 908 * fts_read and nothing found, get back. At the root level we use 909 * the saved fd; if one of fts_open()'s arguments is a relative path 910 * to an empty directory, we wind up here with no other way back. If 911 * can't get back, we're done. 912 */ 913 if (descend && (type == BCHILD || !nitems) && 914 (cur->fts_level == FTS_ROOTLEVEL ? 915 FCHDIR(sp, sp->fts_rfd) : 916 fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) { 917 cur->fts_info = FTS_ERR; 918 SET(FTS_STOP); 919 return (NULL); 920 } 921 922 /* If didn't find anything, return NULL. */ 923 if (!nitems) { 924 if (type == BREAD) 925 cur->fts_info = FTS_DP; 926 return (NULL); 927 } 928 929 /* Sort the entries. */ 930 if (sp->fts_compar && nitems > 1) 931 head = fts_sort(sp, head, nitems); 932 return (head); 933 } 934 935 static int 936 fts_stat(FTS *sp, FTSENT *p, int follow) 937 { 938 FTSENT *t; 939 dev_t dev; 940 ino_t ino; 941 struct stat *sbp, sb; 942 int saved_errno; 943 944 /* If user needs stat info, stat buffer already allocated. */ 945 sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp; 946 947 #ifdef FTS_WHITEOUT 948 /* Check for whiteout. */ 949 if (p->fts_flags & FTS_ISW) { 950 if (sbp != &sb) { 951 memset(sbp, '\0', sizeof(*sbp)); 952 sbp->st_mode = S_IFWHT; 953 } 954 return (FTS_W); 955 } 956 #endif 957 958 /* 959 * If doing a logical walk, or application requested FTS_FOLLOW, do 960 * a stat(2). If that fails, check for a non-existent symlink. If 961 * fail, set the errno from the stat call. 962 */ 963 if (ISSET(FTS_LOGICAL) || follow) { 964 if (stat(p->fts_accpath, sbp)) { 965 saved_errno = errno; 966 if (!lstat(p->fts_accpath, sbp)) { 967 errno = 0; 968 return (FTS_SLNONE); 969 } 970 p->fts_errno = saved_errno; 971 goto err; 972 } 973 } else if (lstat(p->fts_accpath, sbp)) { 974 p->fts_errno = errno; 975 err: memset(sbp, 0, sizeof(struct stat)); 976 return (FTS_NS); 977 } 978 979 if (S_ISDIR(sbp->st_mode)) { 980 /* 981 * Set the device/inode. Used to find cycles and check for 982 * crossing mount points. Also remember the link count, used 983 * in fts_build to limit the number of stat calls. It is 984 * understood that these fields are only referenced if fts_info 985 * is set to FTS_D. 986 */ 987 dev = p->fts_dev = sbp->st_dev; 988 ino = p->fts_ino = sbp->st_ino; 989 p->fts_nlink = sbp->st_nlink; 990 991 if (ISDOT(p->fts_name)) 992 return (FTS_DOT); 993 994 /* 995 * Cycle detection is done by brute force when the directory 996 * is first encountered. If the tree gets deep enough or the 997 * number of symbolic links to directories is high enough, 998 * something faster might be worthwhile. 999 */ 1000 for (t = p->fts_parent; 1001 t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent) 1002 if (ino == t->fts_ino && dev == t->fts_dev) { 1003 p->fts_cycle = t; 1004 return (FTS_DC); 1005 } 1006 return (FTS_D); 1007 } 1008 if (S_ISLNK(sbp->st_mode)) 1009 return (FTS_SL); 1010 if (S_ISREG(sbp->st_mode)) 1011 return (FTS_F); 1012 return (FTS_DEFAULT); 1013 } 1014 1015 /* 1016 * The comparison function takes pointers to pointers to FTSENT structures. 1017 * Qsort wants a comparison function that takes pointers to void. 1018 * (Both with appropriate levels of const-poisoning, of course!) 1019 * Use a trampoline function to deal with the difference. 1020 */ 1021 static int 1022 fts_compar(const void *a, const void *b) 1023 { 1024 FTS *parent; 1025 1026 parent = (*(const FTSENT * const *)a)->fts_fts; 1027 return (*parent->fts_compar)(a, b); 1028 } 1029 1030 static FTSENT * 1031 fts_sort(FTS *sp, FTSENT *head, size_t nitems) 1032 { 1033 FTSENT **ap, *p; 1034 FTSENT **old_array; 1035 1036 /* 1037 * Construct an array of pointers to the structures and call qsort(3). 1038 * Reassemble the array in the order returned by qsort. If unable to 1039 * sort for memory reasons, return the directory entries in their 1040 * current order. Allocate enough space for the current needs plus 1041 * 40 so don't realloc one entry at a time. 1042 */ 1043 if (nitems > sp->fts_nitems) { 1044 sp->fts_nitems = nitems + 40; 1045 old_array = sp->fts_array; 1046 if ((sp->fts_array = realloc(old_array, 1047 sp->fts_nitems * sizeof(FTSENT *))) == NULL) { 1048 free(old_array); 1049 sp->fts_nitems = 0; 1050 return (head); 1051 } 1052 } 1053 for (ap = sp->fts_array, p = head; p; p = p->fts_link) 1054 *ap++ = p; 1055 qsort(sp->fts_array, nitems, sizeof(FTSENT *), fts_compar); 1056 for (head = *(ap = sp->fts_array); --nitems; ++ap) 1057 ap[0]->fts_link = ap[1]; 1058 ap[0]->fts_link = NULL; 1059 return (head); 1060 } 1061 1062 static FTSENT * 1063 fts_alloc(FTS *sp, char *name, size_t namelen) 1064 { 1065 FTSENT *p; 1066 size_t len; 1067 1068 struct ftsent_withstat { 1069 FTSENT ent; 1070 struct stat statbuf; 1071 }; 1072 1073 /* 1074 * The file name is a variable length array and no stat structure is 1075 * necessary if the user has set the nostat bit. Allocate the FTSENT 1076 * structure, the file name and the stat structure in one chunk, but 1077 * be careful that the stat structure is reasonably aligned. 1078 */ 1079 if (ISSET(FTS_NOSTAT)) 1080 len = sizeof(FTSENT) + namelen + 1; 1081 else 1082 len = sizeof(struct ftsent_withstat) + namelen + 1; 1083 1084 if ((p = malloc(len)) == NULL) 1085 return (NULL); 1086 1087 if (ISSET(FTS_NOSTAT)) { 1088 p->fts_name = (char *)(p + 1); 1089 p->fts_statp = NULL; 1090 } else { 1091 p->fts_name = (char *)((struct ftsent_withstat *)p + 1); 1092 p->fts_statp = &((struct ftsent_withstat *)p)->statbuf; 1093 } 1094 1095 /* Copy the name and guarantee NUL termination. */ 1096 memcpy(p->fts_name, name, namelen); 1097 p->fts_name[namelen] = '\0'; 1098 p->fts_namelen = namelen; 1099 p->fts_path = sp->fts_path; 1100 p->fts_errno = 0; 1101 p->fts_flags = 0; 1102 p->fts_instr = FTS_NOINSTR; 1103 p->fts_number = 0; 1104 p->fts_pointer = NULL; 1105 p->fts_fts = sp; 1106 return (p); 1107 } 1108 1109 static void 1110 fts_lfree(FTSENT *head) 1111 { 1112 FTSENT *p; 1113 1114 /* Free a linked list of structures. */ 1115 while ((p = head)) { 1116 head = head->fts_link; 1117 free(p); 1118 } 1119 } 1120 1121 /* 1122 * Allow essentially unlimited paths; find, rm, ls should all work on any tree. 1123 * Most systems will allow creation of paths much longer than MAXPATHLEN, even 1124 * though the kernel won't resolve them. Add the size (not just what's needed) 1125 * plus 256 bytes so don't realloc the path 2 bytes at a time. 1126 */ 1127 static int 1128 fts_palloc(FTS *sp, size_t more) 1129 { 1130 char *old_path; 1131 sp->fts_pathlen += more + 256; 1132 1133 old_path = sp->fts_path; 1134 sp->fts_path = realloc(old_path, sp->fts_pathlen); 1135 if (sp->fts_path == NULL) 1136 free(old_path); 1137 1138 return (sp->fts_path == NULL); 1139 } 1140 1141 /* 1142 * When the path is realloc'd, have to fix all of the pointers in structures 1143 * already returned. 1144 */ 1145 static void 1146 fts_padjust(FTS *sp, FTSENT *head) 1147 { 1148 FTSENT *p; 1149 char *addr = sp->fts_path; 1150 1151 #define ADJUST(p) do { \ 1152 if ((p)->fts_accpath != (p)->fts_name) { \ 1153 (p)->fts_accpath = \ 1154 (char *)addr + ((p)->fts_accpath - (p)->fts_path); \ 1155 } \ 1156 (p)->fts_path = addr; \ 1157 } while (0) 1158 /* Adjust the current set of children. */ 1159 for (p = sp->fts_child; p; p = p->fts_link) 1160 ADJUST(p); 1161 1162 /* Adjust the rest of the tree, including the current level. */ 1163 for (p = head; p->fts_level >= FTS_ROOTLEVEL;) { 1164 ADJUST(p); 1165 p = p->fts_link ? p->fts_link : p->fts_parent; 1166 } 1167 } 1168 1169 static size_t 1170 fts_maxarglen(argv) 1171 char * const *argv; 1172 { 1173 size_t len, max; 1174 1175 for (max = 0; *argv; ++argv) 1176 if ((len = strlen(*argv)) > max) 1177 max = len; 1178 return (max + 1); 1179 } 1180 1181 /* 1182 * Change to dir specified by fd or p->fts_accpath without getting 1183 * tricked by someone changing the world out from underneath us. 1184 * Assumes p->fts_dev and p->fts_ino are filled in. 1185 */ 1186 static int 1187 fts_safe_changedir(FTS *sp, FTSENT *p, int fd, char *path) 1188 { 1189 int ret, oerrno, newfd; 1190 struct stat sb; 1191 1192 newfd = fd; 1193 if (ISSET(FTS_NOCHDIR)) 1194 return (0); 1195 if (fd < 0 && (newfd = open(path, O_RDONLY | O_CLOEXEC, 0)) < 0) 1196 return (-1); 1197 if (fstat(newfd, &sb)) { 1198 ret = -1; 1199 goto bail; 1200 } 1201 if (p->fts_dev != sb.st_dev || p->fts_ino != sb.st_ino) { 1202 errno = ENOENT; /* disinformation */ 1203 ret = -1; 1204 goto bail; 1205 } 1206 ret = fchdir(newfd); 1207 bail: 1208 oerrno = errno; 1209 if (fd < 0) 1210 (void)close(newfd); 1211 errno = oerrno; 1212 return (ret); 1213 } 1214 1215 /* 1216 * Check if the filesystem for "ent" has UFS-style links. 1217 */ 1218 static int 1219 fts_ufslinks(FTS *sp, const FTSENT *ent) 1220 { 1221 struct _fts_private *priv; 1222 #ifndef __HAIKU__ 1223 const char **cpp; 1224 #endif 1225 1226 priv = (struct _fts_private *)sp; 1227 /* 1228 * If this node's device is different from the previous, grab 1229 * the filesystem information, and decide on the reliability 1230 * of the link information from this filesystem for stat(2) 1231 * avoidance. 1232 */ 1233 if (priv->ftsp_dev != ent->fts_dev) { 1234 #ifndef __HAIKU__ 1235 if (statfs(ent->fts_path, &priv->ftsp_statfs) != -1) { 1236 priv->ftsp_dev = ent->fts_dev; 1237 priv->ftsp_linksreliable = 0; 1238 for (cpp = ufslike_filesystems; *cpp; cpp++) { 1239 if (strcmp(priv->ftsp_statfs.f_fstypename, 1240 *cpp) == 0) { 1241 priv->ftsp_linksreliable = 1; 1242 break; 1243 } 1244 } 1245 } else { 1246 priv->ftsp_linksreliable = 0; 1247 } 1248 #else 1249 priv->ftsp_linksreliable = 0; 1250 #endif 1251 } 1252 return (priv->ftsp_linksreliable); 1253 } 1254