Mercurial > hg > octave-nkf > gnulib-hg
changeset 16193:0b2b4b60945f
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.
author | Pádraig Brady <P@draigBrady.com> |
---|---|
date | Thu, 29 Dec 2011 23:49:53 +0000 |
parents | 557452ce040c |
children | 63675a6cbed4 |
files | ChangeLog lib/canonicalize.c lib/canonicalize.h tests/test-canonicalize.c |
diffstat | 4 files changed, 50 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2011-12-29 Pádraig Brady <P@draigBrady.com> + + canonicalize: add support for not resolving symlinks + * 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. + 2011-12-25 Jim Meyering <meyering@redhat.com> gitlog-to-changelog: do not clump multi-paragraph entries
--- 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 @@ /* 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 @@ 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 @@ 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)
--- a/lib/canonicalize.h +++ b/lib/canonicalize.h @@ -19,6 +19,8 @@ #include <stdlib.h> /* for canonicalize_file_name */ +#define CAN_MODE_MASK (CAN_EXISTING | CAN_ALL_BUT_LAST | CAN_MISSING) + enum canonicalize_mode_t { /* All components must exist. */ @@ -28,7 +30,10 @@ CAN_ALL_BUT_LAST = 1, /* No requirements on components existence. */ - CAN_MISSING = 2 + CAN_MISSING = 2, + + /* Don't expand symlinks. */ + CAN_NOLINKS = 4 }; typedef enum canonicalize_mode_t canonicalize_mode_t;
--- a/tests/test-canonicalize.c +++ b/tests/test-canonicalize.c @@ -82,6 +82,9 @@ result2 = canonicalize_filename_mode (NULL, CAN_EXISTING); ASSERT (result2 == NULL); ASSERT (errno == EINVAL); + result2 = canonicalize_filename_mode (".", CAN_MISSING | CAN_ALL_BUT_LAST); + ASSERT (result2 == NULL); + ASSERT (errno == EINVAL); } /* Check that a non-directory with trailing slash yields NULL. */ @@ -134,6 +137,15 @@ ASSERT (symlink ("../s/2", BASE "/d/1") == 0); ASSERT (symlink ("//.//../..", BASE "/droot") == 0); + /* Check that symbolic links are not resolved, with CAN_NOLINKS. */ + { + char *result1 = canonicalize_filename_mode (BASE "/huk", CAN_NOLINKS); + ASSERT (result1 != NULL); + ASSERT (strcmp (result1 + strlen (result1) - strlen ("/" BASE "/huk"), + "/" BASE "/huk") == 0); + free (result1); + } + /* Check that the symbolic link to a file can be resolved. */ { char *result1 = canonicalize_file_name (BASE "/huk");