summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2003-02-24 08:24:59 +0000
committerJim Meyering <jim@meyering.net>2003-02-24 08:24:59 +0000
commitf30cda6bd2ac0d103fdbd184f6cdb25e64aafb50 (patch)
tree29748a643c3b5c35ee8be1ac3c54d695e8e4fc01 /lib
parent74432ad178b5821eada57d2be8682dfe81ecc3ef (diff)
downloadcoreutils-f30cda6bd2ac0d103fdbd184f6cdb25e64aafb50.tar.xz
virgin copy from glibc
Diffstat (limited to 'lib')
-rw-r--r--lib/fts.c201
-rw-r--r--lib/fts_.h86
2 files changed, 83 insertions, 204 deletions
diff --git a/lib/fts.c b/lib/fts.c
index 05f4aa240..35374a094 100644
--- a/lib/fts.c
+++ b/lib/fts.c
@@ -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 */