diff options
author | Pádraig Brady <P@draigBrady.com> | 2011-12-29 23:49:53 +0000 |
---|---|---|
committer | Pádraig Brady <P@draigBrady.com> | 2011-12-30 12:43:43 +0000 |
commit | 8bcd0399386f6c3298ee63da74c58f80053d5a42 (patch) | |
tree | 4129f0562bb854b9135b71b02c0972bcc1ee1a10 /lib/canonicalize.c | |
parent | 771de9614b52042c1870625d412263a22708152e (diff) | |
download | gnulib-8bcd0399386f6c3298ee63da74c58f80053d5a42.tar.gz |
canonicalize: add support for not resolving symlinks
This will initially be used by a new coreutils realpath command.
* lib/canonicalize.h: Add the CAN_NOLINKS flag to
indicate we don't want to follow symlinks. Also
provide CAN_MODE_MASK to aid setting these existing
mutually exclusive values.
* lib/canonicalize.c (canonicalize_filename_mode):
Extract the flags from can_mode parameter, which
are currently just used to select between stat()
and lstat(). Also ensure that mutually exclusive
values are flagged immediately as invalid.
* tests/test-canonicalize.c: Verify symlinks are
not followed, and that invalid flag combinations
are diagnosed.
Diffstat (limited to 'lib/canonicalize.c')
-rw-r--r-- | lib/canonicalize.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/lib/canonicalize.c b/lib/canonicalize.c index 4fe9f308af..a5c9cb4a58 100644 --- a/lib/canonicalize.c +++ b/lib/canonicalize.c @@ -31,6 +31,8 @@ #include "xalloc.h" #include "xgetcwd.h" +#define MULTIPLE_BITS_SET(i) (((i) & ((i) - 1)) != 0) + /* In this file, we cannot handle file names longer than PATH_MAX. On systems with no file name length limit, use a fallback. */ #ifndef PATH_MAX @@ -82,8 +84,9 @@ 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 symlinks. Whether components must exist - or not depends on canonicalize mode. The result is malloc'd. */ + separators ('/') or, depdending on other CAN_MODE flags, symlinks. + Whether components must exist or not depends on canonicalize mode. + The result is malloc'd. */ char * canonicalize_filename_mode (const char *name, canonicalize_mode_t can_mode) @@ -95,6 +98,16 @@ canonicalize_filename_mode (const char *name, canonicalize_mode_t can_mode) size_t extra_len = 0; Hash_table *ht = NULL; int saved_errno; + int can_flags = can_mode & ~CAN_MODE_MASK; + can_mode &= CAN_MODE_MASK; + bool logical = can_flags & CAN_NOLINKS; + /* Perhaps in future we might support CAN_NOALLOC with CAN_NOLINKS. */ + + if (MULTIPLE_BITS_SET (can_mode)) + { + errno = EINVAL; + return NULL; + } if (name == NULL) { @@ -185,7 +198,7 @@ canonicalize_filename_mode (const char *name, canonicalize_mode_t can_mode) dest += end - start; *dest = '\0'; - if (lstat (rname, &st) != 0) + if ((logical ? stat : lstat) (rname, &st) != 0) { saved_errno = errno; if (can_mode == CAN_EXISTING) |