* modules/canonicalize (Files): Add double-slash-root.m4.
* modules/canonicalize-lgpl (Files): Likewise.
* m4/canonicalize.m4 (gl_FUNC_CANONICALIZE_FILENAME_MODE)
(gl_CANONICALIZE_LGPL_SEPARATE): Add dependency.
* lib/canonicalize.c (DOUBLE_SLASH_IS_DISTINCT_ROOT): Provide
fallback definition.
(canonicalize_filename_mode): Use it to protect //.
* lib/canonicalize-lgpl.c (DOUBLE_SLASH_IS_DISTINCT_ROOT)
(__realpath): Likewise.
* tests/test-canonicalize.c (main): Test this.
* tests/test-canonicalize-lgpl.c (main): Likewise.
* modules/canonicalize-tests (Depends-on): Add same-inode.
* modules/canonicalize-lgpl-tests (Depends-on): Likewise.
Signed-off-by: Eric Blake <ebb9@byu.net>
2009-09-17 Eric Blake <ebb9@byu.net>
+ canonicalize, canonicalize-lgpl: honor // if distinct from /
+ * modules/canonicalize (Files): Add double-slash-root.m4.
+ * modules/canonicalize-lgpl (Files): Likewise.
+ * m4/canonicalize.m4 (gl_FUNC_CANONICALIZE_FILENAME_MODE)
+ (gl_CANONICALIZE_LGPL_SEPARATE): Add dependency.
+ * lib/canonicalize.c (DOUBLE_SLASH_IS_DISTINCT_ROOT): Provide
+ fallback definition.
+ (canonicalize_filename_mode): Use it to protect //.
+ * lib/canonicalize-lgpl.c (DOUBLE_SLASH_IS_DISTINCT_ROOT)
+ (__realpath): Likewise.
+ * tests/test-canonicalize.c (main): Test this.
+ * tests/test-canonicalize-lgpl.c (main): Likewise.
+ * modules/canonicalize-tests (Depends-on): Add same-inode.
+ * modules/canonicalize-lgpl-tests (Depends-on): Likewise.
+
canonicalize-lgpl: fix glibc bug with trailing slash
* m4/canonicalize-lgpl.m4: Move contents...
* m4/canonicalize.m4: ...here.
# endif
#endif
+#ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
+# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
+#endif
+
#if !FUNC_REALPATH_WORKS || defined _LIBC
/* Return the canonical absolute name of file NAME. A canonical name
does not contain any `.', `..' components nor any repeated path
{
rpath[0] = '/';
dest = rpath + 1;
+ if (DOUBLE_SLASH_IS_DISTINCT_ROOT && name[1] == '/')
+ *dest++ = '/';
}
for (start = end = name; *start; start = end)
/* 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
{
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')
{
}
if (dest > rpath + 1 && dest[-1] == '/')
--dest;
+ if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1 && *dest == '/')
+ dest++;
*dest = '\0';
if (extra_buf)
#include "xalloc.h"
#include "xgetcwd.h"
+#ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
+# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
+#endif
+
#if !((HAVE_CANONICALIZE_FILE_NAME && FUNC_REALPATH_WORKS) \
|| GNULIB_CANONICALIZE_LGPL)
/* Return the canonical absolute name of file NAME. A canonical name
rname_limit = rname + PATH_MAX;
rname[0] = '/';
dest = rname + 1;
+ if (DOUBLE_SLASH_IS_DISTINCT_ROOT && name[1] == '/')
+ *dest++ = '/';
}
for (start = name; *start; start = end)
/* Back up to previous component, ignore if at root already. */
if (dest > rname + 1)
while ((--dest)[-1] != '/');
+ if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1
+ && *dest == '/')
+ dest++;
}
else
{
name = end = memcpy (extra_buf, buf, n);
if (buf[0] == '/')
- dest = rname + 1; /* It's an absolute symlink */
+ {
+ dest = rname + 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 > rname + 1)
- while ((--dest)[-1] != '/');
+ {
+ /* Back up to previous component, ignore if at root
+ already: */
+ if (dest > rname + 1)
+ while ((--dest)[-1] != '/');
+ if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1
+ && *dest == '/')
+ dest++;
+ }
free (buf);
}
}
if (dest > rname + 1 && dest[-1] == '/')
--dest;
+ if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1 && *dest == '/')
+ dest++;
*dest = '\0';
free (extra_buf);
-# canonicalize.m4 serial 15
+# canonicalize.m4 serial 16
dnl Copyright (C) 2003-2007, 2009 Free Software Foundation, Inc.
AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
AC_CHECK_FUNCS_ONCE([canonicalize_file_name])
+ AC_REQUIRE([gl_DOUBLE_SLASH_ROOT])
AC_REQUIRE([gl_FUNC_REALPATH_WORKS])
if test $ac_cv_func_canonicalize_file_name = no; then
HAVE_CANONICALIZE_FILE_NAME=0
[
AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
AC_CHECK_FUNCS_ONCE([canonicalize_file_name getcwd readlink])
+ AC_REQUIRE([gl_DOUBLE_SLASH_ROOT])
AC_REQUIRE([gl_FUNC_REALPATH_WORKS])
AC_CHECK_HEADERS_ONCE([sys/param.h])
])
lib/canonicalize.h
lib/canonicalize.c
m4/canonicalize.m4
+m4/double-slash-root.m4
Depends-on:
areadlink-with-size
Files:
lib/canonicalize-lgpl.c
m4/canonicalize.m4
+m4/double-slash-root.m4
Depends-on:
alloca-opt
tests/test-canonicalize-lgpl.c
Depends-on:
+same-inode
configure.ac:
AC_CHECK_FUNCS_ONCE([symlink])
Depends-on:
progname
+same-inode
configure.ac:
AC_CHECK_FUNCS_ONCE([symlink])
#include <sys/stat.h>
#include <unistd.h>
+#include "same-inode.h"
+
#if !HAVE_SYMLINK
# define symlink(a,b) (-1)
#endif /* !HAVE_SYMLINK */
ASSERT (symlink ("wum", BASE "/ouk") == 0);
ASSERT (symlink ("../ise", BASE "/ket") == 0);
ASSERT (mkdir (BASE "/lum", 0700) == 0);
+ ASSERT (symlink ("//.//../..", BASE "/droot") == 0);
/* Check that the symbolic link to a file can be resolved. */
{
ASSERT (errno == ELOOP);
}
+ /* Check that leading // is honored correctly. */
+ {
+ struct stat st1;
+ struct stat st2;
+ char *result1 = canonicalize_file_name ("//.");
+ char *result2 = canonicalize_file_name (BASE "/droot");
+ ASSERT (result1);
+ ASSERT (result2);
+ ASSERT (stat ("/", &st1) == 0);
+ ASSERT (stat ("//", &st2) == 0);
+ if (SAME_INODE (st1, st2))
+ {
+ ASSERT (strcmp (result1, "/") == 0);
+ ASSERT (strcmp (result2, "/") == 0);
+ }
+ else
+ {
+ ASSERT (strcmp (result1, "//") == 0);
+ ASSERT (strcmp (result2, "//") == 0);
+ }
+ free (result1);
+ free (result2);
+ }
+
+
/* Cleanup. */
+ ASSERT (remove (BASE "/droot") == 0);
ASSERT (remove (BASE "/plo") == 0);
ASSERT (remove (BASE "/huk") == 0);
ASSERT (remove (BASE "/bef") == 0);
#include <sys/stat.h>
#include <unistd.h>
+#include "same-inode.h"
+
#if !HAVE_SYMLINK
# define symlink(a,b) (-1)
#endif
ASSERT (mkdir (BASE "/d", 0700) == 0);
ASSERT (close (creat (BASE "/d/2", 0600)) == 0);
ASSERT (symlink ("../s/2", BASE "/d/1") == 0);
+ ASSERT (symlink ("//.//../..", BASE "/droot") == 0);
/* Check that the symbolic link to a file can be resolved. */
{
free (result2);
}
+ /* Check that leading // is honored correctly. */
+ {
+ struct stat st1;
+ struct stat st2;
+ char *result1 = canonicalize_file_name ("//.");
+ char *result2 = canonicalize_filename_mode ("//.", CAN_EXISTING);
+ char *result3 = canonicalize_file_name (BASE "/droot");
+ char *result4 = canonicalize_filename_mode (BASE "/droot", CAN_EXISTING);
+ ASSERT (result1);
+ ASSERT (result2);
+ ASSERT (result3);
+ ASSERT (result4);
+ ASSERT (stat ("/", &st1) == 0);
+ ASSERT (stat ("//", &st2) == 0);
+ if (SAME_INODE (st1, st2))
+ {
+ ASSERT (strcmp (result1, "/") == 0);
+ ASSERT (strcmp (result2, "/") == 0);
+ ASSERT (strcmp (result3, "/") == 0);
+ ASSERT (strcmp (result4, "/") == 0);
+ }
+ else
+ {
+ ASSERT (strcmp (result1, "//") == 0);
+ ASSERT (strcmp (result2, "//") == 0);
+ ASSERT (strcmp (result3, "//") == 0);
+ ASSERT (strcmp (result4, "//") == 0);
+ }
+ free (result1);
+ free (result2);
+ free (result3);
+ free (result4);
+ }
+
/* Cleanup. */
+ ASSERT (remove (BASE "/droot") == 0);
ASSERT (remove (BASE "/d/1") == 0);
ASSERT (remove (BASE "/d/2") == 0);
ASSERT (remove (BASE "/d") == 0);