This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCHv2 1/2] realpath: allow // to be handled specially


Part 1 of fixes for BZ #10635.

POSIX states that //path may be distinct from /path; while
GNU/Linux does not make this distinction, the code for
canonicalize is copied via gnulib to other platforms (such
as cygwin) where this makes a difference in the behavior of
realpath.

* stdlib/canonicalize.c (__realpath): Add and honor
DOUBLE_SLASH_IS_DISTINCT_ROOT.
---
 ChangeLog             |  6 ++++++
 stdlib/canonicalize.c | 30 ++++++++++++++++++++++++++----
 2 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 55bcf08..3336c10 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2013-10-01  Eric Blake  <eblake@redhat.com>
+
+	realpath: allow // to be handled specially
+	* stdlib/canonicalize.c (__realpath): Add and honor
+	DOUBLE_SLASH_IS_DISTINCT_ROOT.
+
 2013-09-30  Petr Machata  <pmachata@redhat.com>

 	* elf/elf.h (R_AARCH64_ABS16): New macro.
diff --git a/stdlib/canonicalize.c b/stdlib/canonicalize.c
index 784c978..5a52f06 100644
--- a/stdlib/canonicalize.c
+++ b/stdlib/canonicalize.c
@@ -28,6 +28,11 @@
 #include <eloop-threshold.h>
 #include <shlib-compat.h>

+/* Define this to 1 if you want realpath to honor leading //.  */
+#ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
+# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
+#endif
+
 /* Return the canonical absolute name of file NAME.  A canonical name
    does not contain any `.', `..' components nor any repeated path
    separators ('/') or symlinks.  All path components must exist.  If
@@ -96,6 +101,8 @@ __realpath (const char *name, char *resolved)
     {
       rpath[0] = '/';
       dest = rpath + 1;
+      if (DOUBLE_SLASH_IS_DISTINCT_ROOT && name[1] == '/')
+	*dest++ = '/';
     }

   for (start = end = name; *start; start = end)
@@ -120,6 +127,9 @@ __realpath (const char *name, char *resolved)
 	  /* Back up to previous component, ignore if at root already.  */
 	  if (dest > rpath + 1)
 	    while ((--dest)[-1] != '/');
+	  if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1
+	      && *dest == '/')
+	    dest++;
 	}
       else
 	{
@@ -192,11 +202,21 @@ __realpath (const char *name, char *resolved)
 	      name = end = memcpy (extra_buf, buf, n);

 	      if (buf[0] == '/')
-		dest = rpath + 1;	/* It's an absolute symlink */
+		{
+		  dest = rpath + 1;	/* It's an absolute symlink */
+		  if (DOUBLE_SLASH_IS_DISTINCT_ROOT && buf[1] == '/')
+		    *dest++ = '/';
+		}
 	      else
-		/* Back up to previous component, ignore if at root already: */
-		if (dest > rpath + 1)
-		  while ((--dest)[-1] != '/');
+		{
+		  /* Back up to previous component, ignore if at root
+		     already: */
+		  if (dest > rpath + 1)
+		    while ((--dest)[-1] != '/');
+		  if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1
+		      && *dest == '/')
+		    dest++;
+		}
 	    }
 	  else if (!S_ISDIR (st.st_mode) && *end != '\0')
 	    {
@@ -207,6 +227,8 @@ __realpath (const char *name, char *resolved)
     }
   if (dest > rpath + 1 && dest[-1] == '/')
     --dest;
+  if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1 && *dest == '/')
+    dest++;
   *dest = '\0';

   assert (resolved == NULL || resolved == rpath);
-- 
1.8.3.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]