]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - io/ftw.c
Update copyright notices with scripts/update-copyrights
[thirdparty/glibc.git] / io / ftw.c
index 50303d9cd09d44cf45a2ddeb61f142206bb51689..b058b7465a24fcea9221f5436093365673b95cad 100644 (file)
--- a/io/ftw.c
+++ b/io/ftw.c
@@ -1,5 +1,5 @@
 /* File tree walker functions.
-   Copyright (C) 1996-2003, 2004, 2006 Free Software Foundation, Inc.
+   Copyright (C) 1996-2014 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
 
@@ -14,9 +14,8 @@
    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.  */
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
@@ -243,7 +242,7 @@ object_compare (const void *p1, const void *p2)
 }
 
 
-static inline int
+static int
 add_object (struct ftw_data *data, struct STAT *st)
 {
   struct known_object *newp = malloc (sizeof (struct known_object));
@@ -301,8 +300,7 @@ open_dir_stream (int *dfdp, struct ftw_data *data, struct dir_data *dirp)
                      int save_err = errno;
                      free (buf);
                      __set_errno (save_err);
-                     result = -1;
-                     break;
+                     return -1;
                    }
                  buf = newp;
                }
@@ -349,8 +347,17 @@ open_dir_stream (int *dfdp, struct ftw_data *data, struct dir_data *dirp)
        }
       else
        {
-         const char *name = ((data->flags & FTW_CHDIR)
-                             ? data->dirbuf + data->ftw.base: data->dirbuf);
+         const char *name;
+
+         if (data->flags & FTW_CHDIR)
+           {
+             name = data->dirbuf + data->ftw.base;
+             if (name[0] == '\0')
+               name = ".";
+           }
+         else
+           name = data->dirbuf;
+
          dirp->stream = __opendir (name);
        }
 
@@ -419,13 +426,22 @@ process_entry (struct ftw_data *data, struct dir_data *dir, const char *name,
     {
       if (errno != EACCES && errno != ENOENT)
        result = -1;
-      else if (!(data->flags & FTW_PHYS)
-              && (d_type == DT_LNK
-                  || (LXSTAT (_STAT_VER, name, &st) == 0
-                      && S_ISLNK (st.st_mode))))
+      else if (data->flags & FTW_PHYS)
+       flag = FTW_NS;
+      else if (d_type == DT_LNK)
        flag = FTW_SLN;
       else
-       flag = FTW_NS;
+       {
+         if (dir->streamfd != -1)
+           statres = FXSTATAT (_STAT_VER, dir->streamfd, name, &st,
+                               AT_SYMLINK_NOFOLLOW);
+         else
+           statres = LXSTAT (_STAT_VER, name, &st);
+         if (statres == 0 && S_ISLNK (st.st_mode))
+           flag = FTW_SLN;
+         else
+           flag = FTW_NS;
+       }
     }
   else
     {
@@ -517,7 +533,7 @@ fail:
 
   /* Next, update the `struct FTW' information.  */
   ++data->ftw.level;
-  startp = strchr (data->dirbuf, '\0');
+  startp = __rawmemchr (data->dirbuf, '\0');
   /* There always must be a directory name.  */
   assert (startp != data->dirbuf);
   if (startp[-1] != '/')
@@ -526,7 +542,11 @@ fail:
 
   while (dir.stream != NULL && (d = __readdir64 (dir.stream)) != NULL)
     {
-      result = process_entry (data, &dir, d->d_name, NAMLEN (d), d->d_type);
+      int d_type = DT_UNKNOWN;
+#ifdef _DIRENT_HAVE_D_TYPE
+      d_type = d->d_type;
+#endif
+      result = process_entry (data, &dir, d->d_name, NAMLEN (d), d_type);
       if (result != 0)
        break;
     }
@@ -713,9 +733,16 @@ ftw_startup (const char *dir, int is_nftw, void *func, int descriptors,
   /* 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;
+
+      if (data.flags & FTW_CHDIR)
+       {
+         name = data.dirbuf + data.ftw.base;
+         if (name[0] == '\0')
+           name = ".";
+       }
+      else
+       name = data.dirbuf;
 
       if (((flags & FTW_PHYS)
           ? LXSTAT (_STAT_VER, name, &st)
@@ -766,6 +793,7 @@ ftw_startup (const char *dir, int is_nftw, void *func, int descriptors,
     {
       int save_err = errno;
       __fchdir (cwdfd);
+      close_not_cancel_no_status (cwdfd);
       __set_errno (save_err);
     }
   else if (cwd != NULL)