diff options
author | Jim Meyering <jim@meyering.net> | 2003-02-24 08:24:59 +0000 |
---|---|---|
committer | Jim Meyering <jim@meyering.net> | 2003-02-24 08:24:59 +0000 |
commit | f30cda6bd2ac0d103fdbd184f6cdb25e64aafb50 (patch) | |
tree | 29748a643c3b5c35ee8be1ac3c54d695e8e4fc01 /lib | |
parent | 74432ad178b5821eada57d2be8682dfe81ecc3ef (diff) | |
download | coreutils-f30cda6bd2ac0d103fdbd184f6cdb25e64aafb50.tar.xz |
virgin copy from glibc
Diffstat (limited to 'lib')
-rw-r--r-- | lib/fts.c | 201 | ||||
-rw-r--r-- | lib/fts_.h | 86 |
2 files changed, 83 insertions, 204 deletions
@@ -27,96 +27,29 @@ * 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; } diff --git a/lib/fts_.h b/lib/fts_.h index 03f621bf6..a22c7bb9c 100644 --- a/lib/fts_.h +++ b/lib/fts_.h @@ -30,10 +30,17 @@ */ #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 */ |