-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

According to Jim Meyering on 9/10/2009 11:29 AM:
>> readlink -fv missing  => lists /path/to/missing
>> readlink -fv missing/ => complains that missing is not a dir
>>
>> I would like to see: 'readlink -fv missing/' list '/path/to/missing', on the
>> grounds that one could do 'mkdir missing' to bring the path into existence;
>> this matches the documentation that -f ignores a missing final element 
>> (nowhere
>> does it say the final element has to be a non-file).
> 
> Yes, that makes sense.

This patch (on top of my canonicalize cleanups) does that:

- --
Don't work too hard, make some time for fun as well!

Eric Blake             e...@byu.net
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkqrur0ACgkQ84KuGfSFAYCBZgCfZQguPsWRKZJUh7WLF3Nli/tV
okIAoJOg78QYodvBq2ybYCGlaqmS/7Zq
=Yscq
-----END PGP SIGNATURE-----
>From 424bfcda7e9dea15ae03e1332d7ca59b0d1b845d Mon Sep 17 00:00:00 2001
From: Eric Blake <e...@byu.net>
Date: Sat, 12 Sep 2009 06:04:46 -0600
Subject: [PATCH] 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.

Signed-off-by: Eric Blake <e...@byu.net>
---
 ChangeLog                 |    5 +++++
 lib/canonicalize.c        |    8 ++++++--
 tests/test-canonicalize.c |   16 ++++++++++++++++
 3 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 5c03d38..c2290f3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2009-09-12  Eric Blake  <e...@byu.net>

+       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 a90f1a8..2374169 100644
--- a/lib/canonicalize.c
+++ b/lib/canonicalize.c
@@ -183,8 +183,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, "/")])
+                   goto error;
+                 continue;
+               }
              st.st_mode = 0;
            }

diff --git a/tests/test-canonicalize.c b/tests/test-canonicalize.c
index f8dcc54..463297f 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.  */
-- 
1.6.3.3.334.g916e1

Reply via email to