(NFTW_OLD_NAME, NFTW_NEW_NAME): Define.
authordrepper <drepper>
Fri, 7 Nov 2003 22:57:43 +0000 (22:57 +0000)
committerdrepper <drepper>
Fri, 7 Nov 2003 22:57:43 +0000 (22:57 +0000)
(ftw_dir, ftw_startup): Add __attribute ((noinline)).
(NFTW_OLD_NAME, NFTW_NEW_NAME): New functions.
(NFTW_NAME): Only define if !_LIBC, add versioned_symbol and compat_symbol.
(ftw_dir): Add old_dir argument.

Clear result if it was FTW_SKIP_SIBLINGS after processing all
dir entries.  Change cwd back if old_dir != NULL.
(process_entry): Adjust caller.  Don't change cwd back here.
Change FTW_SKIP_SUBTREE result to 0.
(ftw_startup): Adjust ftw_dir caller.
Clear result if it was FTW_SKIP_SUBTREE or FTW_SKIP_SIBLINGS.

io/ftw.c

index 6d5cedf..c4d2157 100644 (file)
--- a/io/ftw.c
+++ b/io/ftw.c
@@ -135,6 +135,8 @@ int rpl_lstat (const char *, struct stat *);
 #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
@@ -217,7 +219,8 @@ static const int ftw_arr[] =
 
 
 /* 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
@@ -415,43 +418,24 @@ process_entry (struct ftw_data *data, struct dir_data *dir, const char *name,
              || (!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;
-                   }
-               }
-           }
+           result = ftw_dir (data, &st, dir);
        }
       else
        result = (*data->func) (data->dirbuf, &st, data->cvt_arr[flag],
                                &data->ftw);
     }
 
+  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 dirent64 *d;
@@ -550,6 +534,9 @@ fail:
       __set_errno (save_err);
     }
 
+  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;
@@ -559,11 +546,37 @@ fail:
   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;
+
+      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)
@@ -683,7 +696,7 @@ ftw_startup (const char *dir, int is_nftw, void *func, int descriptors,
                result = add_object (&data, &st);
 
              if (result == 0)
-               result = ftw_dir (&data, &st);
+               result = ftw_dir (&data, &st, NULL);
            }
          else
            {
@@ -693,6 +706,10 @@ ftw_startup (const char *dir, int is_nftw, void *func, int descriptors,
                                     &data.ftw);
            }
        }
+
+      if ((flags & FTW_ACTIONRETVAL)
+         && (result == FTW_SKIP_SUBTREE || result == FTW_SKIP_SIBLINGS))
+       result = 0;
     }
 
   /* Return to the start directory (if necessary).  */
@@ -726,6 +743,7 @@ FTW_NAME (path, func, descriptors)
   return ftw_startup (path, 0, func, descriptors, 0);
 }
 
+#ifndef _LIBC
 int
 NFTW_NAME (path, func, descriptors, flags)
      const char *path;
@@ -735,3 +753,43 @@ NFTW_NAME (path, func, descriptors, flags)
 {
   return ftw_startup (path, 1, func, descriptors, flags);
 }
+#else
+
+#include <shlib-compat.h>
+
+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 (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