X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fcanonicalize.c;h=583c1a4af200903b7f6b935191b43cddc28bc889;hb=66f5e6513c46dffcb40b216e3709b84ab5fbc392;hp=a5c9cb4a5853af084470f4e5b558e58eec506caa;hpb=8bcd0399386f6c3298ee63da74c58f80053d5a42;p=gnulib.git diff --git a/lib/canonicalize.c b/lib/canonicalize.c index a5c9cb4a5..583c1a4af 100644 --- a/lib/canonicalize.c +++ b/lib/canonicalize.c @@ -1,5 +1,5 @@ /* 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 @@ -46,7 +46,7 @@ #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. */ @@ -83,8 +83,8 @@ seen_triple (Hash_table **ht, char const *filename, struct stat const *st) /* 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. */ @@ -145,8 +145,12 @@ canonicalize_filename_mode (const char *name, canonicalize_mode_t can_mode) 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) @@ -169,7 +173,7 @@ canonicalize_filename_mode (const char *name, canonicalize_mode_t can_mode) if (dest > rname + 1) while ((--dest)[-1] != '/'); if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1 - && *dest == '/') + && *dest == '/' && dest[1] != '/') dest++; } else @@ -198,7 +202,14 @@ canonicalize_filename_mode (const char *name, canonicalize_mode_t can_mode) dest += end - start; *dest = '\0'; - if ((logical ? stat : 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) @@ -260,8 +271,12 @@ canonicalize_filename_mode (const char *name, canonicalize_mode_t can_mode) 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 { @@ -270,7 +285,7 @@ canonicalize_filename_mode (const char *name, canonicalize_mode_t can_mode) if (dest > rname + 1) while ((--dest)[-1] != '/'); if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1 - && *dest == '/') + && *dest == '/' && dest[1] != '/') dest++; } @@ -288,7 +303,8 @@ canonicalize_filename_mode (const char *name, canonicalize_mode_t can_mode) } 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)