This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCHv2 1/2] realpath: allow // to be handled specially
- From: Eric Blake <eblake at redhat dot com>
- To: libc-alpha at sourceware dot org
- Date: Tue, 1 Oct 2013 14:22:53 -0600
- Subject: [PATCHv2 1/2] realpath: allow // to be handled specially
- Authentication-results: sourceware.org; auth=none
- References: <1380658974-28848-1-git-send-email-eblake at redhat dot com>
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