diff options
| -rw-r--r-- | include/ftw.h | 4 | ||||
| -rw-r--r-- | libc/misc/ftw/Makefile.in | 37 | ||||
| -rw-r--r-- | libc/misc/ftw/ftw.c | 1031 | ||||
| -rw-r--r-- | libc/misc/ftw/ftw64.c | 32 | 
4 files changed, 642 insertions, 462 deletions
| diff --git a/include/ftw.h b/include/ftw.h index b1f7e09cb..4bdff88c6 100644 --- a/include/ftw.h +++ b/include/ftw.h @@ -74,7 +74,7 @@ enum  # define FTW_CHDIR	FTW_CHDIR    FTW_DEPTH = 8		/* Report files in directory before directory itself.*/  # define FTW_DEPTH	FTW_DEPTH -# if 0 /* def __USE_GNU */ +# ifdef __USE_GNU    ,    FTW_ACTIONRETVAL = 16	/* Assume callback to return FTW_* values instead of  			   zero to continue and non-zero to terminate.  */ @@ -82,7 +82,7 @@ enum  # endif  }; -#if 0 /* def __USE_GNU */ +#ifdef __USE_GNU  /* Return values from callback functions.  */  enum  { diff --git a/libc/misc/ftw/Makefile.in b/libc/misc/ftw/Makefile.in index c2cabfa0e..6c0304bc8 100644 --- a/libc/misc/ftw/Makefile.in +++ b/libc/misc/ftw/Makefile.in @@ -5,36 +5,23 @@  # Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.  # -MSRC:=ftw.c -MOBJ:=ftw.o ftw64.o +SRC := ftw.c +ifeq ($(UCLIBC_HAS_LFS),y) +SRC += ftw64.c +endif -MISC_FTW_DIR:=$(top_srcdir)libc/misc/ftw -MISC_FTW_OUT:=$(top_builddir)libc/misc/ftw +MISC_FTW_DIR := $(top_srcdir)libc/misc/ftw +MISC_FTW_OUT := $(top_builddir)libc/misc/ftw -# ftw.c has to be rewritten to allow multi -MISC_FTW_NO_MULTI:=ftw64.o +MISC_FTW_SRC := $(patsubst %.c,$(MISC_FTW_DIR)/%.c,$(SRC)) +MISC_FTW_OBJ := $(patsubst %.c,$(MISC_FTW_OUT)/%.o,$(SRC)) -MISC_FTW_MSRC:=$(MISC_FTW_DIR)/$(MSRC) -MISC_FTW_MOBJ:=$(patsubst %.o,$(MISC_FTW_OUT)/%.o,$(MOBJ)) +libc-a-$(UCLIBC_HAS_FTW) += $(MISC_FTW_OBJ) +libc-so-$(UCLIBC_HAS_FTW) += $(MISC_FTW_OBJ:.o=.os) -MISC_FTW_DEF:=$(patsubst %,-DL_%,$(subst .o,,$(filter-out $(MISC_FTW_NO_MULTI),$(notdir $(MISC_FTW_MOBJ))))) +libc-multi-$(UCLIBC_HAS_FTW) += $(MISC_FTW_SRC) -MISC_FTW_OBJS:=$(MISC_FTW_MOBJ) - -$(MISC_FTW_OBJS): $(MISC_FTW_MSRC) -	$(compile.m) - -$(MISC_FTW_OBJS:.o=.os): $(MISC_FTW_MSRC) -	$(compile.m) - -libc-a-$(UCLIBC_HAS_FTW)+=$(MISC_FTW_OBJS) -libc-so-$(UCLIBC_HAS_FTW)+=$(MISC_FTW_OBJS:.o=.os) - -CFLAGS-multi-$(UCLIBC_HAS_FTW)+=$(MISC_FTW_DEF) -libc-multi-$(UCLIBC_HAS_FTW)+=$(MISC_FTW_MSRC) -libc-nomulti-$(UCLIBC_HAS_FTW)+=$(patsubst %.o,$(MISC_FTW_OUT)/%.o,$(MISC_FTW_NO_MULTI)) - -objclean-y+=misc_ftw_objclean +objclean-y += misc_ftw_objclean  misc_ftw_objclean:  	$(RM) $(MISC_FTW_OUT)/*.{o,os} diff --git a/libc/misc/ftw/ftw.c b/libc/misc/ftw/ftw.c index 8a6db98d3..fdea1c208 100644 --- a/libc/misc/ftw/ftw.c +++ b/libc/misc/ftw/ftw.c @@ -1,5 +1,5 @@  /* File tree walker functions. -   Copyright (C) 1996-2001, 2002, 2003 Free Software Foundation, Inc. +   Copyright (C) 1996-2003, 2004 Free Software Foundation, Inc.     This file is part of the GNU C Library.     Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. @@ -18,67 +18,68 @@     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA     02111-1307 USA.  */ -/* used by D_EXACT_NAMLEN */ -#define strlen __strlen +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif -#define mempcpy __mempcpy -#define stpcpy __stpcpy +#define _GNU_SOURCE +#define _XOPEN_SOURCE 500 +#include <features.h> +#ifdef __UCLIBC__ +#undef _LIBC +#define HAVE_DIRENT_H 1 +#define HAVE_SYS_PARAM_H 1 +#define HAVE_DECL_STPCPY 1 +#define HAVE_MEMPCPY 1 +#define dirfd __dirfd  #define tsearch __tsearch -#define tdestroy __tdestroy  #define tfind __tfind -#define fchdir __fchdir -#define chdir __chdir -#define dirfd __dirfd +#define tdestroy __tdestroy  #define getcwd __getcwd +#define chdir __chdir +#define fchdir __fchdir +#define mempcpy __mempcpy  #define opendir __opendir  #define closedir __closedir - -#define _GNU_SOURCE -#include <features.h> - -#if defined (__UCLIBC_HAS_LFS__) && defined L_ftw64 -#ifndef L_ftw -#define L_ftw +#define stpcpy __stpcpy  #endif -/* If Large file support is enabled, transparently remap - * things to use the 64-bit interfaces */ -#if defined _FILE_OFFSET_BITS && _FILE_OFFSET_BITS != 64  -#undef _FILE_OFFSET_BITS -#define	_FILE_OFFSET_BITS   64 -#endif -#ifndef __USE_LARGEFILE64 -# define __USE_LARGEFILE64  1 -#endif -#ifndef __USE_FILE_OFFSET64 -# define __USE_FILE_OFFSET64  1 +#if __GNUC__ +# define alloca __builtin_alloca +#else +# if HAVE_ALLOCA_H +#  include <alloca.h> +# else +#  ifdef _AIX + #  pragma alloca +#  else +char *alloca (); +#  endif +# endif  #endif -#define FTW_NAME ftw64 -#define NFTW_NAME nftw64 -#define INO_T ino64_t -#define STAT stat64 -#define LSTAT __lstat64 -#define XSTAT __stat64 -#define FTW_FUNC_T __ftw64_func_t -#define NFTW_FUNC_T __nftw64_func_t -#define __readdir __readdir64 +#if defined _LIBC +# include <dirent.h> +# define NAMLEN(dirent) _D_EXACT_NAMLEN (dirent)  #else -#undef __stat -#undef __lstat -#define FTW_NAME ftw -#define NFTW_NAME nftw -#define INO_T ino_t -#define STAT stat -#define LSTAT __lstat -#define XSTAT __stat -#define FTW_FUNC_T __ftw_func_t -#define NFTW_FUNC_T __nftw_func_t +# 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 -#ifdef L_ftw - -#include <alloca.h>  #include <errno.h>  #include <ftw.h>  #include <limits.h> @@ -86,14 +87,100 @@  #include <stdlib.h>  #include <string.h>  #include <unistd.h> -#include <sys/param.h> -#include <sys/stat.h> +#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 + +#if ! _LIBC && !HAVE_DECL_STPCPY && !defined stpcpy +char *stpcpy (); +#endif + +#if ! _LIBC && ! defined HAVE_MEMPCPY && ! defined mempcpy +/* Be CAREFUL that there are no side effects in N.  */ +# define mempcpy(D, S, N) ((void *) ((char *) memcpy (D, S, N) + (N))) +#endif + +/* #define NDEBUG 1 */  #include <assert.h> -#include <dirent.h> -#if 1 /*ndef L_ftw64*/ +#if !defined _LIBC && !defined __UCLIBC__ +# undef __chdir +# define __chdir chdir +# undef __closedir +# define __closedir closedir +# undef __fchdir +# define __fchdir fchdir +# ifndef __UCLIBC__ +# undef __getcwd +# define __getcwd(P, N) xgetcwd () +extern char *xgetcwd (void); +# endif +# undef __mempcpy +# define __mempcpy mempcpy +# undef __opendir +# define __opendir opendir +# undef __readdir64 +# define __readdir64 readdir +# undef __stpcpy +# define __stpcpy stpcpy +# undef __tdestroy +# define __tdestroy tdestroy +# undef __tfind +# define __tfind tfind +# undef __tsearch +# define __tsearch tsearch +# undef internal_function +# define internal_function /* empty */ +# undef dirent64 +# define dirent64 dirent +# undef MAX +# define MAX(a, b) ((a) > (b) ? (a) : (b)) +#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 && !defined __UCLIBC__ +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 + +/* Support for the LFS API version.  */ +#ifndef FTW_NAME +# define FTW_NAME ftw +# define NFTW_NAME nftw +# define NFTW_OLD_NAME __old_nftw +# define NFTW_NEW_NAME __new_nftw +# define INO_T ino_t +# define STAT stat +# ifdef _LIBC +#  define LXSTAT __lxstat +#  define XSTAT __xstat +# else +#  ifdef __UCLIBC__ +#    define LXSTAT(V,f,sb) __lstat(f,sb) +#    define XSTAT(V,f,sb) __stat(f,sb) +#    define __readdir64 __readdir +#    define dirent64 dirent +#  else +#  define LXSTAT(V,f,sb) lstat (f,sb) +#  define XSTAT(V,f,sb) stat (f,sb) +#  endif +# endif +# define FTW_FUNC_T __ftw_func_t +# define NFTW_FUNC_T __nftw_func_t  extern struct dirent *__readdir (DIR *__dirp) __nonnull ((1)) attribute_hidden; -#else +# else  extern struct dirent64 *__readdir64 (DIR *__dirp) __nonnull ((1)) attribute_hidden;  #endif @@ -107,48 +194,48 @@ extern struct dirent64 *__readdir64 (DIR *__dirp) __nonnull ((1)) attribute_hidd  struct dir_data  { -    DIR *stream; -    char *content; +  DIR *stream; +  char *content;  };  struct known_object  { -    dev_t dev; -    INO_T ino; +  dev_t dev; +  INO_T ino;  };  struct ftw_data  { -    /* Array with pointers to open directory streams.  */ -    struct dir_data **dirstreams; -    size_t actdir; -    size_t maxdir; +  /* Array with pointers to open directory streams.  */ +  struct dir_data **dirstreams; +  size_t actdir; +  size_t maxdir; -    /* Buffer containing name of currently processed object.  */ -    char *dirbuf; -    size_t dirbufsize; +  /* Buffer containing name of currently processed object.  */ +  char *dirbuf; +  size_t dirbufsize; -    /* Passed as fourth argument to `nftw' callback.  The `base' member -       tracks the content of the `dirbuf'.  */ -    struct FTW ftw; +  /* Passed as fourth argument to `nftw' callback.  The `base' member +     tracks the content of the `dirbuf'.  */ +  struct FTW ftw; -    /* Flags passed to `nftw' function.  0 for `ftw'.  */ -    int flags; +  /* Flags passed to `nftw' function.  0 for `ftw'.  */ +  int flags; -    /* Conversion array for flag values.  It is the identity mapping for -       `nftw' calls, otherwise it maps the values to those known by -       `ftw'.  */ -    const int *cvt_arr; +  /* Conversion array for flag values.  It is the identity mapping for +     `nftw' calls, otherwise it maps the values to those known by +     `ftw'.  */ +  const int *cvt_arr; -    /* Callback function.  We always use the `nftw' form.  */ -    NFTW_FUNC_T func; +  /* Callback function.  We always use the `nftw' form.  */ +  NFTW_FUNC_T func; -    /* Device of starting point.  Needed for FTW_MOUNT.  */ -    dev_t dev; +  /* Device of starting point.  Needed for FTW_MOUNT.  */ +  dev_t dev; -    /* Data structure for keeping fingerprints of already processed -       object.  This is needed when not using FTW_PHYS.  */ -    void *known_objects; +  /* Data structure for keeping fingerprints of already processed +     object.  This is needed when not using FTW_PHYS.  */ +  void *known_objects;  }; @@ -156,52 +243,54 @@ struct ftw_data     as `ftw', map each flag to the subset of values used by `ftw'.  */  static const int nftw_arr[] =  { -    FTW_F, FTW_D, FTW_DNR, FTW_NS, FTW_SL, FTW_DP, FTW_SLN +  FTW_F, FTW_D, FTW_DNR, FTW_NS, FTW_SL, FTW_DP, FTW_SLN  };  static const int ftw_arr[] =  { -    FTW_F, FTW_D, FTW_DNR, FTW_NS, FTW_F, FTW_D, FTW_NS +  FTW_F, FTW_D, FTW_DNR, FTW_NS, FTW_F, FTW_D, FTW_NS  }; +  /* Forward declarations of local functions.  */ -static int ftw_dir (struct ftw_data *data, struct STAT *st) internal_function; +static int ftw_dir (struct ftw_data *data, struct STAT *st, +		    struct dir_data *old_dir) internal_function;  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); +  /* 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 (struct ftw_data *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; -    return tsearch (newp, &data->known_objects, object_compare) ? 0 : -1; +  struct known_object *newp = malloc (sizeof (struct known_object)); +  if (newp == NULL) +    return -1; +  newp->dev = st->st_dev; +  newp->ino = st->st_ino; +  return __tsearch (newp, &data->known_objects, object_compare) ? 0 : -1;  }  static inline int  find_object (struct ftw_data *data, struct STAT *st)  { -    struct known_object obj; -    obj.dev = st->st_dev; -    obj.ino = st->st_ino; -    return tfind (&obj, &data->known_objects, object_compare) != NULL; +  struct known_object obj; +  obj.dev = st->st_dev; +  obj.ino = st->st_ino; +  return __tfind (&obj, &data->known_objects, object_compare) != NULL;  } @@ -209,465 +298,537 @@ static inline int  __attribute ((always_inline))  open_dir_stream (struct ftw_data *data, struct dir_data *dirp)  { -    int result = 0; +  int result = 0; -    if (data->dirstreams[data->actdir] != NULL) +  if (data->dirstreams[data->actdir] != NULL)      { -	/* Oh, oh.  We must close this stream.  Get all remaining -	   entries and store them as a list in the `content' member of -	   the `struct dir_data' variable.  */ -	size_t bufsize = 1024; -	char *buf = malloc (bufsize); - -	if (buf == NULL) -	    result = -1; -	else +      /* Oh, oh.  We must close this stream.  Get all remaining +	 entries and store them as a list in the `content' member of +	 the `struct dir_data' variable.  */ +      size_t bufsize = 1024; +      char *buf = malloc (bufsize); + +      if (buf == NULL) +	result = -1; +      else  	{ -	    DIR *st = data->dirstreams[data->actdir]->stream; -	    struct dirent *d; -	    size_t actsize = 0; +	  DIR *st = data->dirstreams[data->actdir]->stream; +	  struct dirent64 *d; +	  size_t actsize = 0; -	    while ((d = __readdir (st)) != NULL) +	  while ((d = __readdir64 (st)) != NULL)  	    { -		size_t this_len = _D_EXACT_NAMLEN (d); -		if (actsize + this_len + 2 >= bufsize) +	      size_t this_len = NAMLEN (d); +	      if (actsize + this_len + 2 >= bufsize)  		{ -		    char *newp; -		    bufsize += MAX (1024, 2 * this_len); -		    newp = (char *) realloc (buf, bufsize); -		    if (newp == NULL) +		  char *newp; +		  bufsize += MAX (1024, 2 * this_len); +		  newp = (char *) realloc (buf, bufsize); +		  if (newp == NULL)  		    { -			/* No more memory.  */ -			int save_err = errno; -			free (buf); -			__set_errno (save_err); -			result = -1; -			break; +		      /* No more memory.  */ +		      int save_err = errno; +		      free (buf); +		      __set_errno (save_err); +		      result = -1; +		      break;  		    } -		    buf = newp; +		  buf = newp;  		} -		*((char *) mempcpy (buf + actsize, d->d_name, this_len)) -		    = '\0'; -		actsize += this_len + 1; +	      *((char *) __mempcpy (buf + actsize, d->d_name, this_len)) +		= '\0'; +	      actsize += this_len + 1;  	    } -	    /* Terminate the list with an additional NUL byte.  */ -	    buf[actsize++] = '\0'; +	  /* Terminate the list with an additional NUL byte.  */ +	  buf[actsize++] = '\0'; -	    /* Shrink the buffer to what we actually need.  */ -	    data->dirstreams[data->actdir]->content = realloc (buf, actsize); -	    if (data->dirstreams[data->actdir]->content == NULL) +	  /* Shrink the buffer to what we actually need.  */ +	  data->dirstreams[data->actdir]->content = realloc (buf, actsize); +	  if (data->dirstreams[data->actdir]->content == NULL)  	    { -		int save_err = errno; -		free (buf); -		__set_errno (save_err); -		result = -1; +	      int save_err = errno; +	      free (buf); +	      __set_errno (save_err); +	      result = -1;  	    } -	    else +	  else  	    { -		closedir (st); -		data->dirstreams[data->actdir]->stream = NULL; -		data->dirstreams[data->actdir] = NULL; +	      __closedir (st); +	      data->dirstreams[data->actdir]->stream = NULL; +	      data->dirstreams[data->actdir] = NULL;  	    }  	}      } -    /* Open the new stream.  */ -    if (result == 0) +  /* Open the new stream.  */ +  if (result == 0)      { -	const char *name = ((data->flags & FTW_CHDIR) -		? data->dirbuf + data->ftw.base: data->dirbuf); -	assert (data->dirstreams[data->actdir] == NULL); - -	dirp->stream = opendir (name); -	if (dirp->stream == NULL) -	    result = -1; -	else +      const char *name = ((data->flags & FTW_CHDIR) +			  ? data->dirbuf + data->ftw.base: data->dirbuf); +      assert (data->dirstreams[data->actdir] == NULL); + +      dirp->stream = __opendir (name); +      if (dirp->stream == NULL) +	result = -1; +      else  	{ -	    dirp->content = NULL; -	    data->dirstreams[data->actdir] = dirp; +	  dirp->content = NULL; +	  data->dirstreams[data->actdir] = dirp; -	    if (++data->actdir == data->maxdir) -		data->actdir = 0; +	  if (++data->actdir == data->maxdir) +	    data->actdir = 0;  	}      } -    return result; +  return result;  }  static int  internal_function -process_entry (struct ftw_data *data, struct dir_data *dir, const char *name, size_t namlen) +process_entry (struct ftw_data *data, struct dir_data *dir, const char *name, +	       size_t namlen)  { -    struct STAT st; -    int result = 0; -    int flag = 0; -    size_t new_buflen; - -    if (name[0] == '.' && (name[1] == '\0' -		|| (name[1] == '.' && name[2] == '\0'))) -	/* Don't process the "." and ".." entries.  */ -	return 0; - -    new_buflen = data->ftw.base + namlen + 2; -    if (data->dirbufsize < new_buflen) +  struct STAT st; +  int result = 0; +  int flag = 0; +  size_t new_buflen; + +  if (name[0] == '.' && (name[1] == '\0' +			 || (name[1] == '.' && name[2] == '\0'))) +    /* Don't process the "." and ".." entries.  */ +    return 0; + +  new_buflen = data->ftw.base + namlen + 2; +  if (data->dirbufsize < new_buflen)      { -	/* Enlarge the buffer.  */ -	char *newp; - -	data->dirbufsize = 2 * new_buflen; -	newp = (char *) realloc (data->dirbuf, data->dirbufsize); -	if (newp == NULL) -	    return -1; -	data->dirbuf = newp; +      /* Enlarge the buffer.  */ +      char *newp; + +      data->dirbufsize = 2 * new_buflen; +      newp = (char *) realloc (data->dirbuf, data->dirbufsize); +      if (newp == NULL) +	return -1; +      data->dirbuf = newp;      } -    *((char *) mempcpy (data->dirbuf + data->ftw.base, name, namlen)) = '\0'; +  *((char *) __mempcpy (data->dirbuf + data->ftw.base, name, namlen)) = '\0'; -    if ((data->flags & FTW_CHDIR) == 0) -	name = data->dirbuf; +  if ((data->flags & FTW_CHDIR) == 0) +    name = data->dirbuf; -    if (((data->flags & FTW_PHYS) -		? LSTAT (name, &st) -		: XSTAT (name, &st)) < 0) +  if (((data->flags & FTW_PHYS) +       ? LXSTAT (_STAT_VER, name, &st) +       : XSTAT (_STAT_VER, name, &st)) < 0)      { -	if (errno != EACCES && errno != ENOENT) -	    result = -1; -	else if (!(data->flags & FTW_PHYS) -		&& LSTAT (name, &st) == 0 -		&& S_ISLNK (st.st_mode)) -	    flag = FTW_SLN; -	else -	    flag = FTW_NS; +      if (errno != EACCES && errno != ENOENT) +	result = -1; +      else if (!(data->flags & FTW_PHYS) +	       && LXSTAT (_STAT_VER, name, &st) == 0 +	       && S_ISLNK (st.st_mode)) +	flag = FTW_SLN; +      else +	flag = FTW_NS;      } -    else +  else      { -	if (S_ISDIR (st.st_mode)) -	    flag = FTW_D; -	else if (S_ISLNK (st.st_mode)) -	    flag = FTW_SL; -	else -	    flag = FTW_F; +      if (S_ISDIR (st.st_mode)) +	flag = FTW_D; +      else if (S_ISLNK (st.st_mode)) +	flag = FTW_SL; +      else +	flag = FTW_F;      } -    if (result == 0 -	    && (flag == FTW_NS -		|| !(data->flags & FTW_MOUNT) || st.st_dev == data->dev)) +  if (result == 0 +      && (flag == FTW_NS +	  || !(data->flags & FTW_MOUNT) || st.st_dev == data->dev))      { -	if (flag == FTW_D) +      if (flag == FTW_D)  	{ -	    if ((data->flags & FTW_PHYS) -		    || (!find_object (data, &st) -			/* Remember the object.  */ -			&& (result = add_object (data, &st)) == 0)) -	    { -		result = ftw_dir (data, &st); - -		if (result == 0 && (data->flags & FTW_CHDIR)) -		{ -		    /* Change back to the parent directory.  */ -		    int done = 0; -		    if (dir->stream != NULL) -			if (fchdir (dirfd (dir->stream)) == 0) -			    done = 1; - -		    if (!done) -		    { -			if (data->ftw.base == 1) -			{ -			    if (chdir ("/") < 0) -				result = -1; -			} -			else -			    if (chdir ("..") < 0) -				result = -1; -		    } -		} -	    } +	  if ((data->flags & FTW_PHYS) +	      || (!find_object (data, &st) +		  /* Remember the object.  */ +		  && (result = add_object (data, &st)) == 0)) +	    result = ftw_dir (data, &st, dir);  	} -	else -	    result = (*data->func) (data->dirbuf, &st, data->cvt_arr[flag], -		    &data->ftw); +      else +	result = (*data->func) (data->dirbuf, &st, data->cvt_arr[flag], +				&data->ftw);      } -    return result; +  if ((data->flags & FTW_ACTIONRETVAL) && result == FTW_SKIP_SUBTREE) +    result = 0; + +  return result;  } +  static int +__attribute ((noinline))  internal_function -ftw_dir (struct ftw_data *data, struct STAT *st) +ftw_dir (struct ftw_data *data, struct STAT *st, struct dir_data *old_dir)  { -    struct dir_data dir; -    struct dirent *d; -    int previous_base = data->ftw.base; -    int result; -    char *startp; - -    /* Open the stream for this directory.  This might require that -       another stream has to be closed.  */ -    result = open_dir_stream (data, &dir); -    if (result != 0) +  struct dir_data dir; +  struct dirent64 *d; +  int previous_base = data->ftw.base; +  int result; +  char *startp; + +  /* Open the stream for this directory.  This might require that +     another stream has to be closed.  */ +  result = open_dir_stream (data, &dir); +  if (result != 0)      { -	if (errno == EACCES) -	    /* We cannot read the directory.  Signal this with a special flag.  */ -	    result = (*data->func) (data->dirbuf, st, FTW_DNR, &data->ftw); +      if (errno == EACCES) +	/* We cannot read the directory.  Signal this with a special flag.  */ +	result = (*data->func) (data->dirbuf, st, FTW_DNR, &data->ftw); -	return result; +      return result;      } -    /* First, report the directory (if not depth-first).  */ -    if (!(data->flags & FTW_DEPTH)) +  /* First, report the directory (if not depth-first).  */ +  if (!(data->flags & FTW_DEPTH))      { -	result = (*data->func) (data->dirbuf, st, FTW_D, &data->ftw); -	if (result != 0) -	    return result; +      result = (*data->func) (data->dirbuf, st, FTW_D, &data->ftw); +      if (result != 0) +	{ +	  int save_err; +fail: +	  save_err = errno; +	  __closedir (dir.stream); +	  __set_errno (save_err); + +	  if (data->actdir-- == 0) +	    data->actdir = data->maxdir - 1; +	  data->dirstreams[data->actdir] = NULL; +	  return result; +	}      } -    /* If necessary, change to this directory.  */ -    if (data->flags & FTW_CHDIR) +  /* If necessary, change to this directory.  */ +  if (data->flags & FTW_CHDIR)      { -	if (fchdir (dirfd (dir.stream)) < 0) +      if (__fchdir (dirfd (dir.stream)) < 0)  	{ -	    int save_err = errno; -	    closedir (dir.stream); -	    __set_errno (save_err); - -	    if (data->actdir-- == 0) -		data->actdir = data->maxdir - 1; -	    data->dirstreams[data->actdir] = NULL; - -	    return -1; +	  result = -1; +	  goto fail;  	}      } -    /* Next, update the `struct FTW' information.  */ -    ++data->ftw.level; -    startp = __strchr (data->dirbuf, '\0'); -    /* There always must be a directory name.  */ -    assert (startp != data->dirbuf); -    if (startp[-1] != '/') -	*startp++ = '/'; -    data->ftw.base = startp - data->dirbuf; +  /* Next, update the `struct FTW' information.  */ +  ++data->ftw.level; +  startp = __strchr (data->dirbuf, '\0'); +  /* There always must be a directory name.  */ +  assert (startp != data->dirbuf); +  if (startp[-1] != '/') +    *startp++ = '/'; +  data->ftw.base = startp - data->dirbuf; -    while (dir.stream != NULL && (d = __readdir (dir.stream)) != NULL) +  while (dir.stream != NULL && (d = __readdir64 (dir.stream)) != NULL)      { -	result = process_entry (data, &dir, d->d_name, _D_EXACT_NAMLEN (d)); -	if (result != 0) -	    break; +      result = process_entry (data, &dir, d->d_name, NAMLEN (d)); +      if (result != 0) +	break;      } -    if (dir.stream != NULL) +  if (dir.stream != NULL)      { -	/* The stream is still open.  I.e., we did not need more -	   descriptors.  Simply close the stream now.  */ -	int save_err = errno; +      /* The stream is still open.  I.e., we did not need more +	 descriptors.  Simply close the stream now.  */ +      int save_err = errno; -	assert (dir.content == NULL); +      assert (dir.content == NULL); -	closedir (dir.stream); -	__set_errno (save_err); +      __closedir (dir.stream); +      __set_errno (save_err); -	if (data->actdir-- == 0) -	    data->actdir = data->maxdir - 1; -	data->dirstreams[data->actdir] = NULL; +      if (data->actdir-- == 0) +	data->actdir = data->maxdir - 1; +      data->dirstreams[data->actdir] = NULL;      } -    else +  else      { -	int save_err; -	char *runp = dir.content; +      int save_err; +      char *runp = dir.content; -	while (result == 0 && *runp != '\0') +      while (result == 0 && *runp != '\0')  	{ -	    char *endp = __strchr (runp, '\0'); +	  char *endp = __strchr (runp, '\0'); -	    result = process_entry (data, &dir, runp, endp - runp); +	  result = process_entry (data, &dir, runp, endp - runp); -	    runp = endp + 1; +	  runp = endp + 1;  	} -	save_err = errno; -	free (dir.content); -	__set_errno (save_err); +      save_err = errno; +      free (dir.content); +      __set_errno (save_err);      } -    /* Prepare the return, revert the `struct FTW' information.  */ -    data->dirbuf[data->ftw.base - 1] = '\0'; -    --data->ftw.level; -    data->ftw.base = previous_base; +  if ((data->flags & FTW_ACTIONRETVAL) && result == FTW_SKIP_SIBLINGS) +    result = 0; + +  /* Prepare the return, revert the `struct FTW' information.  */ +  data->dirbuf[data->ftw.base - 1] = '\0'; +  --data->ftw.level; +  data->ftw.base = previous_base; -    /* Finally, if we process depth-first report the directory.  */ -    if (result == 0 && (data->flags & FTW_DEPTH)) -	result = (*data->func) (data->dirbuf, st, FTW_DP, &data->ftw); +  /* Finally, if we process depth-first report the directory.  */ +  if (result == 0 && (data->flags & FTW_DEPTH)) +    result = (*data->func) (data->dirbuf, st, FTW_DP, &data->ftw); + +  if (old_dir +      && (data->flags & FTW_CHDIR) +      && (result == 0 +	  || ((data->flags & FTW_ACTIONRETVAL) +	      && (result != -1 && result != FTW_STOP)))) +    { +      /* Change back to the parent directory.  */ +      int done = 0; +      if (old_dir->stream != NULL) +	if (__fchdir (dirfd (old_dir->stream)) == 0) +	  done = 1; -    return result; +      if (!done) +	{ +	  if (data->ftw.base == 1) +	    { +	      if (__chdir ("/") < 0) +		result = -1; +	    } +	  else +	    if (__chdir ("..") < 0) +	      result = -1; +	} +    } + +  return result;  }  static int +__attribute ((noinline))  internal_function -ftw_startup (const char *dir, int is_nftw, void *func, int descriptors, int flags) +ftw_startup (const char *dir, int is_nftw, void *func, int descriptors, +	     int flags)  { -    struct ftw_data data; -    struct STAT st; -    int result = 0; -    int save_err; -    char *cwd = NULL; -    char *cp; - -    /* First make sure the parameters are reasonable.  */ -    if (unlikely(dir==NULL || *dir=='\0')) { -	__set_errno (ENOENT); -	return -1; -    } -    if ((__strlen(dir)+1) > NAME_MAX) { -	__set_errno(ENAMETOOLONG); -	return -1; +  struct ftw_data data; +  struct STAT st; +  int result = 0; +  int save_err; +  char *cwd = NULL; +  char *cp; + +  /* First make sure the parameters are reasonable.  */ +  if (dir[0] == '\0') +    { +      __set_errno (ENOENT); +      return -1;      } -    data.maxdir = descriptors < 1 ? 1 : descriptors; -    data.actdir = 0; -    data.dirstreams = (struct dir_data **) alloca (data.maxdir -	    * sizeof (struct dir_data *)); -    __memset (data.dirstreams, '\0', data.maxdir * sizeof (struct dir_data *)); - -    /* PATH_MAX is always defined when we get here.  */ -    data.dirbufsize = MAX (2 * __strlen (dir), PATH_MAX); -    data.dirbuf = (char *) malloc (data.dirbufsize); -    if (data.dirbuf == NULL) -	return -1; -    cp = stpcpy (data.dirbuf, dir); -    /* Strip trailing slashes.  */ -    while (cp > data.dirbuf + 1 && cp[-1] == '/') -	--cp; -    *cp = '\0'; - -    data.ftw.level = 0; - -    /* Find basename.  */ -    while (cp > data.dirbuf && cp[-1] != '/') -	--cp; -    data.ftw.base = cp - data.dirbuf; - -    data.flags = flags; - -    /* This assignment might seem to be strange but it is what we want. -       The trick is that the first three arguments to the `ftw' and -       `nftw' callback functions are equal.  Therefore we can call in -       every case the callback using the format of the `nftw' version -       and get the correct result since the stack layout for a function -       call in C allows this.  */ -    data.func = (NFTW_FUNC_T) func; - -    /* Since we internally use the complete set of FTW_* values we need -       to reduce the value range before calling a `ftw' callback.  */ -    data.cvt_arr = is_nftw ? nftw_arr : ftw_arr; - -    /* No object known so far.  */ -    data.known_objects = NULL; - -    /* Now go to the directory containing the initial file/directory.  */ -    if (flags & FTW_CHDIR) +  data.maxdir = descriptors < 1 ? 1 : descriptors; +  data.actdir = 0; +  data.dirstreams = (struct dir_data **) alloca (data.maxdir +						 * sizeof (struct dir_data *)); +  __memset (data.dirstreams, '\0', data.maxdir * sizeof (struct dir_data *)); + +  /* PATH_MAX is always defined when we get here.  */ +  data.dirbufsize = MAX (2 * __strlen (dir), PATH_MAX); +  data.dirbuf = (char *) malloc (data.dirbufsize); +  if (data.dirbuf == NULL) +    return -1; +  cp = __stpcpy (data.dirbuf, dir); +  /* Strip trailing slashes.  */ +  while (cp > data.dirbuf + 1 && cp[-1] == '/') +    --cp; +  *cp = '\0'; + +  data.ftw.level = 0; + +  /* Find basename.  */ +  while (cp > data.dirbuf && cp[-1] != '/') +    --cp; +  data.ftw.base = cp - data.dirbuf; + +  data.flags = flags; + +  /* This assignment might seem to be strange but it is what we want. +     The trick is that the first three arguments to the `ftw' and +     `nftw' callback functions are equal.  Therefore we can call in +     every case the callback using the format of the `nftw' version +     and get the correct result since the stack layout for a function +     call in C allows this.  */ +  data.func = (NFTW_FUNC_T) func; + +  /* Since we internally use the complete set of FTW_* values we need +     to reduce the value range before calling a `ftw' callback.  */ +  data.cvt_arr = is_nftw ? nftw_arr : ftw_arr; + +  /* No object known so far.  */ +  data.known_objects = NULL; + +  /* Now go to the directory containing the initial file/directory.  */ +  if (flags & FTW_CHDIR)      { -	/* GNU extension ahead.  */ -	cwd =  getcwd (NULL, 0); -	if (cwd == NULL) -	    result = -1; -	else if (data.ftw.base > 0) +      /* GNU extension ahead.  */ +      cwd =  __getcwd (NULL, 0); +      if (cwd == NULL) +	result = -1; +      else if (data.ftw.base > 0)  	{ -	    /* Change to the directory the file is in.  In data.dirbuf -	       we have a writable copy of the file name.  Just NUL -	       terminate it for now and change the directory.  */ -	    if (data.ftw.base == 1) -		/* I.e., the file is in the root directory.  */ -		result = chdir ("/"); -	    else +	  /* Change to the directory the file is in.  In data.dirbuf +	     we have a writable copy of the file name.  Just NUL +	     terminate it for now and change the directory.  */ +	  if (data.ftw.base == 1) +	    /* I.e., the file is in the root directory.  */ +	    result = __chdir ("/"); +	  else  	    { -		char ch = data.dirbuf[data.ftw.base - 1]; -		data.dirbuf[data.ftw.base - 1] = '\0'; -		result = chdir (data.dirbuf); -		data.dirbuf[data.ftw.base - 1] = ch; +	      char ch = data.dirbuf[data.ftw.base - 1]; +	      data.dirbuf[data.ftw.base - 1] = '\0'; +	      result = __chdir (data.dirbuf); +	      data.dirbuf[data.ftw.base - 1] = ch;  	    }  	}      } -    /* Get stat info for start directory.  */ -    if (result == 0) +  /* Get stat info for start directory.  */ +  if (result == 0)      { -	const char *name = ((data.flags & FTW_CHDIR) -		? data.dirbuf + data.ftw.base -		: data.dirbuf); +      const char *name = ((data.flags & FTW_CHDIR) +			  ? data.dirbuf + data.ftw.base +			  : data.dirbuf); -	if (((flags & FTW_PHYS) -		    ? LSTAT (name, &st) -		    : XSTAT (name, &st)) < 0) +      if (((flags & FTW_PHYS) +	   ? LXSTAT (_STAT_VER, name, &st) +	   : XSTAT (_STAT_VER, name, &st)) < 0)  	{ -	    if (!(flags & FTW_PHYS) -		    && errno == ENOENT -		    && LSTAT (name, &st) == 0 -		    && S_ISLNK (st.st_mode)) -		result = (*data.func) (data.dirbuf, &st, data.cvt_arr[FTW_SLN], -			&data.ftw); -	    else -		/* No need to call the callback since we cannot say anything -		   about the object.  */ -		result = -1; +	  if (!(flags & FTW_PHYS) +	      && errno == ENOENT +	      && LXSTAT (_STAT_VER, name, &st) == 0 +	      && S_ISLNK (st.st_mode)) +	    result = (*data.func) (data.dirbuf, &st, data.cvt_arr[FTW_SLN], +				   &data.ftw); +	  else +	    /* No need to call the callback since we cannot say anything +	       about the object.  */ +	    result = -1;  	} -	else +      else  	{ -	    if (S_ISDIR (st.st_mode)) +	  if (S_ISDIR (st.st_mode))  	    { -		/* Remember the device of the initial directory in case -		   FTW_MOUNT is given.  */ -		data.dev = st.st_dev; +	      /* Remember the device of the initial directory in case +		 FTW_MOUNT is given.  */ +	      data.dev = st.st_dev; -		/* We know this directory now.  */ -		if (!(flags & FTW_PHYS)) -		    result = add_object (&data, &st); +	      /* We know this directory now.  */ +	      if (!(flags & FTW_PHYS)) +		result = add_object (&data, &st); -		if (result == 0) -		    result = ftw_dir (&data, &st); +	      if (result == 0) +		result = ftw_dir (&data, &st, NULL);  	    } -	    else +	  else  	    { -		int flag = S_ISLNK (st.st_mode) ? FTW_SL : FTW_F; +	      int flag = S_ISLNK (st.st_mode) ? FTW_SL : FTW_F; -		result = (*data.func) (data.dirbuf, &st, data.cvt_arr[flag], -			&data.ftw); +	      result = (*data.func) (data.dirbuf, &st, data.cvt_arr[flag], +				     &data.ftw);  	    }  	} + +      if ((flags & FTW_ACTIONRETVAL) +	  && (result == FTW_SKIP_SUBTREE || result == FTW_SKIP_SIBLINGS)) +	result = 0;      } -    /* Return to the start directory (if necessary).  */ -    if (cwd != NULL) +  /* Return to the start directory (if necessary).  */ +  if (cwd != NULL)      { -	int save_err = errno; -	chdir (cwd); -	free (cwd); -	__set_errno (save_err); +      int save_err = errno; +      __chdir (cwd); +      free (cwd); +      __set_errno (save_err);      } -    /* Free all memory.  */ -    save_err = errno; -    tdestroy (data.known_objects, free); -    free (data.dirbuf); -    __set_errno (save_err); +  /* Free all memory.  */ +  save_err = errno; +  __tdestroy (data.known_objects, free); +  free (data.dirbuf); +  __set_errno (save_err); -    return result; +  return result;  }  /* Entry points.  */ -int FTW_NAME (const char *path, FTW_FUNC_T func, int descriptors) +int +FTW_NAME (path, func, descriptors) +     const char *path; +     FTW_FUNC_T func; +     int descriptors;  { -    return ftw_startup (path, 0, func, descriptors, 0); +  return ftw_startup (path, 0, func, descriptors, 0);  } -int NFTW_NAME (const char *path, NFTW_FUNC_T func, int descriptors, int flags) +#ifndef _LIBC +int +NFTW_NAME (path, func, descriptors, flags) +     const char *path; +     NFTW_FUNC_T func; +     int descriptors; +     int flags;  { -    return ftw_startup (path, 1, func, descriptors, flags); +  return ftw_startup (path, 1, func, descriptors, flags);  } +#else + +#include <shlib-compat.h> + +int NFTW_NEW_NAME (const char *, NFTW_FUNC_T, int, int); + +int +NFTW_NEW_NAME (path, func, descriptors, flags) +     const char *path; +     NFTW_FUNC_T func; +     int descriptors; +     int flags; +{ +  if (flags +      & ~(FTW_PHYS | FTW_MOUNT | FTW_CHDIR | FTW_DEPTH | FTW_ACTIONRETVAL)) +    { +      __set_errno (EINVAL); +      return -1; +    } +  return ftw_startup (path, 1, func, descriptors, flags); +} + +versioned_symbol (libc, NFTW_NEW_NAME, NFTW_NAME, GLIBC_2_3_3); + +#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_3_3) + +/* Older nftw* version just ignored all unknown flags.  */ + +int NFTW_OLD_NAME (const char *, NFTW_FUNC_T, int, int); + +int +attribute_compat_text_section +NFTW_OLD_NAME (path, func, descriptors, flags) +     const char *path; +     NFTW_FUNC_T func; +     int descriptors; +     int flags; +{ +  flags &= (FTW_PHYS | FTW_MOUNT | FTW_CHDIR | FTW_DEPTH); +  return ftw_startup (path, 1, func, descriptors, flags); +} + +compat_symbol (libc, NFTW_OLD_NAME, NFTW_NAME, GLIBC_2_1); +#endif  #endif diff --git a/libc/misc/ftw/ftw64.c b/libc/misc/ftw/ftw64.c new file mode 100644 index 000000000..c4edd4d0a --- /dev/null +++ b/libc/misc/ftw/ftw64.c @@ -0,0 +1,32 @@ +/* File tree walker functions.  LFS version. +   Copyright (C) 1996, 1997, 1998, 2001 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#define FTW_NAME ftw64 +#define NFTW_NAME nftw64 +#define NFTW_OLD_NAME __old_nftw64 +#define NFTW_NEW_NAME __new_nftw64 +#define INO_T ino64_t +#define STAT stat64 +#define LXSTAT(V,f,sb) __lstat64(f,sb) +#define XSTAT(V,f,sb) __stat64(f,sb) +#define FTW_FUNC_T __ftw64_func_t +#define NFTW_FUNC_T __nftw64_func_t + +#include "ftw.c" | 
