00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "system.h"
00032
00033 #if defined(LIBC_SCCS) && !defined(lint)
00034 static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94";
00035 #endif
00036
00037 #if defined(_LIBC)
00038 #include <sys/param.h>
00039 #include <include/sys/stat.h>
00040 #include <fcntl.h>
00041 #include <dirent.h>
00042 #include <errno.h>
00043 #include <fts.h>
00044 #include <stdlib.h>
00045 #include <string.h>
00046 #include <unistd.h>
00047 #else
00048 #if defined(__UCLIBC__)
00049 # define __fxstat64(_stat_ver, _fd, _sbp) fstat((_fd), (_sbp))
00050 #endif
00051 #if defined(hpux) || defined(__hpux)
00052 # define _INCLUDE_POSIX_SOURCE
00053 # define __errno_location() (&errno)
00054 # define dirfd(dirp) -1
00055 # define stat64 stat
00056 # define _STAT_VER 0
00057 # define __fxstat64(_stat_ver, _fd, _sbp) fstat((_fd), (_sbp))
00058 # define _D_EXACT_NAMLEN(d) ((d)->d_namlen)
00059 #endif
00060 #if defined(sun) || defined(RPM_OS_UNIXWARE)
00061 # define __errno_location() (&errno)
00062 # define dirfd(dirp) -1
00063 # define _STAT_VER 0
00064 # define __fxstat64(_stat_ver, _fd, _sbp) fstat((_fd), (_sbp))
00065 #endif
00066 #if defined(__APPLE__)
00067 # include <sys/stat.h>
00068 # define __errno_location() (__error())
00069 #ifndef __DARWIN_STRUCT_STAT64
00070 # define stat64 stat
00071 #endif
00072 # define _STAT_VER 0
00073 #ifndef __DARWIN_STRUCT_STAT64
00074 # define __fxstat64(_stat_ver, _fd, _sbp) fstat((_fd), (_sbp))
00075 #else
00076 # define __fxstat64(_stat_ver, _fd, _sbp) fstat64((_fd), (_sbp))
00077 #endif
00078 #endif
00079 #if defined(__CYGWIN__) || defined(__MINGW32__)
00080 # include <sys/stat.h>
00081 #if defined(__CYGWIN__)
00082 # define __errno_location() (__errno())
00083 #elif !defined(_UWIN)
00084 # define __errno_location() (_errno())
00085 #else
00086 # define __errno_location() (&errno)
00087 #endif
00088 # define stat64 stat
00089 # define _STAT_VER 0
00090 # define __fxstat64(_stat_ver, _fd, _sbp) fstat((_fd), (_sbp))
00091 #endif
00092 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
00093 # define __errno_location() (&errno)
00094 # define stat64 stat
00095 # define __fxstat64(_stat_ver, _fd, _sbp) fstat((_fd), (_sbp))
00096 # define _D_EXACT_NAMLEN(d) ((d)->d_namlen)
00097 #endif
00098 #if defined(__osf__)
00099 # define __errno_location() (&errno)
00100 # define dirfd(dirp) -1
00101 # define stat64 stat
00102 # define _STAT_VER 0
00103 # define __fxstat64(_stat_ver, _fd, _sbp) fstat((_fd), (_sbp))
00104 # define _D_EXACT_NAMLEN(d) ((d)->d_namlen)
00105 #endif
00106 #if defined(RPM_OS_IRIX)
00107 # define __errno_location() (&errno)
00108 # define dirfd(dirp) -1
00109 # define __fxstat64(_stat_ver, _fd, _sbp) fstat((_fd), (_sbp))
00110 # define _D_EXACT_NAMLEN(d) ((d)->d_reclen)
00111 #endif
00112 #if defined(RPM_OS_AIX)
00113 # define __errno_location() (&errno)
00114 # define dirfd(dirp) ((dirp)->dd_fd)
00115 # define _STAT_VER 0
00116 # define __fxstat64(_stat_ver, _fd, _sbp) fstat((_fd), (_sbp))
00117 # define _D_EXACT_NAMLEN(d) ((d)->d_namlen)
00118 #endif
00119 #if defined(RPM_OS_NTOQNX)
00120 # define __errno_location() (&errno)
00121 # define stat64 stat
00122 # define _STAT_VER 0
00123 # define dirfd(dirp) -1
00124 # define __fxstat64(_stat_ver, _fd, _sbp) fstat((_fd), (_sbp))
00125 #endif
00126
00127 #if !defined(_D_EXACT_NAMLEN)
00128 # define _D_EXACT_NAMLEN(d) (strlen((d)->d_name))
00129 #endif
00130 #include "fts.h"
00131 #include "rpmio.h"
00132 #include "rpmurl.h"
00133 #include "debug.h"
00134 # define __set_errno(val) (*__errno_location ()) = (val)
00135 # define __open open
00136 # define __close close
00137 # define __fchdir fchdir
00138 #endif
00139
00140 #if !defined(USHRT_MAX)
00141 #define USHRT_MAX 65535
00142 #endif
00143
00144
00145
00146 #ifndef ALIGNBYTES
00147 #if defined __GNUC__ && __GNUC__ >= 2
00148 # define alignof(TYPE) __alignof__ (TYPE)
00149 #else
00150 # define alignof(TYPE) \
00151 ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2)
00152 #endif
00153 #define ALIGNBYTES (alignof(long double) - 1)
00154 #endif
00155
00156 #ifndef ALIGN
00157 #define ALIGN(p) (((unsigned long int) (p) + ALIGNBYTES) & ~ALIGNBYTES)
00158 #endif
00159
00160
00161 int _fts_debug = 0;
00162
00163
00164 static FTSENT * fts_alloc(FTS * sp, const char * name, int namelen)
00165 ;
00166
00167 static FTSENT * fts_build(FTS * sp, int type)
00168
00169 ;
00170 static void fts_lfree( FTSENT * head)
00171 ;
00172 static void fts_load(FTS * sp, FTSENT * p)
00173 ;
00174 static size_t fts_maxarglen(char * const * argv)
00175 ;
00176 static void fts_padjust(FTS * sp, FTSENT * head)
00177 ;
00178 static int fts_palloc(FTS * sp, size_t more)
00179 ;
00180 static FTSENT * fts_sort(FTS * sp, FTSENT * head, int nitems)
00181 ;
00182 static u_short fts_stat(FTS * sp, FTSENT * p, int follow)
00183 ;
00184 static int fts_safe_changedir(FTS * sp, FTSENT * p, int fd,
00185 const char * path)
00186
00187 ;
00188
00189 #define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
00190
00191 #define CLR(opt) (sp->fts_options &= ~(opt))
00192 #define ISSET(opt) (sp->fts_options & (opt))
00193 #define SET(opt) (sp->fts_options |= (opt))
00194
00195 #define FCHDIR(sp, fd) (!ISSET(FTS_NOCHDIR) && __fchdir(fd))
00196
00197
00198 #define BCHILD 1
00199 #define BNAMES 2
00200 #define BREAD 3
00201
00202 FTS *
00203 Fts_open(char * const * argv, int options,
00204 int (*compar) (const FTSENT **, const FTSENT **))
00205 {
00206 register FTS *sp;
00207 register FTSENT *p, *root;
00208 register int nitems;
00209 FTSENT *parent = NULL;
00210 FTSENT *tmp = NULL;
00211 size_t len;
00212
00213
00214 if (_fts_debug)
00215 fprintf(stderr, "*** Fts_open(%p, 0x%x, %p)\n", argv, options, compar);
00216
00217
00218
00219 if (options & ~FTS_OPTIONMASK) {
00220
00221 __set_errno (EINVAL);
00222
00223 return (NULL);
00224 }
00225
00226
00227 if ((sp = malloc((u_int)sizeof(*sp))) == NULL)
00228 return (NULL);
00229 memset(sp, 0, sizeof(*sp));
00230 sp->fts_compar = (int (*) (const void *, const void *)) compar;
00231 sp->fts_opendir = Opendir;
00232 sp->fts_readdir = Readdir;
00233 sp->fts_closedir = Closedir;
00234 sp->fts_stat = Stat;
00235 sp->fts_lstat = Lstat;
00236 sp->fts_options = options;
00237
00238
00239 if (ISSET(FTS_LOGICAL))
00240 SET(FTS_NOCHDIR);
00241
00242
00243
00244
00245
00246 #ifndef MAXPATHLEN
00247 #define MAXPATHLEN 1024
00248 #endif
00249 len = fts_maxarglen(argv);
00250 if (len < MAXPATHLEN)
00251 len = MAXPATHLEN;
00252 if (fts_palloc(sp, len))
00253 goto mem1;
00254
00255
00256 if (*argv != NULL) {
00257 if ((parent = fts_alloc(sp, "", 0)) == NULL)
00258 goto mem2;
00259 parent->fts_level = FTS_ROOTPARENTLEVEL;
00260 }
00261
00262
00263 for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) {
00264
00265 if ((len = strlen(*argv)) == 0) {
00266 __set_errno (ENOENT);
00267 goto mem3;
00268 }
00269
00270
00271 switch (urlIsURL(*argv)) {
00272 case URL_IS_DASH:
00273 case URL_IS_HKP:
00274 __set_errno (ENOENT);
00275 goto mem3;
00276 break;
00277 case URL_IS_HTTPS:
00278 case URL_IS_HTTP:
00279 case URL_IS_FTP:
00280 SET(FTS_NOCHDIR);
00281 break;
00282 case URL_IS_UNKNOWN:
00283 case URL_IS_PATH:
00284 break;
00285 }
00286
00287 p = fts_alloc(sp, *argv, (int)len);
00288 if (p == NULL)
00289 goto mem3;
00290 p->fts_level = FTS_ROOTLEVEL;
00291 p->fts_parent = parent;
00292 p->fts_accpath = p->fts_name;
00293 p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW));
00294
00295
00296 if (p->fts_info == FTS_DOT)
00297 p->fts_info = FTS_D;
00298
00299
00300
00301
00302
00303 if (compar) {
00304 p->fts_link = root;
00305 root = p;
00306 } else {
00307 p->fts_link = NULL;
00308 if (root == NULL)
00309 tmp = root = p;
00310 else {
00311 if (tmp != NULL)
00312 tmp->fts_link = p;
00313 tmp = p;
00314 }
00315 }
00316 }
00317 if (compar && nitems > 1)
00318 root = fts_sort(sp, root, nitems);
00319
00320
00321
00322
00323
00324
00325 if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL)
00326 goto mem3;
00327 sp->fts_cur->fts_link = root;
00328 sp->fts_cur->fts_info = FTS_INIT;
00329
00330
00331
00332
00333
00334
00335
00336
00337 if (!ISSET(FTS_NOCHDIR)
00338 && (sp->fts_rfd = __open(".", O_RDONLY, 0)) < 0)
00339 SET(FTS_NOCHDIR);
00340
00341 return (sp);
00342
00343 mem3: fts_lfree(root);
00344 free(parent);
00345 mem2: free(sp->fts_path);
00346 mem1: free(sp);
00347 return (NULL);
00348 }
00349
00350 static void
00351 fts_load(FTS * sp, FTSENT * p)
00352 {
00353 register size_t len;
00354 register char *cp;
00355
00356
00357
00358
00359
00360
00361
00362
00363 len = p->fts_pathlen = p->fts_namelen;
00364 memmove(sp->fts_path, p->fts_name, len + 1);
00365 if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) {
00366 len = strlen(++cp);
00367 memmove(p->fts_name, cp, len + 1);
00368 p->fts_namelen = (u_short)len;
00369 }
00370 p->fts_accpath = p->fts_path = sp->fts_path;
00371 sp->fts_dev = p->fts_dev;
00372 }
00373
00374 int
00375 Fts_close(FTS * sp)
00376 {
00377 register FTSENT *freep, *p;
00378 int saved_errno;
00379
00380 if (_fts_debug)
00381 fprintf(stderr, "*** Fts_close(%p)\n", sp);
00382
00383 if (sp == NULL)
00384 return 0;
00385
00386
00387
00388
00389
00390
00391 if (sp->fts_cur) {
00392 for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
00393 freep = p;
00394 p = p->fts_link != NULL ? p->fts_link : p->fts_parent;
00395 free(freep);
00396 }
00397 free(p);
00398 }
00399
00400
00401 if (sp->fts_child)
00402 fts_lfree(sp->fts_child);
00403 if (sp->fts_array)
00404 free(sp->fts_array);
00405 free(sp->fts_path);
00406
00407
00408 if (!ISSET(FTS_NOCHDIR)) {
00409 saved_errno = __fchdir(sp->fts_rfd) ? errno : 0;
00410 (void)__close(sp->fts_rfd);
00411
00412
00413 if (saved_errno != 0) {
00414
00415 free(sp);
00416 __set_errno (saved_errno);
00417 return (-1);
00418 }
00419 }
00420
00421
00422 free(sp);
00423 return (0);
00424 }
00425
00426
00427
00428
00429
00430 #define NAPPEND(p) \
00431 (p->fts_path[p->fts_pathlen - 1] == '/' \
00432 ? p->fts_pathlen - 1 : p->fts_pathlen)
00433
00434 FTSENT *
00435 Fts_read(FTS * sp)
00436 {
00437 register FTSENT *p;
00438 register FTSENT *tmp;
00439 register int instr;
00440 register char *t;
00441 int saved_errno;
00442
00443 if (_fts_debug)
00444 fprintf(stderr, "*** Fts_read(%p)\n", sp);
00445
00446
00447 if (sp == NULL || sp->fts_cur == NULL || ISSET(FTS_STOP))
00448 return (NULL);
00449
00450
00451 p = sp->fts_cur;
00452
00453
00454 instr = p->fts_instr;
00455 p->fts_instr = FTS_NOINSTR;
00456
00457
00458 if (instr == FTS_AGAIN) {
00459 p->fts_info = fts_stat(sp, p, 0);
00460 return (p);
00461 }
00462
00463
00464
00465
00466
00467
00468
00469 if (instr == FTS_FOLLOW &&
00470 (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
00471 p->fts_info = fts_stat(sp, p, 1);
00472 if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
00473 if ((p->fts_symfd = __open(".", O_RDONLY, 0)) < 0) {
00474 p->fts_errno = errno;
00475 p->fts_info = FTS_ERR;
00476 } else
00477 p->fts_flags |= FTS_SYMFOLLOW;
00478 }
00479 return (p);
00480 }
00481
00482
00483 if (p->fts_info == FTS_D) {
00484
00485 if (instr == FTS_SKIP ||
00486 (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) {
00487 if (p->fts_flags & FTS_SYMFOLLOW)
00488 (void)__close(p->fts_symfd);
00489 if (sp->fts_child) {
00490 fts_lfree(sp->fts_child);
00491 sp->fts_child = NULL;
00492 }
00493 p->fts_info = FTS_DP;
00494 return (p);
00495 }
00496
00497
00498 if (sp->fts_child != NULL && ISSET(FTS_NAMEONLY)) {
00499 CLR(FTS_NAMEONLY);
00500 fts_lfree(sp->fts_child);
00501 sp->fts_child = NULL;
00502 }
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516 if (sp->fts_child != NULL) {
00517 if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) {
00518 p->fts_errno = errno;
00519 p->fts_flags |= FTS_DONTCHDIR;
00520 for (p = sp->fts_child; p != NULL;
00521 p = p->fts_link)
00522 p->fts_accpath =
00523 p->fts_parent->fts_accpath;
00524 }
00525 } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) {
00526 if (ISSET(FTS_STOP))
00527 return (NULL);
00528 return (p);
00529 }
00530 p = sp->fts_child;
00531 sp->fts_child = NULL;
00532 sp->fts_cur = p;
00533 goto name;
00534 }
00535
00536
00537 next: tmp = p;
00538 if ((p = p->fts_link) != NULL) {
00539 sp->fts_cur = p;
00540 free(tmp);
00541
00542
00543
00544
00545
00546 if (p->fts_level == FTS_ROOTLEVEL) {
00547 if (FCHDIR(sp, sp->fts_rfd)) {
00548 SET(FTS_STOP);
00549 return (NULL);
00550 }
00551 fts_load(sp, p);
00552 return (p);
00553 }
00554
00555
00556
00557
00558
00559
00560 if (p->fts_instr == FTS_SKIP)
00561 goto next;
00562 if (p->fts_instr == FTS_FOLLOW) {
00563 p->fts_info = fts_stat(sp, p, 1);
00564 if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
00565 if ((p->fts_symfd =
00566 __open(".", O_RDONLY, 0)) < 0) {
00567 p->fts_errno = errno;
00568 p->fts_info = FTS_ERR;
00569 } else
00570 p->fts_flags |= FTS_SYMFOLLOW;
00571 }
00572 p->fts_instr = FTS_NOINSTR;
00573 }
00574
00575 name: t = sp->fts_path + NAPPEND(p->fts_parent);
00576 *t++ = '/';
00577 memmove(t, p->fts_name, p->fts_namelen + 1);
00578 return (p);
00579 }
00580
00581
00582 p = tmp->fts_parent;
00583 sp->fts_cur = p;
00584 free(tmp);
00585
00586 if (p->fts_level == FTS_ROOTPARENTLEVEL) {
00587
00588
00589
00590
00591 free(p);
00592 __set_errno (0);
00593 return (sp->fts_cur = NULL);
00594 }
00595
00596
00597 sp->fts_path[p->fts_pathlen] = '\0';
00598
00599
00600
00601
00602
00603
00604 if (p->fts_level == FTS_ROOTLEVEL) {
00605 if (FCHDIR(sp, sp->fts_rfd)) {
00606 SET(FTS_STOP);
00607 return (NULL);
00608 }
00609 } else if (p->fts_flags & FTS_SYMFOLLOW) {
00610 if (FCHDIR(sp, p->fts_symfd)) {
00611 saved_errno = errno;
00612 (void)__close(p->fts_symfd);
00613 __set_errno (saved_errno);
00614 SET(FTS_STOP);
00615 return (NULL);
00616 }
00617 (void)__close(p->fts_symfd);
00618 } else if (!(p->fts_flags & FTS_DONTCHDIR) &&
00619 fts_safe_changedir(sp, p->fts_parent, -1, "..")) {
00620 SET(FTS_STOP);
00621 return (NULL);
00622 }
00623 p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
00624 return (p);
00625 }
00626
00627
00628
00629
00630
00631
00632
00633 int
00634 Fts_set( FTS * sp, FTSENT * p, int instr)
00635 {
00636
00637 if (_fts_debug)
00638 fprintf(stderr, "*** Fts_set(%p, %p, 0x%x)\n", sp, p, instr);
00639
00640
00641 if (instr != 0 && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
00642 instr != FTS_NOINSTR && instr != FTS_SKIP) {
00643 __set_errno (EINVAL);
00644 return (1);
00645 }
00646 p->fts_instr = instr;
00647 return (0);
00648 }
00649
00650 FTSENT *
00651 Fts_children(FTS * sp, int instr)
00652 {
00653 register FTSENT *p;
00654 int fd;
00655
00656
00657 if (_fts_debug)
00658 fprintf(stderr, "*** Fts_children(%p, 0x%x)\n", sp, instr);
00659
00660
00661 if (instr != 0 && instr != FTS_NAMEONLY) {
00662 __set_errno (EINVAL);
00663 return (NULL);
00664 }
00665
00666
00667 p = sp->fts_cur;
00668
00669
00670
00671
00672
00673 __set_errno (0);
00674
00675
00676 if (ISSET(FTS_STOP))
00677 return (NULL);
00678
00679
00680 if (p->fts_info == FTS_INIT)
00681 return (p->fts_link);
00682
00683
00684
00685
00686
00687
00688 if (p->fts_info != FTS_D )
00689 return (NULL);
00690
00691
00692 if (sp->fts_child != NULL)
00693 fts_lfree(sp->fts_child);
00694
00695 if (instr == FTS_NAMEONLY) {
00696 SET(FTS_NAMEONLY);
00697 instr = BNAMES;
00698 } else
00699 instr = BCHILD;
00700
00701
00702
00703
00704
00705
00706
00707
00708 if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' ||
00709 ISSET(FTS_NOCHDIR))
00710 return (sp->fts_child = fts_build(sp, instr));
00711
00712 if ((fd = __open(".", O_RDONLY, 0)) < 0)
00713 return (NULL);
00714 sp->fts_child = fts_build(sp, instr);
00715 if (__fchdir(fd))
00716 return (NULL);
00717 (void)__close(fd);
00718 return (sp->fts_child);
00719 }
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735 static FTSENT *
00736 fts_build(FTS * sp, int type)
00737 {
00738 register struct dirent *dp;
00739 register FTSENT *p, *head;
00740 register int nitems;
00741 FTSENT *cur, *tail;
00742 DIR *dirp;
00743 void *oldaddr;
00744 int cderrno, descend, len, level, nlinks, saved_errno,
00745 nostat, doadjust;
00746 size_t maxlen;
00747 char *cp;
00748
00749
00750 cur = sp->fts_cur;
00751
00752
00753
00754
00755
00756 #if defined FTS_WHITEOUT && 0
00757 if (ISSET(FTS_WHITEOUT))
00758 oflag = DTF_NODUP|DTF_REWIND;
00759 else
00760 oflag = DTF_HIDEW|DTF_NODUP|DTF_REWIND;
00761 #else
00762 # define __opendir2(path, flag) (*sp->fts_opendir) (path)
00763 #endif
00764 if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) {
00765 if (type == BREAD) {
00766 cur->fts_info = FTS_DNR;
00767 cur->fts_errno = errno;
00768 }
00769 return (NULL);
00770 }
00771
00772
00773
00774
00775
00776
00777 if (type == BNAMES) {
00778 nlinks = 0;
00779
00780 nostat = 0;
00781 } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) {
00782 nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2);
00783 nostat = 1;
00784 } else {
00785 nlinks = -1;
00786 nostat = 0;
00787 }
00788
00789 #ifdef notdef
00790 (void)printf("nlinks == %d (cur: %d)\n", nlinks, cur->fts_nlink);
00791 (void)printf("NOSTAT %d PHYSICAL %d SEEDOT %d\n",
00792 ISSET(FTS_NOSTAT), ISSET(FTS_PHYSICAL), ISSET(FTS_SEEDOT));
00793 #endif
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809 cderrno = 0;
00810 if (nlinks || type == BREAD) {
00811
00812 if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) {
00813
00814 if (nlinks && type == BREAD)
00815 cur->fts_errno = errno;
00816 cur->fts_flags |= FTS_DONTCHDIR;
00817 descend = 0;
00818 cderrno = errno;
00819 (void) (*sp->fts_closedir) (dirp);
00820 dirp = NULL;
00821 } else
00822 descend = 1;
00823 } else
00824 descend = 0;
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836 len = NAPPEND(cur);
00837 if (ISSET(FTS_NOCHDIR)) {
00838 cp = sp->fts_path + len;
00839 *cp++ = '/';
00840 } else {
00841
00842 cp = NULL;
00843 }
00844 len++;
00845 maxlen = sp->fts_pathlen - len;
00846
00847 level = cur->fts_level + 1;
00848
00849
00850 doadjust = 0;
00851 for (head = tail = NULL, nitems = 0;
00852 dirp && (dp = (*sp->fts_readdir) (dirp));)
00853 {
00854 if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
00855 continue;
00856
00857 if ((p = fts_alloc(sp, dp->d_name, (int)_D_EXACT_NAMLEN (dp))) == NULL)
00858 goto mem1;
00859 if (_D_EXACT_NAMLEN (dp) >= maxlen) {
00860 oldaddr = sp->fts_path;
00861 if (fts_palloc(sp, _D_EXACT_NAMLEN (dp) + len + 1)) {
00862
00863
00864
00865
00866
00867 mem1: saved_errno = errno;
00868 if (p)
00869 free(p);
00870 fts_lfree(head);
00871 (void) (*sp->fts_closedir) (dirp);
00872 cur->fts_info = FTS_ERR;
00873 SET(FTS_STOP);
00874 __set_errno (saved_errno);
00875 return (NULL);
00876 }
00877
00878 if (oldaddr != sp->fts_path) {
00879 doadjust = 1;
00880 if (ISSET(FTS_NOCHDIR))
00881 cp = sp->fts_path + len;
00882 }
00883 maxlen = sp->fts_pathlen - len;
00884 }
00885
00886 if (len + _D_EXACT_NAMLEN (dp) >= USHRT_MAX) {
00887
00888
00889
00890
00891
00892
00893 free(p);
00894 fts_lfree(head);
00895 (void) (*sp->fts_closedir) (dirp);
00896 cur->fts_info = FTS_ERR;
00897 SET(FTS_STOP);
00898 __set_errno (ENAMETOOLONG);
00899 return (NULL);
00900 }
00901 p->fts_level = level;
00902 p->fts_parent = sp->fts_cur;
00903 p->fts_pathlen = (u_short)(len + _D_EXACT_NAMLEN (dp));
00904
00905 #if defined FTS_WHITEOUT && 0
00906 if (dp->d_type == DT_WHT)
00907 p->fts_flags |= FTS_ISW;
00908 #endif
00909
00910 #if 0
00911
00912
00913
00914
00915
00916 if (cderrno) {
00917 if (nlinks) {
00918 p->fts_info = FTS_NS;
00919 p->fts_errno = cderrno;
00920 } else
00921 p->fts_info = FTS_NSOK;
00922 p->fts_accpath = cur->fts_accpath;
00923 } else
00924 #endif
00925 if (nlinks == 0
00926 #if defined DT_DIR && defined _DIRENT_HAVE_D_TYPE
00927 || (nostat &&
00928 dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN)
00929 #endif
00930 ) {
00931 p->fts_accpath =
00932 ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name;
00933 p->fts_info = FTS_NSOK;
00934 } else {
00935
00936 if (ISSET(FTS_NOCHDIR)) {
00937 p->fts_accpath = p->fts_path;
00938 memmove(cp, p->fts_name, p->fts_namelen + 1);
00939 } else
00940 p->fts_accpath = p->fts_name;
00941
00942 p->fts_info = fts_stat(sp, p, 0);
00943
00944
00945 if (nlinks > 0 && (p->fts_info == FTS_D ||
00946 p->fts_info == FTS_DC || p->fts_info == FTS_DOT))
00947 --nlinks;
00948 }
00949
00950
00951 p->fts_link = NULL;
00952 if (head == NULL)
00953 head = tail = p;
00954 else {
00955 tail->fts_link = p;
00956 tail = p;
00957 }
00958 ++nitems;
00959 }
00960 if (dirp)
00961 (void) (*sp->fts_closedir) (dirp);
00962
00963
00964
00965
00966
00967 if (doadjust)
00968 fts_padjust(sp, head);
00969
00970
00971
00972
00973
00974 if (ISSET(FTS_NOCHDIR)) {
00975 if (len == sp->fts_pathlen || nitems == 0)
00976 --cp;
00977 if (cp != NULL)
00978 *cp = '\0';
00979 }
00980
00981
00982
00983
00984
00985
00986
00987
00988 if (descend && (type == BCHILD || !nitems) &&
00989 (cur->fts_level == FTS_ROOTLEVEL ?
00990 FCHDIR(sp, sp->fts_rfd) :
00991 fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
00992 cur->fts_info = FTS_ERR;
00993 SET(FTS_STOP);
00994 fts_lfree(head);
00995 return (NULL);
00996 }
00997
00998
00999 if (!nitems) {
01000 if (type == BREAD)
01001 cur->fts_info = FTS_DP;
01002 fts_lfree(head);
01003 return (NULL);
01004 }
01005
01006
01007 if (sp->fts_compar && nitems > 1)
01008 head = fts_sort(sp, head, nitems);
01009 return (head);
01010 }
01011
01012 static u_short
01013 fts_stat(FTS * sp, FTSENT * p, int follow)
01014 {
01015 register FTSENT *t;
01016 register dev_t dev;
01017 register ino_t ino;
01018 struct stat *sbp, sb;
01019 int saved_errno;
01020
01021
01022 sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp;
01023
01024 #if defined FTS_WHITEOUT && 0
01025
01026 if (p->fts_flags & FTS_ISW) {
01027 if (sbp != &sb) {
01028 memset(sbp, '\0', sizeof (*sbp));
01029 sbp->st_mode = S_IFWHT;
01030 }
01031 return (FTS_W);
01032 }
01033 #endif
01034
01035
01036
01037
01038
01039
01040 if (ISSET(FTS_LOGICAL) || follow) {
01041 if ((*sp->fts_stat) (p->fts_accpath, sbp)) {
01042 saved_errno = errno;
01043 if (!(*sp->fts_lstat) (p->fts_accpath, sbp)) {
01044 __set_errno (0);
01045 return (FTS_SLNONE);
01046 }
01047 p->fts_errno = saved_errno;
01048 goto err;
01049 }
01050 } else if ((*sp->fts_lstat) (p->fts_accpath, sbp)) {
01051 p->fts_errno = errno;
01052 err: memset(sbp, 0, sizeof(*sbp));
01053 return (FTS_NS);
01054 }
01055
01056 if (S_ISDIR(sbp->st_mode)) {
01057
01058
01059
01060
01061
01062
01063
01064 dev = p->fts_dev = sbp->st_dev;
01065 ino = p->fts_ino = sbp->st_ino;
01066 p->fts_nlink = sbp->st_nlink;
01067
01068 if (ISDOT(p->fts_name))
01069 return (FTS_DOT);
01070
01071
01072
01073
01074
01075
01076
01077 for (t = p->fts_parent;
01078 t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent)
01079 if (ino == t->fts_ino && dev == t->fts_dev) {
01080 p->fts_cycle = t;
01081 return (FTS_DC);
01082 }
01083 return (FTS_D);
01084 }
01085 if (S_ISLNK(sbp->st_mode))
01086 return (FTS_SL);
01087 if (S_ISREG(sbp->st_mode))
01088 return (FTS_F);
01089 return (FTS_DEFAULT);
01090 }
01091
01092 static FTSENT *
01093 fts_sort(FTS * sp, FTSENT * head, int nitems)
01094 {
01095 register FTSENT **ap, *p;
01096
01097
01098
01099
01100
01101
01102
01103
01104 if (nitems > sp->fts_nitems) {
01105 struct _ftsent **a;
01106
01107 sp->fts_nitems = nitems + 40;
01108 if ((a = realloc(sp->fts_array,
01109 (size_t)(sp->fts_nitems * sizeof(*sp->fts_array)))) == NULL)
01110 {
01111 free(sp->fts_array);
01112 sp->fts_array = NULL;
01113 sp->fts_nitems = 0;
01114 return (head);
01115 }
01116 sp->fts_array = a;
01117 }
01118 for (ap = sp->fts_array, p = head; p != NULL; p = p->fts_link)
01119 *ap++ = p;
01120 qsort((void *)sp->fts_array, nitems, sizeof(*sp->fts_array),
01121 sp->fts_compar);
01122 for (head = *(ap = sp->fts_array); --nitems; ++ap)
01123 ap[0]->fts_link = ap[1];
01124 ap[0]->fts_link = NULL;
01125 return (head);
01126 }
01127
01128 static FTSENT *
01129 fts_alloc(FTS * sp, const char * name, int namelen)
01130 {
01131 register FTSENT *p;
01132 size_t len;
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142 len = sizeof(*p) + namelen;
01143 if (!ISSET(FTS_NOSTAT))
01144 len += sizeof(*p->fts_statp) + ALIGNBYTES;
01145 if ((p = malloc(len)) == NULL)
01146 return (NULL);
01147
01148
01149 memmove(p->fts_name, name, namelen);
01150 p->fts_name[namelen] = '\0';
01151
01152 if (!ISSET(FTS_NOSTAT))
01153 p->fts_statp = (struct stat *)ALIGN(p->fts_name + namelen + 2);
01154 p->fts_namelen = namelen;
01155 p->fts_path = sp->fts_path;
01156 p->fts_errno = 0;
01157 p->fts_flags = 0;
01158 p->fts_instr = FTS_NOINSTR;
01159 p->fts_number = 0;
01160 p->fts_pointer = NULL;
01161 return (p);
01162 }
01163
01164 static void
01165 fts_lfree(FTSENT * head)
01166 {
01167 register FTSENT *p;
01168
01169
01170 while ((p = head)) {
01171 head = head->fts_link;
01172 free(p);
01173 }
01174 }
01175
01176
01177
01178
01179
01180
01181
01182 static int
01183 fts_palloc(FTS * sp, size_t more)
01184 {
01185 char *p;
01186
01187 sp->fts_pathlen += more + 256;
01188
01189
01190
01191
01192
01193 if (sp->fts_pathlen < 0 || sp->fts_pathlen >= USHRT_MAX) {
01194 if (sp->fts_path)
01195 free(sp->fts_path);
01196 sp->fts_path = NULL;
01197 __set_errno (ENAMETOOLONG);
01198 return (1);
01199 }
01200 p = realloc(sp->fts_path, sp->fts_pathlen);
01201 if (p == NULL) {
01202 free(sp->fts_path);
01203 sp->fts_path = NULL;
01204 return 1;
01205 }
01206 sp->fts_path = p;
01207 return 0;
01208 }
01209
01210
01211
01212
01213
01214 static void
01215 fts_padjust(FTS * sp, FTSENT * head)
01216 {
01217 FTSENT *p;
01218 char *addr = sp->fts_path;
01219
01220 #define ADJUST(p) do { \
01221 if ((p)->fts_accpath != (p)->fts_name) { \
01222 (p)->fts_accpath = \
01223 (char *)addr + ((p)->fts_accpath - (p)->fts_path); \
01224 } \
01225 (p)->fts_path = addr; \
01226 } while (0)
01227
01228 for (p = sp->fts_child; p != NULL; p = p->fts_link)
01229 ADJUST(p);
01230
01231
01232 for (p = head; p->fts_level >= FTS_ROOTLEVEL;) {
01233 ADJUST(p);
01234 p = p->fts_link ? p->fts_link : p->fts_parent;
01235 }
01236 }
01237
01238 static size_t
01239 fts_maxarglen(char * const * argv)
01240 {
01241 size_t len, max;
01242
01243 for (max = 0; *argv; ++argv)
01244 if ((len = strlen(*argv)) > max)
01245 max = len;
01246 return (max + 1);
01247 }
01248
01249
01250
01251
01252
01253
01254 static int
01255 fts_safe_changedir(FTS * sp, FTSENT * p, int fd, const char * path)
01256 {
01257 int ret, oerrno, newfd;
01258 struct stat64 sb;
01259
01260 newfd = fd;
01261 if (ISSET(FTS_NOCHDIR))
01262 return (0);
01263
01264
01265
01266
01267 { const char * lpath = NULL;
01268 int ut = urlPath(path, &lpath);
01269 if (ut == URL_IS_PATH) path = lpath;
01270 }
01271
01272 if (fd < 0 && (newfd = __open(path, O_RDONLY, 0)) < 0)
01273 return (-1);
01274
01275 if (__fxstat64(_STAT_VER, newfd, &sb)) {
01276 ret = -1;
01277 goto bail;
01278 }
01279
01280 if (p->fts_dev != sb.st_dev || p->fts_ino != sb.st_ino) {
01281 __set_errno (ENOENT);
01282 ret = -1;
01283 goto bail;
01284 }
01285 ret = __fchdir(newfd);
01286 bail:
01287 oerrno = errno;
01288 if (fd < 0)
01289 (void)__close(newfd);
01290 __set_errno (oerrno);
01291 return (ret);
01292 }
01293