From aedc566a94116191d3a8b3f7f9955058316f9fdc Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Thu, 7 Sep 2017 17:46:12 -0700 Subject: [PATCH] Fix bug: (directory-file-name "///") returned "//" * src/fileio.c (directory_file_name): For "///" and longer, return "/", not "//", as per POSIX. * test/src/fileio-tests.el (fileio-tests--directory-file-name) (fileio-tests--file-name-as-directory): New tests. --- src/fileio.c | 15 ++++++++------- test/src/fileio-tests.el | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/fileio.c b/src/fileio.c index 0a52982291d..9df3b1bedae 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -566,15 +566,16 @@ is already present. */) static ptrdiff_t directory_file_name (char *dst, char *src, ptrdiff_t srclen, bool multibyte) { - /* Process as Unix format: just remove any final slash. - But leave "/" and "//" unchanged. */ - while (srclen > 1 + /* In Unix-like systems, just remove any final slashes. However, if + they are all slashes, leave "/" and "//" alone, and treat "///" + and longer as if they were "/". */ + if (! (srclen == 2 && IS_DIRECTORY_SEP (src[0]))) + while (srclen > 1 #ifdef DOS_NT - && !IS_ANY_SEP (src[srclen - 2]) + && !IS_ANY_SEP (src[srclen - 2]) #endif - && IS_DIRECTORY_SEP (src[srclen - 1]) - && ! (srclen == 2 && IS_DIRECTORY_SEP (src[0]))) - srclen--; + && IS_DIRECTORY_SEP (src[srclen - 1])) + srclen--; memcpy (dst, src, srclen); dst[srclen] = 0; diff --git a/test/src/fileio-tests.el b/test/src/fileio-tests.el index 5103d2f21e6..ac5d533e63b 100644 --- a/test/src/fileio-tests.el +++ b/test/src/fileio-tests.el @@ -44,3 +44,22 @@ "Check that any non-NULL ASCII character can appear in a symlink. Also check that an encoding error can appear in a symlink." (should (equal nil (fileio-tests--symlink-failure)))) + +(ert-deftest fileio-tests--directory-file-name () + (should (equal (directory-file-name "/") "/")) + (should (equal (directory-file-name "//") "//")) + (should (equal (directory-file-name "///") "/")) + (should (equal (directory-file-name "////") "/")) + (should (equal (directory-file-name "/abc") "/abc")) + (should (equal (directory-file-name "/abc/") "/abc")) + (should (equal (directory-file-name "/abc//") "/abc"))) + +(ert-deftest fileio-tests--file-name-as-directory () + (should (equal (file-name-as-directory "") "./")) + (should (equal (file-name-as-directory "/") "/")) + (should (equal (file-name-as-directory "//") "//")) + (should (equal (file-name-as-directory "///") "///")) + (should (equal (file-name-as-directory "////") "////")) + (should (equal (file-name-as-directory "/abc") "/abc/")) + (should (equal (file-name-as-directory "/abc/") "/abc/")) + (should (equal (file-name-as-directory "/abc//") "/abc//"))) -- 2.39.2