[PATCH] Speed up realpath and fix EOVERFLOW bug

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[PATCH] Speed up realpath and fix EOVERFLOW bug

Paul Eggert
[BZ#24970]
* stdlib/canonicalize.c: Do not include <sys/stat.h>; no longer needed.
(__realpath): Use __readlink instead of __lxstat64 to determine
whether RPATH is a symbolic link.  This avoids an unnecessary
__lxstat64 when RPATH is a symbolic link and replaces __lxstat64
with __readlink when RPATH is not a symbolic link.  It also avoids
an unnecessary failure if __lxstat64 would fail with errno ==
EOVERFLOW due to timestamp or other integer overflow.  Remove
unnecessary S_ISDIR check, as the next time through the loop will
fail with errno == ENOTDIR as appropriate.
---
 stdlib/canonicalize.c | 28 +++++++++++-----------------
 1 file changed, 11 insertions(+), 17 deletions(-)

diff --git a/stdlib/canonicalize.c b/stdlib/canonicalize.c
index cbd885a3c5..cd2051d35f 100644
--- a/stdlib/canonicalize.c
+++ b/stdlib/canonicalize.c
@@ -21,7 +21,6 @@
 #include <string.h>
 #include <unistd.h>
 #include <limits.h>
-#include <sys/stat.h>
 #include <errno.h>
 #include <stddef.h>
 
@@ -98,9 +97,10 @@ __realpath (const char *name, char *resolved)
       dest = rpath + 1;
     }
 
+  char *buf = __alloca (path_max);
+
   for (start = end = name; *start; start = end)
     {
-      struct stat64 st;
       int n;
 
       /* Skip sequence of multiple path-separators.  */
@@ -158,12 +158,14 @@ __realpath (const char *name, char *resolved)
   dest = __mempcpy (dest, start, end - start);
   *dest = '\0';
 
-  if (__lxstat64 (_STAT_VER, rpath, &st) < 0)
-    goto error;
-
-  if (S_ISLNK (st.st_mode))
+  n = __readlink (rpath, buf, path_max);
+  if (n < 0)
+    {
+      if (errno != EINVAL)
+ goto error;
+    }
+  else
     {
-      char *buf = __alloca (path_max);
       size_t len;
 
       if (++num_links > __eloop_threshold ())
@@ -172,11 +174,6 @@ __realpath (const char *name, char *resolved)
   goto error;
  }
 
-      n = __readlink (rpath, buf, path_max - 1);
-      if (n < 0)
- goto error;
-      buf[n] = '\0';
-
       if (!extra_buf)
  extra_buf = __alloca (path_max);
 
@@ -187,6 +184,8 @@ __realpath (const char *name, char *resolved)
   goto error;
  }
 
+      buf[n] = '\0';
+
       /* Careful here, end may be a pointer into extra_buf... */
       memmove (&extra_buf[n], end, len + 1);
       name = end = memcpy (extra_buf, buf, n);
@@ -198,11 +197,6 @@ __realpath (const char *name, char *resolved)
  if (dest > rpath + 1)
   while ((--dest)[-1] != '/');
     }
-  else if (!S_ISDIR (st.st_mode) && *end != '\0')
-    {
-      __set_errno (ENOTDIR);
-      goto error;
-    }
  }
     }
   if (dest > rpath + 1 && dest[-1] == '/')
--
2.24.1