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 * 3. 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 30 #include <sys/stat.h> 31 32 #include <dirent.h> 33 #include <errno.h> 34 #include <fcntl.h> 35 #include <fts.h> 36 #include <limits.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <unistd.h> 40 41 #define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b)) 42 43 #define ALIGNBYTES _POINTER_ALIGNMENT 44 #define ALIGN(p) (((unsigned long)(p) + ALIGNBYTES) & ~ALIGNBYTES) 45 46 static FTSENT *fts_alloc(FTS *, char *, size_t); 47 static FTSENT *fts_build(FTS *, int); 48 static void fts_lfree(FTSENT *); 49 static void fts_load(FTS *, FTSENT *); 50 static size_t fts_maxarglen(char * const *); 51 static void fts_padjust(FTS *, FTSENT *); 52 static int fts_palloc(FTS *, size_t); 53 static FTSENT *fts_sort(FTS *, FTSENT *, int); 54 static ushort_t fts_stat(FTS *, FTSENT *, int, int); 55 static int fts_safe_changedir(FTS *, FTSENT *, int, char *); 56 57 #define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2]))) 58 59 #define CLR(opt) (sp->fts_options &= ~(opt)) 60 #define ISSET(opt) (sp->fts_options & (opt)) 61 #define SET(opt) (sp->fts_options |= (opt)) 62 63 #define FCHDIR(sp, fd) (!ISSET(FTS_NOCHDIR) && fchdir(fd)) 64 65 /* fts_build flags */ 66 #define BCHILD 1 /* fts_children */ 67 #define BNAMES 2 /* fts_children, names only */ 68 #define BREAD 3 /* fts_read */ 69 70 FTS * 71 fts_open(char * const *argv, int options, 72 int (*compar)(const FTSENT **, const FTSENT **)) 73 { 74 FTS *sp; 75 FTSENT *p, *root; 76 int nitems; 77 FTSENT *parent, *prev; 78 79 /* Options check. */ 80 if (options & ~FTS_OPTIONMASK) { 81 errno = EINVAL; 82 return (NULL); 83 } 84 85 /* At least one path must be specified. */ 86 if (*argv == NULL) { 87 errno = EINVAL; 88 return (NULL); 89 } 90 91 /* Allocate/initialize the stream */ 92 if ((sp = calloc(1, sizeof (FTS))) == NULL) 93 return (NULL); 94 sp->fts_compar = compar; 95 sp->fts_options = options; 96 97 /* Logical walks turn on NOCHDIR; symbolic links are too hard. */ 98 if (ISSET(FTS_LOGICAL)) 99 SET(FTS_NOCHDIR); 100 101 /* 102 * Start out with 1K of path space, and enough, in any case, 103 * to hold the user's paths. 104 */ 105 if (fts_palloc(sp, MAXIMUM(fts_maxarglen(argv), PATH_MAX))) 106 goto mem1; 107 108 /* Allocate/initialize root's parent. */ 109 if ((parent = fts_alloc(sp, "", 0)) == NULL) 110 goto mem2; 111 parent->fts_level = FTS_ROOTPARENTLEVEL; 112 113 /* Allocate/initialize root(s). */ 114 for (root = prev = NULL, nitems = 0; *argv; ++argv, ++nitems) { 115 if ((p = fts_alloc(sp, *argv, strlen(*argv))) == NULL) 116 goto mem3; 117 p->fts_level = FTS_ROOTLEVEL; 118 p->fts_parent = parent; 119 p->fts_accpath = p->fts_name; 120 p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW), -1); 121 122 /* Command-line "." and ".." are real directories. */ 123 if (p->fts_info == FTS_DOT) 124 p->fts_info = FTS_D; 125 126 /* 127 * If comparison routine supplied, traverse in sorted 128 * order; otherwise traverse in the order specified. 129 */ 130 if (compar) { 131 p->fts_link = root; 132 root = p; 133 } else { 134 p->fts_link = NULL; 135 if (root == NULL) 136 root = p; 137 else 138 prev->fts_link = p; 139 prev = p; 140 } 141 } 142 if (compar && nitems > 1) 143 root = fts_sort(sp, root, nitems); 144 145 /* 146 * Allocate a dummy pointer and make fts_read think that we've just 147 * finished the node before the root(s); set p->fts_info to FTS_INIT 148 * so that everything about the "current" node is ignored. 149 */ 150 if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL) 151 goto mem3; 152 sp->fts_cur->fts_link = root; 153 sp->fts_cur->fts_info = FTS_INIT; 154 155 /* 156 * If using chdir(2), grab a file descriptor pointing to dot to ensure 157 * that we can get back here; this could be avoided for some paths, 158 * but almost certainly not worth the effort. Slashes, symbolic links, 159 * and ".." are all fairly nasty problems. Note, if we can't get the 160 * descriptor we run anyway, just more slowly. 161 */ 162 if (!ISSET(FTS_NOCHDIR) && 163 (sp->fts_rfd = open(".", O_RDONLY | O_CLOEXEC)) < 0) 164 SET(FTS_NOCHDIR); 165 166 if (nitems == 0) 167 free(parent); 168 169 return (sp); 170 171 mem3: fts_lfree(root); 172 free(parent); 173 mem2: free(sp->fts_path); 174 mem1: free(sp); 175 return (NULL); 176 } 177 178 static void 179 fts_load(FTS *sp, FTSENT *p) 180 { 181 size_t len; 182 char *cp; 183 184 /* 185 * Load the stream structure for the next traversal. Since we don't 186 * actually enter the directory until after the preorder visit, set 187 * the fts_accpath field specially so the chdir gets done to the right 188 * place and the user can access the first node. From fts_open it's 189 * known that the path will fit. 190 */ 191 len = p->fts_pathlen = p->fts_namelen; 192 (void) memmove(sp->fts_path, p->fts_name, len + 1); 193 if (((cp = strrchr(p->fts_name, '/')) != NULL) && 194 (cp != p->fts_name || cp[1])) { 195 len = strlen(++cp); 196 (void) memmove(p->fts_name, cp, len + 1); 197 p->fts_namelen = len; 198 } 199 p->fts_accpath = p->fts_path = sp->fts_path; 200 sp->fts_dev = p->fts_dev; 201 } 202 203 int 204 fts_close(FTS *sp) 205 { 206 FTSENT *freep, *p; 207 int rfd, error = 0; 208 209 /* 210 * This still works if we haven't read anything -- the dummy structure 211 * points to the root list, so we step through to the end of the root 212 * list which has a valid parent pointer. 213 */ 214 if (sp->fts_cur) { 215 for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL; ) { 216 freep = p; 217 p = p->fts_link ? p->fts_link : p->fts_parent; 218 free(freep); 219 } 220 free(p); 221 } 222 223 /* Stash the original directory fd if needed. */ 224 rfd = ISSET(FTS_NOCHDIR) ? -1 : sp->fts_rfd; 225 226 /* Free up child linked list, sort array, path buffer, stream ptr. */ 227 if (sp->fts_child) 228 fts_lfree(sp->fts_child); 229 free(sp->fts_array); 230 free(sp->fts_path); 231 free(sp); 232 233 /* Return to original directory, checking for error. */ 234 if (rfd != -1) { 235 int saved_errno; 236 error = fchdir(rfd); 237 saved_errno = errno; 238 (void) close(rfd); 239 errno = saved_errno; 240 } 241 242 return (error); 243 } 244 245 /* 246 * Special case of "/" at the end of the path so that slashes aren't 247 * appended which would cause paths to be written as "....//foo". 248 */ 249 #define NAPPEND(p) \ 250 (p->fts_path[p->fts_pathlen - 1] == '/' \ 251 ? p->fts_pathlen - 1 : p->fts_pathlen) 252 253 FTSENT * 254 fts_read(FTS *sp) 255 { 256 FTSENT *p, *tmp; 257 int instr; 258 char *t; 259 int saved_errno; 260 261 /* If finished or unrecoverable error, return NULL. */ 262 if (sp->fts_cur == NULL || ISSET(FTS_STOP)) 263 return (NULL); 264 265 /* Set current node pointer. */ 266 p = sp->fts_cur; 267 268 /* Save and zero out user instructions. */ 269 instr = p->fts_instr; 270 p->fts_instr = FTS_NOINSTR; 271 272 /* Any type of file may be re-visited; re-stat and re-turn. */ 273 if (instr == FTS_AGAIN) { 274 p->fts_info = fts_stat(sp, p, 0, -1); 275 return (p); 276 } 277 278 /* 279 * Following a symlink -- SLNONE test allows application to see 280 * SLNONE and recover. If indirecting through a symlink, have 281 * keep a pointer to current location. If unable to get that 282 * pointer, follow fails. 283 */ 284 if (instr == FTS_FOLLOW && 285 (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) { 286 p->fts_info = fts_stat(sp, p, 1, -1); 287 if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { 288 if ((p->fts_symfd = 289 open(".", O_RDONLY | O_CLOEXEC)) < 0) { 290 p->fts_errno = errno; 291 p->fts_info = FTS_ERR; 292 } else 293 p->fts_flags |= FTS_SYMFOLLOW; 294 } 295 return (p); 296 } 297 298 /* Directory in pre-order. */ 299 if (p->fts_info == FTS_D) { 300 /* If skipped or crossed mount point, do post-order visit. */ 301 if (instr == FTS_SKIP || 302 (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) { 303 if (p->fts_flags & FTS_SYMFOLLOW) 304 (void) close(p->fts_symfd); 305 if (sp->fts_child) { 306 fts_lfree(sp->fts_child); 307 sp->fts_child = NULL; 308 } 309 p->fts_info = FTS_DP; 310 return (p); 311 } 312 313 /* Rebuild if only read the names and now traversing. */ 314 if (sp->fts_child && ISSET(FTS_NAMEONLY)) { 315 CLR(FTS_NAMEONLY); 316 fts_lfree(sp->fts_child); 317 sp->fts_child = NULL; 318 } 319 320 /* 321 * Cd to the subdirectory. 322 * 323 * If have already read and now fail to chdir, whack the list 324 * to make the names come out right, and set the parent errno 325 * so the application will eventually get an error condition. 326 * Set the FTS_DONTCHDIR flag so that when we logically change 327 * directories back to the parent we don't do a chdir. 328 * 329 * If haven't read do so. If the read fails, fts_build sets 330 * FTS_STOP or the fts_info field of the node. 331 */ 332 if (sp->fts_child) { 333 if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) { 334 p->fts_errno = errno; 335 p->fts_flags |= FTS_DONTCHDIR; 336 for (p = sp->fts_child; p; p = p->fts_link) 337 p->fts_accpath = 338 p->fts_parent->fts_accpath; 339 } 340 } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) { 341 if (ISSET(FTS_STOP)) 342 return (NULL); 343 return (p); 344 } 345 p = sp->fts_child; 346 sp->fts_child = NULL; 347 goto name; 348 } 349 350 /* Move to the next node on this level. */ 351 next: tmp = p; 352 if ((p = p->fts_link) != NULL) { 353 free(tmp); 354 355 /* 356 * If reached the top, return to the original directory (or 357 * the root of the tree), and load the paths for the next root. 358 */ 359 if (p->fts_level == FTS_ROOTLEVEL) { 360 if (FCHDIR(sp, sp->fts_rfd)) { 361 SET(FTS_STOP); 362 return (NULL); 363 } 364 fts_load(sp, p); 365 return (sp->fts_cur = p); 366 } 367 368 /* 369 * User may have called fts_set on the node. If skipped, 370 * ignore. If followed, get a file descriptor so we can 371 * get back if necessary. 372 */ 373 if (p->fts_instr == FTS_SKIP) 374 goto next; 375 if (p->fts_instr == FTS_FOLLOW) { 376 p->fts_info = fts_stat(sp, p, 1, -1); 377 if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { 378 if ((p->fts_symfd = 379 open(".", O_RDONLY | O_CLOEXEC)) < 0) { 380 p->fts_errno = errno; 381 p->fts_info = FTS_ERR; 382 } else 383 p->fts_flags |= FTS_SYMFOLLOW; 384 } 385 p->fts_instr = FTS_NOINSTR; 386 } 387 388 name: t = sp->fts_path + NAPPEND(p->fts_parent); 389 *t++ = '/'; 390 (void) memmove(t, p->fts_name, p->fts_namelen + 1); 391 return (sp->fts_cur = p); 392 } 393 394 /* Move up to the parent node. */ 395 p = tmp->fts_parent; 396 free(tmp); 397 398 if (p->fts_level == FTS_ROOTPARENTLEVEL) { 399 /* 400 * Done; free everything up and set errno to 0 so the user 401 * can distinguish between error and EOF. 402 */ 403 free(p); 404 errno = 0; 405 return (sp->fts_cur = NULL); 406 } 407 408 /* NUL terminate the pathname. */ 409 sp->fts_path[p->fts_pathlen] = '\0'; 410 411 /* 412 * Return to the parent directory. If at a root node or came through 413 * a symlink, go back through the file descriptor. Otherwise, cd up 414 * one directory. 415 */ 416 if (p->fts_level == FTS_ROOTLEVEL) { 417 if (FCHDIR(sp, sp->fts_rfd)) { 418 SET(FTS_STOP); 419 sp->fts_cur = p; 420 return (NULL); 421 } 422 } else if (p->fts_flags & FTS_SYMFOLLOW) { 423 if (FCHDIR(sp, p->fts_symfd)) { 424 saved_errno = errno; 425 (void) close(p->fts_symfd); 426 errno = saved_errno; 427 SET(FTS_STOP); 428 sp->fts_cur = p; 429 return (NULL); 430 } 431 (void) close(p->fts_symfd); 432 } else if (!(p->fts_flags & FTS_DONTCHDIR) && 433 fts_safe_changedir(sp, p->fts_parent, -1, "..")) { 434 SET(FTS_STOP); 435 sp->fts_cur = p; 436 return (NULL); 437 } 438 p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP; 439 return (sp->fts_cur = p); 440 } 441 442 /* 443 * Fts_set takes the stream as an argument although it's not used in this 444 * implementation; it would be necessary if anyone wanted to add global 445 * semantics to fts using fts_set. An error return is allowed for similar 446 * reasons. 447 */ 448 /*ARGSUSED*/ 449 int 450 fts_set(FTS *sp, FTSENT *p, int instr) 451 { 452 if (instr && instr != FTS_AGAIN && instr != FTS_FOLLOW && 453 instr != FTS_NOINSTR && instr != FTS_SKIP) { 454 errno = EINVAL; 455 return (1); 456 } 457 p->fts_instr = instr; 458 return (0); 459 } 460 461 FTSENT * 462 fts_children(FTS *sp, int instr) 463 { 464 FTSENT *p; 465 int fd; 466 467 if (instr && instr != FTS_NAMEONLY) { 468 errno = EINVAL; 469 return (NULL); 470 } 471 472 /* Set current node pointer. */ 473 p = sp->fts_cur; 474 475 /* 476 * Errno set to 0 so user can distinguish empty directory from 477 * an error. 478 */ 479 errno = 0; 480 481 /* Fatal errors stop here. */ 482 if (ISSET(FTS_STOP)) 483 return (NULL); 484 485 /* Return logical hierarchy of user's arguments. */ 486 if (p->fts_info == FTS_INIT) 487 return (p->fts_link); 488 489 /* 490 * If not a directory being visited in pre-order, stop here. Could 491 * allow FTS_DNR, assuming the user has fixed the problem, but the 492 * same effect is available with FTS_AGAIN. 493 */ 494 if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */) 495 return (NULL); 496 497 /* Free up any previous child list. */ 498 if (sp->fts_child) 499 fts_lfree(sp->fts_child); 500 501 if (instr == FTS_NAMEONLY) { 502 SET(FTS_NAMEONLY); 503 instr = BNAMES; 504 } else 505 instr = BCHILD; 506 507 /* 508 * If using chdir on a relative path and called BEFORE fts_read does 509 * its chdir to the root of a traversal, we can lose -- we need to 510 * chdir into the subdirectory, and we don't know where the current 511 * directory is, so we can't get back so that the upcoming chdir by 512 * fts_read will work. 513 */ 514 if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' || 515 ISSET(FTS_NOCHDIR)) 516 return (sp->fts_child = fts_build(sp, instr)); 517 518 if ((fd = open(".", O_RDONLY | O_CLOEXEC)) < 0) 519 return (NULL); 520 sp->fts_child = fts_build(sp, instr); 521 if (fchdir(fd)) { 522 (void) close(fd); 523 return (NULL); 524 } 525 (void) close(fd); 526 return (sp->fts_child); 527 } 528 529 /* 530 * This is the tricky part -- do not casually change *anything* in here. The 531 * idea is to build the linked list of entries that are used by fts_children 532 * and fts_read. There are lots of special cases. 533 * 534 * The real slowdown in walking the tree is the stat calls. If FTS_NOSTAT is 535 * set and it's a physical walk (so that symbolic links can't be directories), 536 * we can do things quickly. First, if it's a 4.4BSD file system, the type 537 * of the file is in the directory entry. Otherwise, we assume that the number 538 * of subdirectories in a node is equal to the number of links to the parent. 539 * The former skips all stat calls. The latter skips stat calls in any leaf 540 * directories and for any files after the subdirectories in the directory have 541 * been found, cutting the stat calls by about 2/3. 542 */ 543 static FTSENT * 544 fts_build(FTS *sp, int type) 545 { 546 struct dirent *dp; 547 FTSENT *p, *head; 548 FTSENT *cur, *tail; 549 DIR *dirp; 550 void *oldaddr; 551 size_t len, maxlen; 552 int nitems, cderrno, descend, level, nlinks, doadjust; 553 int saved_errno; 554 char *cp = NULL; 555 556 /* Set current node pointer. */ 557 cur = sp->fts_cur; 558 559 /* 560 * Open the directory for reading. If this fails, we're done. 561 * If being called from fts_read, set the fts_info field. 562 */ 563 if ((dirp = opendir(cur->fts_accpath)) == NULL) { 564 if (type == BREAD) { 565 cur->fts_info = FTS_DNR; 566 cur->fts_errno = errno; 567 } 568 return (NULL); 569 } 570 571 /* 572 * Nlinks is the number of possible entries of type directory in the 573 * directory if we're cheating on stat calls, 0 if we're not doing 574 * any stat calls at all, -1 if we're doing stats on everything. 575 */ 576 if (type == BNAMES) 577 nlinks = 0; 578 else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) 579 nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2); 580 else 581 nlinks = -1; 582 583 /* 584 * If we're going to need to stat anything or we want to descend 585 * and stay in the directory, chdir. If this fails we keep going, 586 * but set a flag so we don't chdir after the post-order visit. 587 * We won't be able to stat anything, but we can still return the 588 * names themselves. Note, that since fts_read won't be able to 589 * chdir into the directory, it will have to return different path 590 * names than before, i.e. "a/b" instead of "b". Since the node 591 * has already been visited in pre-order, have to wait until the 592 * post-order visit to return the error. There is a special case 593 * here, if there was nothing to stat then it's not an error to 594 * not be able to stat. This is all fairly nasty. If a program 595 * needed sorted entries or stat information, they had better be 596 * checking FTS_NS on the returned nodes. 597 */ 598 cderrno = 0; 599 if (nlinks || type == BREAD) { 600 if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) { 601 if (nlinks && type == BREAD) 602 cur->fts_errno = errno; 603 cur->fts_flags |= FTS_DONTCHDIR; 604 descend = 0; 605 cderrno = errno; 606 (void) closedir(dirp); 607 dirp = NULL; 608 } else 609 descend = 1; 610 } else 611 descend = 0; 612 613 /* 614 * Figure out the max file name length that can be stored in the 615 * current path -- the inner loop allocates more path as necessary. 616 * We really wouldn't have to do the maxlen calculations here, we 617 * could do them in fts_read before returning the path, but it's a 618 * lot easier here since the length is part of the dirent structure. 619 * 620 * If not changing directories set a pointer so that can just append 621 * each new name into the path. 622 */ 623 len = NAPPEND(cur); 624 if (ISSET(FTS_NOCHDIR)) { 625 cp = sp->fts_path + len; 626 *cp++ = '/'; 627 } 628 len++; 629 maxlen = sp->fts_pathlen - len; 630 631 /* 632 * fts_level is signed so we must prevent it from wrapping 633 * around to FTS_ROOTLEVEL and FTS_ROOTPARENTLEVEL. 634 */ 635 level = cur->fts_level; 636 if (level < FTS_MAXLEVEL) 637 level++; 638 639 /* Read the directory, attaching each entry to the `link' pointer. */ 640 doadjust = 0; 641 for (head = tail = NULL, nitems = 0; dirp && (dp = readdir(dirp)); ) { 642 if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name)) 643 continue; 644 645 if (!(p = fts_alloc(sp, dp->d_name, strlen(dp->d_name)))) 646 goto mem1; 647 if (strlen(dp->d_name) >= maxlen) { /* include space for NUL */ 648 oldaddr = sp->fts_path; 649 if (fts_palloc(sp, strlen(dp->d_name) +len + 1)) { 650 /* 651 * No more memory for path or structures. Save 652 * errno, free up the current structure and the 653 * structures already allocated. 654 */ 655 mem1: saved_errno = errno; 656 free(p); 657 fts_lfree(head); 658 (void) closedir(dirp); 659 cur->fts_info = FTS_ERR; 660 SET(FTS_STOP); 661 errno = saved_errno; 662 return (NULL); 663 } 664 /* Did realloc() change the pointer? */ 665 if (oldaddr != sp->fts_path) { 666 doadjust = 1; 667 if (ISSET(FTS_NOCHDIR)) 668 cp = sp->fts_path + len; 669 } 670 maxlen = sp->fts_pathlen - len; 671 } 672 673 p->fts_level = level; 674 p->fts_parent = sp->fts_cur; 675 p->fts_pathlen = len + strlen(dp->d_name); 676 if (p->fts_pathlen < len) { 677 /* 678 * If we wrap, free up the current structure and 679 * the structures already allocated, then error 680 * out with ENAMETOOLONG. 681 */ 682 free(p); 683 fts_lfree(head); 684 (void) closedir(dirp); 685 cur->fts_info = FTS_ERR; 686 SET(FTS_STOP); 687 errno = ENAMETOOLONG; 688 return (NULL); 689 } 690 691 if (cderrno) { 692 if (nlinks) { 693 p->fts_info = FTS_NS; 694 p->fts_errno = cderrno; 695 } else 696 p->fts_info = FTS_NSOK; 697 p->fts_accpath = cur->fts_accpath; 698 } else if (nlinks == 0) { 699 p->fts_accpath = 700 ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name; 701 p->fts_info = FTS_NSOK; 702 } else { 703 /* Build a file name for fts_stat to stat. */ 704 if (ISSET(FTS_NOCHDIR)) { 705 p->fts_accpath = p->fts_path; 706 (void) memmove(cp, p->fts_name, 707 p->fts_namelen + 1); 708 p->fts_info = fts_stat(sp, p, 0, dirfd(dirp)); 709 } else { 710 p->fts_accpath = p->fts_name; 711 p->fts_info = fts_stat(sp, p, 0, -1); 712 } 713 714 /* Decrement link count if applicable. */ 715 if (nlinks > 0 && (p->fts_info == FTS_D || 716 p->fts_info == FTS_DC || p->fts_info == FTS_DOT)) 717 --nlinks; 718 } 719 720 /* We walk in directory order so "ls -f" doesn't get upset. */ 721 p->fts_link = NULL; 722 if (head == NULL) 723 head = tail = p; 724 else { 725 tail->fts_link = p; 726 tail = p; 727 } 728 ++nitems; 729 } 730 if (dirp) 731 (void) closedir(dirp); 732 733 /* 734 * If realloc() changed the address of the path, adjust the 735 * addresses for the rest of the tree and the dir list. 736 */ 737 if (doadjust) 738 fts_padjust(sp, head); 739 740 /* 741 * If not changing directories, reset the path back to original 742 * state. 743 */ 744 if (ISSET(FTS_NOCHDIR)) { 745 if (len == sp->fts_pathlen || nitems == 0) 746 --cp; 747 *cp = '\0'; 748 } 749 750 /* 751 * If descended after called from fts_children or after called from 752 * fts_read and nothing found, get back. At the root level we use 753 * the saved fd; if one of fts_open()'s arguments is a relative path 754 * to an empty directory, we wind up here with no other way back. If 755 * can't get back, we're done. 756 */ 757 if (descend && (type == BCHILD || !nitems) && 758 (cur->fts_level == FTS_ROOTLEVEL ? FCHDIR(sp, sp->fts_rfd) : 759 fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) { 760 cur->fts_info = FTS_ERR; 761 SET(FTS_STOP); 762 return (NULL); 763 } 764 765 /* If didn't find anything, return NULL. */ 766 if (!nitems) { 767 if (type == BREAD) 768 cur->fts_info = FTS_DP; 769 return (NULL); 770 } 771 772 /* Sort the entries. */ 773 if (sp->fts_compar && nitems > 1) 774 head = fts_sort(sp, head, nitems); 775 return (head); 776 } 777 778 static ushort_t 779 fts_stat(FTS *sp, FTSENT *p, int follow, int dfd) 780 { 781 FTSENT *t; 782 dev_t dev; 783 ino_t ino; 784 struct stat *sbp, sb; 785 int saved_errno; 786 const char *path; 787 788 if (dfd == -1) { 789 path = p->fts_accpath; 790 dfd = AT_FDCWD; 791 } else 792 path = p->fts_name; 793 794 /* If user needs stat info, stat buffer already allocated. */ 795 sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp; 796 797 /* 798 * If doing a logical walk, or application requested FTS_FOLLOW, do 799 * a stat(2). If that fails, check for a non-existent symlink. If 800 * fail, set the errno from the stat call. 801 */ 802 if (ISSET(FTS_LOGICAL) || follow) { 803 if (fstatat(dfd, path, sbp, 0)) { 804 saved_errno = errno; 805 if (!fstatat(dfd, path, sbp, AT_SYMLINK_NOFOLLOW)) { 806 errno = 0; 807 return (FTS_SLNONE); 808 } 809 p->fts_errno = saved_errno; 810 goto err; 811 } 812 } else if (fstatat(dfd, path, sbp, AT_SYMLINK_NOFOLLOW)) { 813 p->fts_errno = errno; 814 err: (void) memset(sbp, 0, sizeof (struct stat)); 815 return (FTS_NS); 816 } 817 818 if (S_ISDIR(sbp->st_mode)) { 819 /* 820 * Set the device/inode. Used to find cycles and check for 821 * crossing mount points. Also remember the link count, used 822 * in fts_build to limit the number of stat calls. It is 823 * understood that these fields are only referenced if fts_info 824 * is set to FTS_D. 825 */ 826 dev = p->fts_dev = sbp->st_dev; 827 ino = p->fts_ino = sbp->st_ino; 828 p->fts_nlink = sbp->st_nlink; 829 830 if (ISDOT(p->fts_name)) 831 return (FTS_DOT); 832 833 /* 834 * Cycle detection is done by brute force when the directory 835 * is first encountered. If the tree gets deep enough or the 836 * number of symbolic links to directories is high enough, 837 * something faster might be worthwhile. 838 */ 839 for (t = p->fts_parent; 840 t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent) 841 if (ino == t->fts_ino && dev == t->fts_dev) { 842 p->fts_cycle = t; 843 return (FTS_DC); 844 } 845 return (FTS_D); 846 } 847 if (S_ISLNK(sbp->st_mode)) 848 return (FTS_SL); 849 if (S_ISREG(sbp->st_mode)) 850 return (FTS_F); 851 return (FTS_DEFAULT); 852 } 853 854 static FTSENT * 855 fts_sort(FTS *sp, FTSENT *head, int nitems) 856 { 857 FTSENT **ap, *p; 858 859 /* 860 * Construct an array of pointers to the structures and call qsort(3). 861 * Reassemble the array in the order returned by qsort. If unable to 862 * sort for memory reasons, return the directory entries in their 863 * current order. Allocate enough space for the current needs plus 864 * 40 so don't realloc one entry at a time. 865 */ 866 if (nitems > sp->fts_nitems) { 867 struct _ftsent **a; 868 869 sp->fts_nitems = nitems + 40; 870 if ((a = reallocarray(sp->fts_array, 871 sp->fts_nitems, sizeof (FTSENT *))) == NULL) { 872 free(sp->fts_array); 873 sp->fts_array = NULL; 874 sp->fts_nitems = 0; 875 return (head); 876 } 877 sp->fts_array = a; 878 } 879 for (ap = sp->fts_array, p = head; p; p = p->fts_link) 880 *ap++ = p; 881 qsort(sp->fts_array, nitems, sizeof (FTSENT *), sp->fts_compar); 882 for (head = *(ap = sp->fts_array); --nitems; ++ap) 883 ap[0]->fts_link = ap[1]; 884 ap[0]->fts_link = NULL; 885 return (head); 886 } 887 888 static FTSENT * 889 fts_alloc(FTS *sp, char *name, size_t namelen) 890 { 891 FTSENT *p; 892 size_t len; 893 894 /* 895 * The file name is a variable length array and no stat structure is 896 * necessary if the user has set the nostat bit. Allocate the FTSENT 897 * structure, the file name and the stat structure in one chunk, but 898 * be careful that the stat structure is reasonably aligned. Since the 899 * fts_name field is declared to be of size 1, the fts_name pointer is 900 * namelen + 2 before the first possible address of the stat structure. 901 */ 902 len = sizeof (FTSENT) + namelen; 903 if (!ISSET(FTS_NOSTAT)) 904 len += sizeof (struct stat) + ALIGNBYTES; 905 if ((p = calloc(1, len)) == NULL) 906 return (NULL); 907 908 p->fts_path = sp->fts_path; 909 p->fts_namelen = namelen; 910 p->fts_instr = FTS_NOINSTR; 911 if (!ISSET(FTS_NOSTAT)) 912 p->fts_statp = (struct stat *)ALIGN(p->fts_name + namelen + 2); 913 (void) memcpy(p->fts_name, name, namelen); 914 915 return (p); 916 } 917 918 static void 919 fts_lfree(FTSENT *head) 920 { 921 FTSENT *p; 922 923 /* Free a linked list of structures. */ 924 while ((p = head) != NULL) { 925 head = head->fts_link; 926 free(p); 927 } 928 } 929 930 /* 931 * Allow essentially unlimited paths; find, rm, ls should all work on any tree. 932 * Most systems will allow creation of paths much longer than PATH_MAX, even 933 * though the kernel won't resolve them. Add the size (not just what's needed) 934 * plus 256 bytes so don't realloc the path 2 bytes at a time. 935 */ 936 static int 937 fts_palloc(FTS *sp, size_t more) 938 { 939 char *p; 940 941 /* 942 * Check for possible wraparound. 943 */ 944 more += 256; 945 if (sp->fts_pathlen + more < sp->fts_pathlen) { 946 free(sp->fts_path); 947 sp->fts_path = NULL; 948 errno = ENAMETOOLONG; 949 return (1); 950 } 951 sp->fts_pathlen += more; 952 p = realloc(sp->fts_path, sp->fts_pathlen); 953 if (p == NULL) { 954 free(sp->fts_path); 955 sp->fts_path = NULL; 956 return (1); 957 } 958 sp->fts_path = p; 959 return (0); 960 } 961 962 /* 963 * When the path is realloc'd, have to fix all of the pointers in structures 964 * already returned. 965 */ 966 static void 967 fts_padjust(FTS *sp, FTSENT *head) 968 { 969 FTSENT *p; 970 char *addr = sp->fts_path; 971 972 #define ADJUST(p) { \ 973 if ((p)->fts_accpath != (p)->fts_name) { \ 974 (p)->fts_accpath = \ 975 (char *)addr + ((p)->fts_accpath - (p)->fts_path); \ 976 } \ 977 (p)->fts_path = addr; \ 978 } 979 /* Adjust the current set of children. */ 980 for (p = sp->fts_child; p; p = p->fts_link) 981 ADJUST(p); 982 983 /* Adjust the rest of the tree, including the current level. */ 984 for (p = head; p->fts_level >= FTS_ROOTLEVEL; ) { 985 ADJUST(p); 986 p = p->fts_link ? p->fts_link : p->fts_parent; 987 } 988 } 989 990 static size_t 991 fts_maxarglen(char * const *argv) 992 { 993 size_t len, max; 994 995 for (max = 0; *argv; ++argv) 996 if ((len = strlen(*argv)) > max) 997 max = len; 998 return (max + 1); 999 } 1000 1001 /* 1002 * Change to dir specified by fd or p->fts_accpath without getting 1003 * tricked by someone changing the world out from underneath us. 1004 * Assumes p->fts_dev and p->fts_ino are filled in. 1005 */ 1006 static int 1007 fts_safe_changedir(FTS *sp, FTSENT *p, int fd, char *path) 1008 { 1009 int ret, oerrno, newfd; 1010 struct stat sb; 1011 1012 newfd = fd; 1013 if (ISSET(FTS_NOCHDIR)) 1014 return (0); 1015 /* 1016 * This originally specified O_DIRECTORY as well - restore once/if we 1017 * implement the flag. 1018 */ 1019 if (fd < 0 && (newfd = open(path, O_RDONLY|O_CLOEXEC)) < 0) 1020 return (-1); 1021 if (fstat(newfd, &sb)) { 1022 ret = -1; 1023 goto bail; 1024 } 1025 if (p->fts_dev != sb.st_dev || p->fts_ino != sb.st_ino) { 1026 errno = ENOENT; /* disinformation */ 1027 ret = -1; 1028 goto bail; 1029 } 1030 ret = fchdir(newfd); 1031 bail: 1032 oerrno = errno; 1033 if (fd < 0) 1034 (void) close(newfd); 1035 errno = oerrno; 1036 return (ret); 1037 } 1038