1 /*- 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #if defined(LIBC_SCCS) && !defined(lint) 9 static char sccsid[] = "@(#)fts.c 5.15 (Berkeley) 03/11/91"; 10 #endif /* LIBC_SCCS and not lint */ 11 12 #include <sys/cdefs.h> 13 #include <sys/param.h> 14 #include <sys/stat.h> 15 #include <fcntl.h> 16 #include <dirent.h> 17 #include <errno.h> 18 #include "fts.h" 19 #include <stdlib.h> 20 #include <string.h> 21 #include <unistd.h> 22 23 static FTSENT *fts_alloc(), *fts_build(), *fts_sort(); 24 static void fts_lfree(); 25 static int fts_load(); 26 static u_short fts_stat(); 27 static char *fts_path(); 28 29 #define ISSET(opt) (sp->fts_options & opt) 30 #define SET(opt) (sp->fts_options |= opt) 31 32 #define CHDIR(sp, path) (!ISSET(FTS_NOCHDIR) && chdir(path)) 33 #define FCHDIR(sp, fd) (!ISSET(FTS_NOCHDIR) && fchdir(fd)) 34 35 /* fts_build flags */ 36 #define BCHILD 1 /* from fts_children */ 37 #define BREAD 2 /* from fts_read */ 38 39 FTS * 40 fts_open(argv, options, compar) 41 char * const *argv; 42 register int options; 43 int (*compar)(); 44 { 45 register FTS *sp; 46 register FTSENT *p, *root; 47 register int nitems, maxlen; 48 FTSENT *parent, *tmp; 49 int len; 50 51 /* Allocate/initialize the stream */ 52 if (!(sp = (FTS *)malloc((u_int)sizeof(FTS)))) 53 return(NULL); 54 bzero(sp, sizeof(FTS)); 55 sp->fts_compar = compar; 56 sp->fts_options = options; 57 58 /* Logical walks turn on NOCHDIR; symbolic links are too hard. */ 59 if (ISSET(FTS_LOGICAL)) 60 SET(FTS_NOCHDIR); 61 62 /* Allocate/initialize root's parent. */ 63 if (!(parent = fts_alloc(sp, "", 0))) 64 goto mem1; 65 parent->fts_level = FTS_ROOTPARENTLEVEL; 66 67 /* Allocate/initialize root(s). */ 68 maxlen = -1; 69 for (root = NULL, nitems = 0; *argv; ++argv, ++nitems) { 70 if (!(len = strlen(*argv))) { 71 errno = ENOENT; 72 goto mem2; 73 } 74 if (maxlen < len) 75 maxlen = len; 76 p = fts_alloc(sp, *argv, len); 77 /* 78 * If comparison routine supplied, traverse in sorted 79 * order; otherwise traverse in the order specified. 80 */ 81 if (compar) { 82 p->fts_link = root; 83 root = p; 84 p->fts_accpath = p->fts_name; 85 if (!(options & FTS_NOSTAT)) 86 p->fts_info = fts_stat(sp, p, 0); 87 } else { 88 p->fts_link = NULL; 89 if (!root) 90 tmp = root = p; 91 else { 92 tmp->fts_link = p; 93 tmp = p; 94 } 95 } 96 p->fts_level = FTS_ROOTLEVEL; 97 p->fts_parent = parent; 98 } 99 if (compar && nitems > 1) 100 root = fts_sort(sp, root, nitems); 101 102 /* 103 * Allocate a dummy pointer and make fts_read think that we've just 104 * finished the node before the root(s); set p->fts_info to FTS_NS 105 * so that everything about the "current" node is ignored. 106 */ 107 if (!(sp->fts_cur = fts_alloc(sp, "", 0))) 108 goto mem2; 109 sp->fts_cur->fts_link = root; 110 sp->fts_cur->fts_info = FTS_NS; 111 112 /* Start out with at least 1K+ of path space. */ 113 if (!fts_path(sp, MAX(maxlen, MAXPATHLEN))) 114 goto mem3; 115 116 /* 117 * If using chdir(2), grab a file descriptor pointing to dot to insure 118 * that we can get back here; this could be avoided for some paths, 119 * but almost certainly not worth the effort. Slashes, symbolic links, 120 * and ".." are all fairly nasty problems. Note, if we can't get the 121 * descriptor we run anyway, just more slowly. 122 */ 123 if (!ISSET(FTS_NOCHDIR) && (sp->fts_rfd = open(".", O_RDONLY, 0)) < 0) 124 SET(FTS_NOCHDIR); 125 126 return(sp); 127 128 mem3: free(sp->fts_cur); 129 mem2: fts_lfree(root); 130 free(parent); 131 mem1: free(sp); 132 return(NULL); 133 } 134 135 static 136 fts_load(sp, p) 137 FTS *sp; 138 register FTSENT *p; 139 { 140 static int need_to_cd; 141 register int len; 142 register char *cp; 143 144 /* 145 * If changing the root level node, load the stream structure for the 146 * next traversal; set the fts_accpath field specially so the chdir 147 * gets done to the right place and the user can access the first node. 148 */ 149 len = p->fts_pathlen = p->fts_namelen; 150 bcopy(p->fts_name, sp->fts_path, len + 1); 151 if ((cp = rindex(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) { 152 len = strlen(++cp); 153 bcopy(cp, p->fts_name, len + 1); 154 p->fts_namelen = len; 155 } 156 p->fts_accpath = p->fts_path = sp->fts_path; 157 158 sp->rdev = p->fts_statb.st_dev; 159 160 /* 161 * If not the first time, and it's not an absolute pathname, get back 162 * to starting directory. If that fails, we're dead. 163 */ 164 if (need_to_cd && p->fts_path[0] != '/' && FCHDIR(sp, sp->fts_rfd)) 165 return(0); 166 need_to_cd = 1; 167 168 p->fts_info = fts_stat(sp, p, 0); 169 return(1); 170 } 171 172 fts_close(sp) 173 FTS *sp; 174 { 175 register FTSENT *freep, *p; 176 int saved_errno; 177 178 if (sp->fts_cur) { 179 /* 180 * This still works if we haven't read anything -- the dummy 181 * structure points to the root list, so we step through to 182 * the end of the root list which has a valid parent pointer. 183 */ 184 for (p = sp->fts_cur; p->fts_level > FTS_ROOTPARENTLEVEL;) { 185 freep = p; 186 p = p->fts_link ? p->fts_link : p->fts_parent; 187 free(freep); 188 } 189 free(p); 190 } 191 192 /* Free up child linked list, sort array, path buffer. */ 193 if (sp->fts_child) 194 fts_lfree(sp->fts_child); 195 if (sp->fts_array) 196 free(sp->fts_array); 197 free(sp->fts_path); 198 199 /* Return to original directory, save errno if necessary. */ 200 if (!ISSET(FTS_NOCHDIR)) { 201 saved_errno = fchdir(sp->fts_rfd) ? errno : 0; 202 (void)close(sp->fts_rfd); 203 } 204 205 /* Free up the stream pointer. */ 206 free(sp); 207 208 /* Set errno and return. */ 209 if (!ISSET(FTS_NOCHDIR) && saved_errno) { 210 errno = saved_errno; 211 return(-1); 212 } 213 return(0); 214 } 215 216 /* 217 * Special case a root of "/" so that slashes aren't appended causing 218 * paths to be written as "//foo". 219 */ 220 #define NAPPEND(p) \ 221 (p->fts_level == FTS_ROOTLEVEL && p->fts_pathlen == 1 && \ 222 p->fts_path[0] == '/' ? 0 : p->fts_pathlen) 223 224 FTSENT * 225 fts_read(sp) 226 register FTS *sp; 227 { 228 register FTSENT *p, *tmp; 229 register int instr; 230 register char *t; 231 232 /* If finished or unrecoverable error, return NULL. */ 233 if (!sp->fts_cur || ISSET(FTS_STOP)) 234 return(NULL); 235 236 /* Set current node pointer. */ 237 p = sp->fts_cur; 238 239 /* Save and zero out user instructions. */ 240 instr = p->fts_instr; 241 p->fts_instr = FTS_NOINSTR; 242 243 /* If used fts_link pointer for cycle detection, restore it. */ 244 if (sp->fts_savelink) { 245 p->fts_link = sp->fts_savelink; 246 sp->fts_savelink = NULL; 247 } 248 249 /* Any type of file may be re-visited; re-stat and re-turn. */ 250 if (instr == FTS_AGAIN) { 251 p->fts_info = fts_stat(sp, p, 0); 252 return(p); 253 } 254 255 /* 256 * Following a symlink -- SLNONE test allows application to see 257 * SLNONE and recover. 258 */ 259 if (instr == FTS_FOLLOW && 260 (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) { 261 p->fts_info = fts_stat(sp, p, 1); 262 return(p); 263 } 264 265 /* Directory in pre-order. */ 266 if (p->fts_info == FTS_D) { 267 /* If skipped or crossed mount point, do post-order visit. */ 268 if (instr == FTS_SKIP || 269 ISSET(FTS_XDEV) && p->fts_statb.st_dev != sp->rdev) { 270 if (sp->fts_child) { 271 fts_lfree(sp->fts_child); 272 sp->fts_child = NULL; 273 } 274 p->fts_info = FTS_DP; 275 return(p); 276 } 277 278 /* 279 * Cd to the subdirectory, reading it if haven't already. If 280 * the read fails for any reason, or the directory is empty, 281 * the fts_info field of the current node is set by fts_build. 282 * If have already read and fail to chdir, do some quick 283 * whacking to make the names come out right, and set the 284 * parent state so the application will eventually get an 285 * error condition. 286 */ 287 if (sp->fts_child) { 288 if (CHDIR(sp, p->fts_accpath)) { 289 p->fts_parent->fts_cderr = errno; 290 for (p = sp->fts_child; p; p = p->fts_link) 291 p->fts_accpath = 292 p->fts_parent->fts_accpath; 293 } 294 } else if (!(sp->fts_child = fts_build(sp, BREAD))) 295 return(ISSET(FTS_STOP) ? NULL : p); 296 p = sp->fts_child; 297 sp->fts_child = NULL; 298 goto name; 299 } 300 301 /* Move to next node on this level. */ 302 next: tmp = p; 303 if (p = p->fts_link) { 304 free(tmp); 305 306 /* If reached the top, load the paths for the next root. */ 307 if (p->fts_level == FTS_ROOTLEVEL) { 308 if (!fts_load(sp, p)) { 309 SET(FTS_STOP); 310 return(NULL); 311 } 312 return(sp->fts_cur = p); 313 } 314 315 /* User may have called fts_set on the node. */ 316 if (p->fts_instr == FTS_SKIP) 317 goto next; 318 if (p->fts_instr == FTS_FOLLOW) { 319 p->fts_info = fts_stat(sp, p, 1); 320 p->fts_instr = FTS_NOINSTR; 321 } 322 323 name: t = sp->fts_path + NAPPEND(p->fts_parent); 324 *t++ = '/'; 325 bcopy(p->fts_name, t, p->fts_namelen + 1); 326 return(sp->fts_cur = p); 327 } 328 329 /* Move to parent. */ 330 p = tmp->fts_parent; 331 free(tmp); 332 333 if (p->fts_level == FTS_ROOTPARENTLEVEL) { 334 /* 335 * Done; free everything up and set errno to 0 so the user 336 * can distinguish between error and EOF. 337 */ 338 free(p); 339 errno = 0; 340 return(sp->fts_cur = NULL); 341 } 342 343 sp->fts_path[p->fts_pathlen] = '\0'; 344 345 /* 346 * If had a chdir error, set the info field to reflect this, and 347 * restore errno. The error indicator has to be reset to 0 so that 348 * if the user does an FTS_AGAIN, it all works. Can't cd up on 349 * the post-order visit to the root node, otherwise will be in the 350 * wrong directory. 351 */ 352 if (p->fts_cderr) { 353 errno = p->fts_cderr; 354 p->fts_cderr = 0; 355 p->fts_info = FTS_ERR; 356 } else { 357 if (p->fts_level != FTS_ROOTLEVEL && CHDIR(sp, "..")) { 358 SET(FTS_STOP); 359 return(NULL); 360 } 361 p->fts_info = FTS_DP; 362 } 363 return(sp->fts_cur = p); 364 } 365 366 /* 367 * fts_set takes the stream as an argument although it's not used in this 368 * implementation; it would be necessary if anyone wanted to add global 369 * semantics to fts using fts_set. An error return is allowed for similar 370 * reasons. 371 */ 372 /* ARGSUSED */ 373 fts_set(sp, p, instr) 374 FTS *sp; 375 FTSENT *p; 376 int instr; 377 { 378 p->fts_instr = instr; 379 return(0); 380 } 381 382 FTSENT * 383 fts_children(sp) 384 register FTS *sp; 385 { 386 register FTSENT *p; 387 int fd; 388 389 /* Set current node pointer. */ 390 p = sp->fts_cur; 391 392 /* 393 * Set errno to 0 so that user can tell the difference between an 394 * error and a directory without entries. If not a directory being 395 * visited in *pre-order*, or we've already had fatal errors, return 396 * immediately. 397 */ 398 errno = 0; 399 if (ISSET(FTS_STOP) || p->fts_info != FTS_D && p->fts_info != FTS_DNR) 400 return(NULL); 401 402 /* Free up any previous child list. */ 403 if (sp->fts_child) 404 fts_lfree(sp->fts_child); 405 406 /* 407 * If using chdir on a relative path and called BEFORE fts_read does 408 * its chdir to the root of a traversal, we can lose -- we need to 409 * chdir into the subdirectory, and we don't know where the current 410 * directory is, so we can't get back so that the upcoming chdir by 411 * fts_read will work. 412 */ 413 if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' || 414 ISSET(FTS_NOCHDIR)) 415 return(sp->fts_child = fts_build(sp, BCHILD)); 416 417 if ((fd = open(".", O_RDONLY, 0)) < 0) 418 return(NULL); 419 sp->fts_child = fts_build(sp, BCHILD); 420 if (fchdir(fd)) 421 return(NULL); 422 (void)close(fd); 423 return(sp->fts_child); 424 } 425 426 /* 427 * This is the tricky part -- do not casually change *anything* in here. The 428 * idea is to build the linked list of entries that are used by fts_children 429 * and fts_read. There are lots of special cases. 430 * 431 * The real slowdown in walking the tree is the stat calls. If FTS_NOSTAT is 432 * set and it's a physical walk (so that symbolic links can't be directories), 433 * we assume that the number of subdirectories in a node is equal to the number 434 * of links to the parent. This allows stat calls to be skipped in any leaf 435 * directories and for any nodes after the directories in the parent node have 436 * been found. This empirically cuts the stat calls by about 2/3. 437 */ 438 #define ISDOT(a) (a[0] == '.' && (!a[1] || a[1] == '.' && !a[2])) 439 440 static FTSENT * 441 fts_build(sp, type) 442 register FTS *sp; 443 int type; 444 { 445 register struct dirent *dp; 446 register FTSENT *p, *head; 447 register int nitems; 448 FTSENT *cur; 449 DIR *dirp; 450 int cderr, descend, len, level, maxlen, nlinks, saved_errno; 451 char *cp; 452 453 /* Set current node pointer. */ 454 cur = sp->fts_cur; 455 456 /* 457 * Open the directory for reading. If this fails, we're done. 458 * If being called from fts_read, set the fts_info field. 459 */ 460 if (!(dirp = opendir(cur->fts_accpath))) { 461 if (type == BREAD) 462 cur->fts_info = FTS_DNR; 463 return(NULL); 464 } 465 466 /* 467 * Nlinks is the number of possible entries of type directory in the 468 * directory if we're cheating on stat calls, 0 if we're not doing 469 * any stat calls at all, -1 if we're doing stats on everything. 470 */ 471 nlinks = 472 ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL) ? 473 cur->fts_statb.st_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2) : -1; 474 475 /* 476 * If we're going to need to stat anything or we want to descend 477 * and stay in the directory, chdir. If this fails we keep going. 478 * We won't be able to stat anything, but we can still return the 479 * names themselves. Note, that since fts_read won't be able to 480 * chdir into the directory, it will have to return different path 481 * names than before, i.e. "a/b" instead of "b". Since the node 482 * has already been visited in pre-order, have to wait until the 483 * post-order visit to return the error. This is all fairly nasty. 484 * If a program needed sorted entries or stat information, they had 485 * better be checking FTS_NS on the returned nodes. 486 */ 487 if (nlinks || type == BREAD) 488 if (FCHDIR(sp, dirfd(dirp))) { 489 if (type == BREAD) 490 cur->fts_cderr = errno; 491 descend = nlinks = 0; 492 cderr = 1; 493 } else { 494 descend = 1; 495 cderr = 0; 496 } 497 else 498 descend = 0; 499 500 /* 501 * Figure out the max file name length that can be stored in the 502 * current path -- the inner loop allocates more path as necessary. 503 * We really wouldn't have to do the maxlen calculations here, we 504 * could do them in fts_read before returning the path, but it's a 505 * lot easier here since the length is part of the dirent structure. 506 * 507 * If not changing directories set a pointer so that we can just 508 * append each new name into the path. 509 */ 510 maxlen = sp->fts_pathlen - cur->fts_pathlen - 1; 511 len = NAPPEND(cur); 512 if (ISSET(FTS_NOCHDIR)) { 513 cp = sp->fts_path + len; 514 *cp++ = '/'; 515 } 516 517 level = cur->fts_level + 1; 518 519 /* Read the directory, attaching each entry to the `link' pointer. */ 520 for (head = NULL, nitems = 0; dp = readdir(dirp);) { 521 if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name)) 522 continue; 523 524 if (!(p = fts_alloc(sp, dp->d_name, (int)dp->d_namlen))) 525 goto mem1; 526 if (dp->d_namlen > maxlen) { 527 if (!fts_path(sp, (int)dp->d_namlen)) { 528 /* 529 * No more memory for path or structures. Save 530 * errno, free up the current structure and the 531 * structures already allocated. 532 */ 533 mem1: saved_errno = errno; 534 if (p) 535 free(p); 536 fts_lfree(head); 537 (void)closedir(dirp); 538 errno = saved_errno; 539 cur->fts_info = FTS_ERR; 540 SET(FTS_STOP); 541 return(NULL); 542 } 543 maxlen = sp->fts_pathlen - sp->fts_cur->fts_pathlen - 1; 544 } 545 546 p->fts_pathlen = len + dp->d_namlen + 1; 547 p->fts_parent = sp->fts_cur; 548 p->fts_level = level; 549 550 if (nlinks) { 551 /* Build a file name for fts_stat to stat. */ 552 if (ISSET(FTS_NOCHDIR)) { 553 p->fts_accpath = p->fts_path; 554 bcopy(p->fts_name, cp, p->fts_namelen + 1); 555 } else 556 p->fts_accpath = p->fts_name; 557 p->fts_info = fts_stat(sp, p, 0); 558 if (nlinks > 0 && p->fts_info == FTS_D) 559 --nlinks; 560 } else if (cderr) { 561 p->fts_info = ISSET(FTS_NOSTAT) ? FTS_NSOK : FTS_NS; 562 p->fts_accpath = cur->fts_accpath; 563 } else { 564 p->fts_accpath = 565 ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name; 566 p->fts_info = FTS_NSOK; 567 } 568 569 p->fts_link = head; 570 head = p; 571 ++nitems; 572 } 573 (void)closedir(dirp); 574 575 /* 576 * If not changing directories, reset the path back to original 577 * state. 578 */ 579 if (ISSET(FTS_NOCHDIR)) { 580 if (cp - 1 > sp->fts_path) 581 --cp; 582 *cp = '\0'; 583 } 584 585 /* 586 * If descended after called from fts_children or called from 587 * fts_read and didn't find anything, get back. If can't get 588 * back, we're done. 589 */ 590 if (descend && (!nitems || type == BCHILD) && CHDIR(sp, "..")) { 591 cur->fts_info = FTS_ERR; 592 SET(FTS_STOP); 593 return(NULL); 594 } 595 596 /* If we didn't find anything, just do the post-order visit */ 597 if (!nitems) { 598 if (type == BREAD) 599 cur->fts_info = FTS_DP; 600 return(NULL); 601 } 602 603 /* Sort the entries. */ 604 if (sp->fts_compar && nitems > 1) 605 head = fts_sort(sp, head, nitems); 606 return(head); 607 } 608 609 static u_short 610 fts_stat(sp, p, follow) 611 FTS *sp; 612 register FTSENT *p; 613 int follow; 614 { 615 int saved_errno; 616 617 /* 618 * If doing a logical walk, or application requested FTS_FOLLOW, do 619 * a stat(2). If that fails, check for a non-existent symlink. If 620 * fail, return the errno from the stat call. 621 */ 622 if (ISSET(FTS_LOGICAL) || follow) { 623 if (stat(p->fts_accpath, &p->fts_statb)) { 624 saved_errno = errno; 625 if (!lstat(p->fts_accpath, &p->fts_statb)) { 626 errno = 0; 627 return(FTS_SLNONE); 628 } 629 errno = saved_errno; 630 bzero(&p->fts_statb, sizeof(struct stat)); 631 return(FTS_NS); 632 } 633 } else if (lstat(p->fts_accpath, &p->fts_statb)) { 634 bzero(&p->fts_statb, sizeof(struct stat)); 635 return(FTS_NS); 636 } 637 638 /* 639 * Cycle detection is done as soon as we find a directory. Detection 640 * is by brute force; if the tree gets deep enough or the number of 641 * symbolic links to directories high enough something faster might 642 * be worthwhile. 643 */ 644 if (S_ISDIR(p->fts_statb.st_mode)) { 645 register FTSENT *t; 646 register dev_t dev; 647 register ino_t ino; 648 649 dev = p->fts_statb.st_dev; 650 ino = p->fts_statb.st_ino; 651 for (t = p->fts_parent; t->fts_level > FTS_ROOTLEVEL; 652 t = t->fts_parent) 653 if (ino == t->fts_statb.st_ino && 654 dev == t->fts_statb.st_dev) { 655 sp->fts_savelink = p->fts_link; 656 p->fts_link = t; 657 return(FTS_DC); 658 } 659 return(FTS_D); 660 } 661 if (S_ISLNK(p->fts_statb.st_mode)) 662 return(FTS_SL); 663 if (S_ISREG(p->fts_statb.st_mode)) 664 return(FTS_F); 665 return(FTS_DEFAULT); 666 } 667 668 #define R(type, nelem, ptr) \ 669 (type *)realloc((void *)ptr, (u_int)((nelem) * sizeof(type))) 670 671 static FTSENT * 672 fts_sort(sp, head, nitems) 673 FTS *sp; 674 FTSENT *head; 675 register int nitems; 676 { 677 register FTSENT **ap, *p; 678 679 /* 680 * Construct an array of pointers to the structures and call qsort(3). 681 * Reassemble the array in the order returned by qsort. If unable to 682 * sort for memory reasons, return the directory entries in their 683 * current order. Allocate enough space for the current needs plus 684 * 40 so we don't realloc one entry at a time. 685 */ 686 if (nitems > sp->fts_nitems) { 687 sp->fts_nitems = nitems + 40; 688 if (!(sp->fts_array = 689 R(FTSENT *, sp->fts_nitems, sp->fts_array))) { 690 sp->fts_nitems = 0; 691 return(head); 692 } 693 } 694 for (ap = sp->fts_array, p = head; p; p = p->fts_link) 695 *ap++ = p; 696 qsort((void *)sp->fts_array, nitems, sizeof(FTSENT *), sp->fts_compar); 697 for (head = *(ap = sp->fts_array); --nitems; ++ap) 698 ap[0]->fts_link = ap[1]; 699 ap[0]->fts_link = NULL; 700 return(head); 701 } 702 703 static FTSENT * 704 fts_alloc(sp, name, len) 705 FTS *sp; 706 char *name; 707 register int len; 708 { 709 register FTSENT *p; 710 711 /* 712 * Variable sized structures; the name is the last element so 713 * we allocate enough extra space after the structure to store 714 * it. 715 */ 716 if (!(p = (FTSENT *)malloc((size_t)(sizeof(FTSENT) + len)))) 717 return(NULL); 718 bcopy(name, p->fts_name, len + 1); 719 p->fts_namelen = len; 720 p->fts_path = sp->fts_path; 721 p->fts_instr = FTS_NOINSTR; 722 p->fts_cderr = 0; 723 p->fts_number = 0; 724 p->fts_pointer = NULL; 725 return(p); 726 } 727 728 static void 729 fts_lfree(head) 730 register FTSENT *head; 731 { 732 register FTSENT *p; 733 734 /* Free a linked list of structures. */ 735 while (p = head) { 736 head = head->fts_link; 737 free(p); 738 } 739 } 740 741 /* 742 * Allow essentially unlimited paths; certain programs (find, rm, ls) need to 743 * work on any tree. Most systems will allow creation of paths much longer 744 * than MAXPATHLEN, even though the kernel won't resolve them. Add an extra 745 * 128 bytes to the requested size so that we don't realloc the path 2 bytes 746 * at a time. 747 */ 748 static char * 749 fts_path(sp, size) 750 FTS *sp; 751 int size; 752 { 753 sp->fts_pathlen += size + 128; 754 return(sp->fts_path = R(char, sp->fts_pathlen, sp->fts_path)); 755 } 756