summaryrefslogtreecommitdiff
path: root/lib/canonicalize.c
diff options
context:
space:
mode:
authorPádraig Brady <P@draigBrady.com>2011-12-29 23:49:53 +0000
committerPádraig Brady <P@draigBrady.com>2011-12-30 12:43:43 +0000
commit8bcd0399386f6c3298ee63da74c58f80053d5a42 (patch)
tree4129f0562bb854b9135b71b02c0972bcc1ee1a10 /lib/canonicalize.c
parent771de9614b52042c1870625d412263a22708152e (diff)
downloadgnulib-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.c19
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)