(validate_uparams): Fix typo
[gnulib.git] / lib / fts.c
index d3bef85..8666cff 100644 (file)
--- a/lib/fts.c
+++ b/lib/fts.c
@@ -1,6 +1,6 @@
 /* Traverse a file hierarchy.
 
-   Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -71,6 +71,10 @@ static char sccsid[] = "@(#)fts.c    8.6 (Berkeley) 8/14/94";
 #include <string.h>
 #include <unistd.h>
 
+#if ! _LIBC
+# include "lstat.h"
+#endif
+
 #if defined _LIBC
 # include <dirent.h>
 # define NAMLEN(dirent) _D_EXACT_NAMLEN (dirent)
@@ -111,15 +115,6 @@ static char sccsid[] = "@(#)fts.c  8.6 (Berkeley) 8/14/94";
 # 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
@@ -152,10 +147,9 @@ static bool enter_dir (FTS *fts, FTSENT *ent) { return true; }
 static void leave_dir (FTS *fts, FTSENT *ent) {}
 static bool setup_dir (FTS *fts) { return true; }
 static void free_dir (FTS *fts) {}
-static int fd_safer (int fd) { return fd; }
 #else
+# include "fcntl--.h"
 # include "fts-cycle.c"
-# include "unistd-safer.h"
 #endif
 
 #ifndef MAX
@@ -209,10 +203,7 @@ static int
 internal_function
 diropen (char const *dir)
 {
-  int fd = open (dir, O_RDONLY | O_DIRECTORY);
-  if (fd < 0)
-    fd = open (dir, O_WRONLY | O_DIRECTORY);
-  return fd;
+  return open (dir, O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NONBLOCK);
 }
 
 FTS *
@@ -250,8 +241,11 @@ fts_open (char * const *argv,
 #ifndef MAXPATHLEN
 # define MAXPATHLEN 1024
 #endif
-       if (! fts_palloc(sp, MAX(fts_maxarglen(argv), MAXPATHLEN)))
-               goto mem1;
+       {
+         size_t maxarglen = fts_maxarglen(argv);
+         if (! fts_palloc(sp, MAX(maxarglen, MAXPATHLEN)))
+                 goto mem1;
+       }
 
        /* Allocate/initialize root's parent. */
        if ((parent = fts_alloc(sp, "", 0)) == NULL)
@@ -530,6 +524,7 @@ next:       tmp = p;
                if (p->fts_level == FTS_ROOTLEVEL) {
                        if (FCHDIR(sp, sp->fts_rfd)) {
                                SET(FTS_STOP);
+                               sp->fts_cur = p;
                                return (NULL);
                        }
                        fts_load(sp, p);
@@ -700,7 +695,9 @@ fts_children (register FTS *sp, int instr)
                return (sp->fts_child = NULL);
        sp->fts_child = fts_build(sp, instr);
        if (fchdir(fd)) {
+               int saved_errno = errno;
                (void)close(fd);
+               __set_errno (saved_errno);
                return (NULL);
        }
        (void)close(fd);
@@ -1029,7 +1026,7 @@ fts_cross_check (FTS const *sp)
       struct Active_dir ad;
       ad.ino = t->fts_statp->st_ino;
       ad.dev = t->fts_statp->st_dev;
-      if ( ! hash_lookup (sp->active_dir_ht, &ad))
+      if ( ! hash_lookup (sp->fts_cycle.ht, &ad))
        printf ("ERROR: active dir, %s, not in tree\n", t->fts_path);
     }
 
@@ -1040,8 +1037,8 @@ fts_cross_check (FTS const *sp)
          || ent->fts_info == FTS_D))
     {
       struct Active_dir *ad;
-      for (ad = hash_get_first (sp->active_dir_ht); ad != NULL;
-          ad = hash_get_next (sp->active_dir_ht, ad))
+      for (ad = hash_get_first (sp->fts_cycle.ht); ad != NULL;
+          ad = hash_get_next (sp->fts_cycle.ht, ad))
        {
          find_matching_ancestor (ent, ad);
        }
@@ -1073,7 +1070,8 @@ fts_stat(FTS *sp, register FTSENT *p, bool follow)
        if (ISSET(FTS_LOGICAL) || follow) {
                if (stat(p->fts_accpath, sbp)) {
                        saved_errno = errno;
-                       if (!lstat(p->fts_accpath, sbp)) {
+                       if (errno == ENOENT
+                           && lstat(p->fts_accpath, sbp) == 0) {
                                __set_errno (0);
                                return (FTS_SLNONE);
                        }
@@ -1319,7 +1317,7 @@ fts_safe_changedir (FTS *sp, FTSENT *p, int fd, char const *dir)
        newfd = fd;
        if (ISSET(FTS_NOCHDIR))
                return (0);
-       if (fd < 0 && (newfd = fd_safer (diropen (dir))) < 0)
+       if (fd < 0 && (newfd = diropen (dir)) < 0)
                return (-1);
        if (fstat(newfd, &sb)) {
                ret = -1;