/* Return the canonical absolute name of a given file.
- Copyright (C) 1996-2011 Free Software Foundation, Inc.
+ Copyright (C) 1996-2012 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#if !((HAVE_CANONICALIZE_FILE_NAME && FUNC_REALPATH_WORKS) \
|| GNULIB_CANONICALIZE_LGPL)
/* Return the canonical absolute name of file NAME. A canonical name
- does not contain any `.', `..' components nor any repeated file name
+ does not contain any ".", ".." components nor any repeated file name
separators ('/') or symlinks. All components must exist.
The result is malloc'd. */
/* Return the canonical absolute name of file NAME, while treating
missing elements according to CAN_MODE. A canonical name
- does not contain any `.', `..' components nor any repeated file name
- separators ('/') or, depdending on other CAN_MODE flags, symlinks.
+ does not contain any ".", ".." components nor any repeated file name
+ separators ('/') or, depending on other CAN_MODE flags, symlinks.
Whether components must exist or not depends on canonicalize mode.
The result is malloc'd. */
rname_limit = rname + PATH_MAX;
rname[0] = '/';
dest = rname + 1;
- if (DOUBLE_SLASH_IS_DISTINCT_ROOT && name[1] == '/')
- *dest++ = '/';
+ if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
+ {
+ if (name[1] == '/' && name[2] != '/')
+ *dest++ = '/';
+ *dest = '\0';
+ }
}
for (start = name; *start; start = end)
if (dest > rname + 1)
while ((--dest)[-1] != '/');
if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1
- && *dest == '/')
+ && *dest == '/' && dest[1] != '/')
dest++;
}
else
dest += end - start;
*dest = '\0';
- if ((logical ? stat (rname, &st) : lstat (rname, &st)) != 0)
+ if (logical && (can_mode == CAN_MISSING))
+ {
+ /* Avoid the stat in this case as it's inconsequential.
+ i.e. we're neither resolving symlinks or testing
+ component existence. */
+ st.st_mode = 0;
+ }
+ else if ((logical ? stat (rname, &st) : lstat (rname, &st)) != 0)
{
saved_errno = errno;
if (can_mode == CAN_EXISTING)
if (buf[0] == '/')
{
dest = rname + 1; /* It's an absolute symlink */
- if (DOUBLE_SLASH_IS_DISTINCT_ROOT && buf[1] == '/')
- *dest++ = '/';
+ if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
+ {
+ if (buf[1] == '/' && buf[2] != '/')
+ *dest++ = '/';
+ *dest = '\0';
+ }
}
else
{
if (dest > rname + 1)
while ((--dest)[-1] != '/');
if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1
- && *dest == '/')
+ && *dest == '/' && dest[1] != '/')
dest++;
}
}
if (dest > rname + 1 && dest[-1] == '/')
--dest;
- if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1 && *dest == '/')
+ if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1
+ && *dest == '/' && dest[1] != '/')
dest++;
*dest = '\0';
if (rname_limit != dest + 1)