]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
virgin copy from glibc
authorJim Meyering <jim@meyering.net>
Mon, 24 Feb 2003 08:24:59 +0000 (08:24 +0000)
committerJim Meyering <jim@meyering.net>
Mon, 24 Feb 2003 08:24:59 +0000 (08:24 +0000)
lib/fts.c
lib/fts_.h

index 05f4aa2407d47c89d443f12b8809a5929a6598c8..35374a094a708f0edb8b54168979a94bc819846d 100644 (file)
--- a/lib/fts.c
+++ b/lib/fts.c
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)fts.c      8.6 (Berkeley) 8/14/94";
 #endif /* LIBC_SCCS and not lint */
 
-#if HAVE_SYS_PARAM_H || defined _LIBC
-# include <sys/param.h>
-#endif
-#ifdef _LIBC
-# include <include/sys/stat.h>
-#else
-# include <sys/stat.h>
-#endif
+#include <sys/param.h>
+#include <include/sys/stat.h>
 #include <fcntl.h>
+#include <dirent.h>
 #include <errno.h>
-#include <fts_.h>
-#include <search.h>
+#include <fts.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
-#if defined _LIBC
-# include <dirent.h>
-# define NAMLEN(dirent) _D_EXACT_NAMLEN (dirent)
-#else
-# if HAVE_DIRENT_H
-#  include <dirent.h>
-#  define NAMLEN(dirent) strlen ((dirent)->d_name)
-# else
-#  define dirent direct
-#  define NAMLEN(dirent) (dirent)->d_namlen
-#  if HAVE_SYS_NDIR_H
-#   include <sys/ndir.h>
-#  endif
-#  if HAVE_SYS_DIR_H
-#   include <sys/dir.h>
-#  endif
-#  if HAVE_NDIR_H
-#   include <ndir.h>
-#  endif
-# endif
-#endif
-
-#ifndef _LIBC
-# undef __close
-# define __close close
-# undef __closedir
-# define __closedir closedir
-# undef __fchdir
-# define __fchdir fchdir
-# undef __open
-# define __open open
-# undef __opendir
-# define __opendir opendir
-# undef __readdir
-# define __readdir readdir
-# undef __tdestroy
-# define __tdestroy tdestroy
-# undef __tfind
-# define __tfind tfind
-# undef __tsearch
-# define __tsearch tsearch
-# undef internal_function
-# define internal_function /* empty */
-#endif
-
-/* Arrange to make lstat calls go through the wrapper function
-   on systems with an lstat function that does not dereference symlinks
-   that are specified with a trailing slash.  */
-#if ! _LIBC && ! LSTAT_FOLLOWS_SLASHED_SYMLINK
-int rpl_lstat (const char *, struct stat *);
-# undef lstat
-# define lstat(Name, Stat_buf) rpl_lstat(Name, Stat_buf)
-#endif
-
-#ifndef __set_errno
-# define __set_errno(Val) errno = (Val)
-#endif
 
 /* Largest alignment size needed, minus one.
    Usually long double is the worst case.  */
 #ifndef ALIGNBYTES
-# define ALIGNBYTES    (__alignof__ (long double) - 1)
+#define ALIGNBYTES     (__alignof__ (long double) - 1)
 #endif
 /* Align P to that size.  */
 #ifndef ALIGN
-# define ALIGN(p)      (((unsigned long int) (p) + ALIGNBYTES) & ~ALIGNBYTES)
+#define        ALIGN(p)        (((unsigned long int) (p) + ALIGNBYTES) & ~ALIGNBYTES)
 #endif
 
 
@@ -133,23 +66,23 @@ static int      fts_safe_changedir __P((FTS *, FTSENT *, int, const char *))
      internal_function;
 
 #ifndef MAX
-# define MAX(a, b)     ({ __typeof__ (a) _a = (a); \
+#define MAX(a, b)      ({ __typeof__ (a) _a = (a); \
                           __typeof__ (b) _b = (b); \
                           _a > _b ? _a : _b; })
 #endif
 
-#define ISDOT(a)       (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
+#define        ISDOT(a)        (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
 
 #define CLR(opt)       (sp->fts_options &= ~(opt))
-#define ISSET(opt)     (sp->fts_options & (opt))
-#define SET(opt)       (sp->fts_options |= (opt))
+#define        ISSET(opt)      (sp->fts_options & (opt))
+#define        SET(opt)        (sp->fts_options |= (opt))
 
-#define FCHDIR(sp, fd) (!ISSET(FTS_NOCHDIR) && __fchdir(fd))
+#define        FCHDIR(sp, fd)  (!ISSET(FTS_NOCHDIR) && __fchdir(fd))
 
 /* fts_build flags */
-#define BCHILD         1               /* fts_children */
-#define BNAMES         2               /* fts_children, names only */
-#define BREAD          3               /* fts_read */
+#define        BCHILD          1               /* fts_children */
+#define        BNAMES          2               /* fts_children, names only */
+#define        BREAD           3               /* fts_read */
 
 FTS *
 fts_open(argv, options, compar)
@@ -185,7 +118,7 @@ fts_open(argv, options, compar)
         * to hold the user's paths.
         */
 #ifndef MAXPATHLEN
-# define MAXPATHLEN 1024
+#define MAXPATHLEN 1024
 #endif
        if (fts_palloc(sp, MAX(fts_maxarglen(argv), MAXPATHLEN)))
                goto mem1;
@@ -203,8 +136,7 @@ fts_open(argv, options, compar)
                        goto mem3;
                }
 
-               if ((p = fts_alloc(sp, *argv, len)) == NULL)
-                       goto mem3;
+               p = fts_alloc(sp, *argv, len);
                p->fts_level = FTS_ROOTLEVEL;
                p->fts_parent = parent;
                p->fts_accpath = p->fts_name;
@@ -244,8 +176,6 @@ fts_open(argv, options, compar)
        sp->fts_cur->fts_link = root;
        sp->fts_cur->fts_info = FTS_INIT;
 
-       sp->fts_dir_info = NULL;
-
        /*
         * If using chdir(2), grab a file descriptor pointing to dot to ensure
         * that we can get back here; this could be avoided for some paths,
@@ -335,9 +265,6 @@ fts_close(sp)
                }
        }
 
-       /* Free all of the directory fingerprint info.  */
-       __tdestroy (sp->fts_dir_info, free);
-
        /* Free up the stream pointer. */
        free(sp);
        return (0);
@@ -347,7 +274,7 @@ fts_close(sp)
  * Special case of "/" at the end of the path so that slashes aren't
  * appended which would cause paths to be written as "....//foo".
  */
-#define NAPPEND(p)                                                     \
+#define        NAPPEND(p)                                                      \
        (p->fts_path[p->fts_pathlen - 1] == '/'                         \
            ? p->fts_pathlen - 1 : p->fts_pathlen)
 
@@ -442,10 +369,6 @@ fts_read(sp)
                } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) {
                        if (ISSET(FTS_STOP))
                                return (NULL);
-                       /* If fts_safe_changedir failed because it was not able
-                          to fchdir into a subdirectory, tell the caller.  */
-                       if (p->fts_errno)
-                               p->fts_info = FTS_ERR;
                        return (p);
                }
                p = sp->fts_child;
@@ -766,11 +689,11 @@ fts_build(sp, type)
                if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
                        continue;
 
-               if ((p = fts_alloc(sp, dp->d_name, (int)NAMLEN (dp))) == NULL)
+               if ((p = fts_alloc(sp, dp->d_name, (int)_D_EXACT_NAMLEN (dp))) == NULL)
                        goto mem1;
-               if (NAMLEN (dp) >= maxlen) {/* include space for NUL */
+               if (_D_EXACT_NAMLEN (dp) >= maxlen) {/* include space for NUL */
                        oldaddr = sp->fts_path;
-                       if (fts_palloc(sp, NAMLEN (dp) + len + 1)) {
+                       if (fts_palloc(sp, _D_EXACT_NAMLEN (dp) + len + 1)) {
                                /*
                                 * No more memory for path or structures.  Save
                                 * errno, free up the current structure and the
@@ -795,7 +718,7 @@ mem1:                               saved_errno = errno;
                        maxlen = sp->fts_pathlen - len;
                }
 
-               if (len + NAMLEN (dp) >= 999999999 /* FIXME SIZE_MAX */) {
+               if (len + _D_EXACT_NAMLEN (dp) >= USHRT_MAX) {
                        /*
                         * In an FTSENT, fts_pathlen is a u_short so it is
                         * possible to wraparound here.  If we do, free up
@@ -812,7 +735,7 @@ mem1:                               saved_errno = errno;
                }
                p->fts_level = level;
                p->fts_parent = sp->fts_cur;
-               p->fts_pathlen = len + NAMLEN (dp);
+               p->fts_pathlen = len + _D_EXACT_NAMLEN (dp);
 
 #if defined FTS_WHITEOUT && 0
                if (dp->d_type == DT_WHT)
@@ -827,7 +750,7 @@ mem1:                               saved_errno = errno;
                                p->fts_info = FTS_NSOK;
                        p->fts_accpath = cur->fts_accpath;
                } else if (nlinks == 0
-#if defined DT_DIR && defined _DIRENT_HAVE_D_TYPE /* FIXME */
+#if defined DT_DIR && defined _DIRENT_HAVE_D_TYPE
                           || (nostat &&
                               dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN)
 #endif
@@ -910,52 +833,6 @@ mem1:                              saved_errno = errno;
        return (head);
 }
 
-struct known_object
-{
-  dev_t dev;
-  ino_t ino;
-  FTSENT *fts_ent;
-};
-
-static int
-object_compare (const void *p1, const void *p2)
-{
-  /* We don't need a sophisticated and useful comparison.  We are only
-     interested in equality.  However, we must be careful not to
-     accidentally compare `holes' in the structure.  */
-  const struct known_object *kp1 = p1, *kp2 = p2;
-  int cmp1;
-  cmp1 = (kp1->ino > kp2->ino) - (kp1->ino < kp2->ino);
-  if (cmp1 != 0)
-    return cmp1;
-  return (kp1->dev > kp2->dev) - (kp1->dev < kp2->dev);
-}
-
-
-static inline int
-add_object (FTS *fts, FTSENT *data, struct stat *st)
-{
-  struct known_object *newp = malloc (sizeof (struct known_object));
-  if (newp == NULL)
-    return -1;
-  newp->dev = st->st_dev;
-  newp->ino = st->st_ino;
-  newp->fts_ent = data;
-  return __tsearch (newp, &fts->fts_dir_info, object_compare) ? 0 : -1;
-}
-
-
-static inline FTSENT *
-find_object (FTS *fts, struct stat *st)
-{
-  struct known_object obj;
-  struct known_object const *t;
-  obj.dev = st->st_dev;
-  obj.ino = st->st_ino;
-  t = __tfind (&obj, &fts->fts_dir_info, object_compare);
-  return t ? t->fts_ent : NULL;
-}
-
 static u_short
 internal_function
 fts_stat(sp, p, follow)
@@ -963,6 +840,9 @@ fts_stat(sp, p, follow)
        register FTSENT *p;
        int follow;
 {
+       register FTSENT *t;
+       register dev_t dev;
+       register ino_t ino;
        struct stat *sbp, sb;
        int saved_errno;
 
@@ -1002,7 +882,6 @@ err:               memset(sbp, 0, sizeof(struct stat));
        }
 
        if (S_ISDIR(sbp->st_mode)) {
-               register FTSENT *t;
                /*
                 * Set the device/inode.  Used to find cycles and check for
                 * crossing mount points.  Also remember the link count, used
@@ -1010,29 +889,25 @@ err:             memset(sbp, 0, sizeof(struct stat));
                 * understood that these fields are only referenced if fts_info
                 * is set to FTS_D.
                 */
-               p->fts_dev = sbp->st_dev;
-               p->fts_ino = sbp->st_ino;
+               dev = p->fts_dev = sbp->st_dev;
+               ino = p->fts_ino = sbp->st_ino;
                p->fts_nlink = sbp->st_nlink;
 
                if (ISDOT(p->fts_name))
                        return (FTS_DOT);
 
                /*
-                 FIXME
                 * Cycle detection is done by brute force when the directory
                 * is first encountered.  If the tree gets deep enough or the
                 * number of symbolic links to directories is high enough,
                 * something faster might be worthwhile.
                 */
-               if ((t = find_object (sp, sbp))) {
-                       p->fts_cycle = t;
-                       return (FTS_DC);
-               }
-
-               /* Remember the object, ignoring any failure.  If we're running
-                  out of memory, detecting cycles isn't a high priority.  */
-               add_object (sp, p, sbp);
-
+               for (t = p->fts_parent;
+                   t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent)
+                       if (ino == t->fts_ino && dev == t->fts_dev) {
+                               p->fts_cycle = t;
+                               return (FTS_DC);
+                       }
                return (FTS_D);
        }
        if (S_ISLNK(sbp->st_mode))
@@ -1154,7 +1029,7 @@ fts_palloc(sp, more)
         * a signed int but in an FTSENT it is an unsigned short.
         * We limit fts_pathlen to USHRT_MAX to be safe in both cases.
         */
-       if (sp->fts_pathlen < 0 || sp->fts_pathlen >= INT_MAX) {
+       if (sp->fts_pathlen < 0 || sp->fts_pathlen >= USHRT_MAX) {
                if (sp->fts_path) {
                        free(sp->fts_path);
                        sp->fts_path = NULL;
@@ -1186,7 +1061,7 @@ fts_padjust(sp, head)
        FTSENT *p;
        char *addr = sp->fts_path;
 
-#define ADJUST(p) do {                                                 \
+#define        ADJUST(p) do {                                                  \
        if ((p)->fts_accpath != (p)->fts_name) {                        \
                (p)->fts_accpath =                                      \
                    (char *)addr + ((p)->fts_accpath - (p)->fts_path);  \
@@ -1231,14 +1106,14 @@ fts_safe_changedir(sp, p, fd, path)
        const char *path;
 {
        int ret, oerrno, newfd;
-       struct stat sb;
+       struct stat64 sb;
 
        newfd = fd;
        if (ISSET(FTS_NOCHDIR))
                return (0);
        if (fd < 0 && (newfd = __open(path, O_RDONLY, 0)) < 0)
                return (-1);
-       if (fstat(newfd, &sb)) {
+       if (__fxstat64(_STAT_VER, newfd, &sb)) {
                ret = -1;
                goto bail;
        }
index 03f621bf693644e899fc046f23576b7377d237f1..a22c7bb9ca06089d77059e094f965683d7f6712c 100644 (file)
  */
 
 #ifndef        _FTS_H
-# define _FTS_H 1
+#define        _FTS_H 1
+
+#include <features.h>
+#include <sys/types.h>
+
+/* The fts interface is incompatible with the LFS interface which
+   transparently uses the 64-bit file access functions.  */
+#ifdef __USE_FILE_OFFSET64
+# error "<fts.h> cannot be used with -D_FILE_OFFSET_BITS==64"
+#endif
 
-# include <features.h>
-# include <sys/types.h>
 
 typedef struct {
        struct _ftsent *fts_cur;        /* current node */
@@ -46,22 +53,19 @@ typedef struct {
        int fts_nitems;                 /* elements in the sort array */
        int (*fts_compar) (const void *, const void *); /* compare fn */
 
-# define FTS_COMFOLLOW 0x0001          /* follow command line symlinks */
-# define FTS_LOGICAL   0x0002          /* logical walk */
-# define FTS_NOCHDIR   0x0004          /* don't change directories */
-# define FTS_NOSTAT    0x0008          /* don't get stat info */
-# define FTS_PHYSICAL  0x0010          /* physical walk */
-# define FTS_SEEDOT    0x0020          /* return dot and dot-dot */
-# define FTS_XDEV      0x0040          /* don't cross devices */
-# define FTS_WHITEOUT  0x0080          /* return whiteout information */
-# define FTS_OPTIONMASK        0x00ff          /* valid user option mask */
-
-# define FTS_NAMEONLY  0x0100          /* (private) child names only */
-# define FTS_STOP      0x0200          /* (private) unrecoverable error */
+#define        FTS_COMFOLLOW   0x0001          /* follow command line symlinks */
+#define        FTS_LOGICAL     0x0002          /* logical walk */
+#define        FTS_NOCHDIR     0x0004          /* don't change directories */
+#define        FTS_NOSTAT      0x0008          /* don't get stat info */
+#define        FTS_PHYSICAL    0x0010          /* physical walk */
+#define        FTS_SEEDOT      0x0020          /* return dot and dot-dot */
+#define        FTS_XDEV        0x0040          /* don't cross devices */
+#define FTS_WHITEOUT   0x0080          /* return whiteout information */
+#define        FTS_OPTIONMASK  0x00ff          /* valid user option mask */
+
+#define        FTS_NAMEONLY    0x0100          /* (private) child names only */
+#define        FTS_STOP        0x0200          /* (private) unrecoverable error */
        int fts_options;                /* fts_open options, global flags */
-       /* Data structure in which to store the fingerprint
-          of each directory we've encountered.  */
-       void *fts_dir_info;
 } FTS;
 
 typedef struct _ftsent {
@@ -74,41 +78,41 @@ typedef struct _ftsent {
        char *fts_path;                 /* root path */
        int fts_errno;                  /* errno for this node */
        int fts_symfd;                  /* fd for symlink */
-       size_t fts_pathlen;             /* strlen(fts_path) */
+       u_short fts_pathlen;            /* strlen(fts_path) */
        u_short fts_namelen;            /* strlen(fts_name) */
 
        ino_t fts_ino;                  /* inode */
        dev_t fts_dev;                  /* device */
        nlink_t fts_nlink;              /* link count */
 
-# define FTS_ROOTPARENTLEVEL   -1
-# define FTS_ROOTLEVEL          0
+#define        FTS_ROOTPARENTLEVEL     -1
+#define        FTS_ROOTLEVEL            0
        short fts_level;                /* depth (-1 to N) */
 
-# define FTS_D          1              /* preorder directory */
-# define FTS_DC                 2              /* directory that causes cycles */
-# define FTS_DEFAULT    3              /* none of the above */
-# define FTS_DNR                4              /* unreadable directory */
-# define FTS_DOT                5              /* dot or dot-dot */
-# define FTS_DP                 6              /* postorder directory */
-# define FTS_ERR                7              /* error; errno is set */
-# define FTS_F          8              /* regular file */
-# define FTS_INIT       9              /* initialized only */
-# define FTS_NS                10              /* stat(2) failed */
-# define FTS_NSOK      11              /* no stat(2) requested */
-# define FTS_SL                12              /* symbolic link */
-# define FTS_SLNONE    13              /* symbolic link without target */
-# define FTS_W         14              /* whiteout object */
+#define        FTS_D            1              /* preorder directory */
+#define        FTS_DC           2              /* directory that causes cycles */
+#define        FTS_DEFAULT      3              /* none of the above */
+#define        FTS_DNR          4              /* unreadable directory */
+#define        FTS_DOT          5              /* dot or dot-dot */
+#define        FTS_DP           6              /* postorder directory */
+#define        FTS_ERR          7              /* error; errno is set */
+#define        FTS_F            8              /* regular file */
+#define        FTS_INIT         9              /* initialized only */
+#define        FTS_NS          10              /* stat(2) failed */
+#define        FTS_NSOK        11              /* no stat(2) requested */
+#define        FTS_SL          12              /* symbolic link */
+#define        FTS_SLNONE      13              /* symbolic link without target */
+#define FTS_W          14              /* whiteout object */
        u_short fts_info;               /* user flags for FTSENT structure */
 
-# define FTS_DONTCHDIR  0x01           /* don't chdir .. to the parent */
-# define FTS_SYMFOLLOW  0x02           /* followed a symlink to get here */
+#define        FTS_DONTCHDIR    0x01           /* don't chdir .. to the parent */
+#define        FTS_SYMFOLLOW    0x02           /* followed a symlink to get here */
        u_short fts_flags;              /* private flags for FTSENT structure */
 
-# define FTS_AGAIN      1              /* read node again */
-# define FTS_FOLLOW     2              /* follow symbolic link */
-# define FTS_NOINSTR    3              /* no instructions */
-# define FTS_SKIP       4              /* discard node */
+#define        FTS_AGAIN        1              /* read node again */
+#define        FTS_FOLLOW       2              /* follow symbolic link */
+#define        FTS_NOINSTR      3              /* no instructions */
+#define        FTS_SKIP         4              /* discard node */
        u_short fts_instr;              /* fts_set() instructions */
 
        struct stat *fts_statp;         /* stat(2) information */