From: Eric Blake Date: Sat, 12 Sep 2009 12:04:46 +0000 (-0600) Subject: canonicalize: in CAN_ALL_BUT_LAST, allow trailing slash X-Git-Tag: v0.1~5467 X-Git-Url: http://erislabs.org.uk/gitweb/?a=commitdiff_plain;h=484baa4d4a86eedcc1b9473b0c8eb0e8e3d8470d;p=gnulib.git canonicalize: in CAN_ALL_BUT_LAST, allow trailing slash Coreutils' `readlink -f foo/' should not fail if lstat("foo") gives ENOENT. * lib/canonicalize.c (canonicalize_filename_mode): Skip trailing slashes when checking if last component is missing. * tests/test-canonicalize.c (main): Test this. Signed-off-by: Eric Blake --- diff --git a/ChangeLog b/ChangeLog index b0464b4ae..70b592d97 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2009-09-17 Eric Blake + canonicalize: in CAN_ALL_BUT_LAST, allow trailing slash + * lib/canonicalize.c (canonicalize_filename_mode): Skip trailing + slashes when checking if last component is missing. + * tests/test-canonicalize.c (main): Test this. + canonicalize, canonicalize-lgpl: honor // if distinct from / * modules/canonicalize (Files): Add double-slash-root.m4. * modules/canonicalize-lgpl (Files): Likewise. diff --git a/lib/canonicalize.c b/lib/canonicalize.c index 9434699fd..65e73a703 100644 --- a/lib/canonicalize.c +++ b/lib/canonicalize.c @@ -184,8 +184,12 @@ canonicalize_filename_mode (const char *name, canonicalize_mode_t can_mode) saved_errno = errno; if (can_mode == CAN_EXISTING) goto error; - if (can_mode == CAN_ALL_BUT_LAST && *end) - goto error; + if (can_mode == CAN_ALL_BUT_LAST) + { + if (end[strspn (end, "/")] || saved_errno != ENOENT) + goto error; + continue; + } st.st_mode = 0; } diff --git a/tests/test-canonicalize.c b/tests/test-canonicalize.c index f8dcc54d5..463297f61 100644 --- a/tests/test-canonicalize.c +++ b/tests/test-canonicalize.c @@ -240,26 +240,42 @@ main () { char *result1 = canonicalize_filename_mode (BASE "/zzz", CAN_ALL_BUT_LAST); char *result2 = canonicalize_filename_mode (BASE "/zzz", CAN_MISSING); + char *result3 = canonicalize_filename_mode (BASE "/zzz/", CAN_ALL_BUT_LAST); + char *result4 = canonicalize_filename_mode (BASE "/zzz/", CAN_MISSING); ASSERT (result1 != NULL); ASSERT (result2 != NULL); + ASSERT (result3 != NULL); + ASSERT (result4 != NULL); ASSERT (strcmp (result1, result2) == 0); + ASSERT (strcmp (result2, result3) == 0); + ASSERT (strcmp (result3, result4) == 0); ASSERT (strcmp (result1 + strlen (result1) - strlen ("/" BASE "/zzz"), "/" BASE "/zzz") == 0); free (result1); free (result2); + free (result3); + free (result4); } /* Check that alternate modes can resolve broken symlink basenames. */ { char *result1 = canonicalize_filename_mode (BASE "/ouk", CAN_ALL_BUT_LAST); char *result2 = canonicalize_filename_mode (BASE "/ouk", CAN_MISSING); + char *result3 = canonicalize_filename_mode (BASE "/ouk/", CAN_ALL_BUT_LAST); + char *result4 = canonicalize_filename_mode (BASE "/ouk/", CAN_MISSING); ASSERT (result1 != NULL); ASSERT (result2 != NULL); + ASSERT (result3 != NULL); + ASSERT (result4 != NULL); ASSERT (strcmp (result1, result2) == 0); + ASSERT (strcmp (result2, result3) == 0); + ASSERT (strcmp (result3, result4) == 0); ASSERT (strcmp (result1 + strlen (result1) - strlen ("/" BASE "/wum"), "/" BASE "/wum") == 0); free (result1); free (result2); + free (result3); + free (result4); } /* Check that alternate modes can handle missing dirnames. */