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