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