Fix recently-introduced expand-file-name bug
The bug was that (expand-file-name "~") returned something like "/home/eggert/" instead of "/home/eggert". Problem reported by Mattias Engdegård (Bug#26911#27). * src/fileio.c (Fexpand_file_name): When concatenating NEWDIR to NM, instead of stripping trailing slashes from NEWDIR (which can turn non-symlinks into symlinks), strip leading slashes from NM. This also simplifies the code by removing no-longer-needed DOS_NT special-casing. Also, remove an unnecessary ‘target[length] = 0;’ as that byte will be overwritten by the next memcpy anyway. * test/src/fileio-tests.el (fileio-tests--HOME-trailing-slash): New test.
This commit is contained in:
parent
1153b238ae
commit
0bbc84630f
2 changed files with 21 additions and 25 deletions
38
src/fileio.c
38
src/fileio.c
|
@ -827,9 +827,9 @@ the root directory. */)
|
|||
ptrdiff_t tlen;
|
||||
#ifdef DOS_NT
|
||||
int drive = 0;
|
||||
bool collapse_newdir = true;
|
||||
bool is_escaped = 0;
|
||||
#endif /* DOS_NT */
|
||||
bool collapse_newdir = true;
|
||||
ptrdiff_t length, nbytes;
|
||||
Lisp_Object handler, result, handled_name;
|
||||
bool multibyte;
|
||||
|
@ -1183,9 +1183,7 @@ the root directory. */)
|
|||
newdir = SSDATA (hdir);
|
||||
newdirlim = newdir + SBYTES (hdir);
|
||||
}
|
||||
#ifdef DOS_NT
|
||||
collapse_newdir = false;
|
||||
#endif
|
||||
}
|
||||
else /* ~user/filename */
|
||||
{
|
||||
|
@ -1205,9 +1203,7 @@ the root directory. */)
|
|||
|
||||
while (*++nm && !IS_DIRECTORY_SEP (*nm))
|
||||
continue;
|
||||
#ifdef DOS_NT
|
||||
collapse_newdir = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* If we don't find a user of that name, leave the name
|
||||
|
@ -1374,12 +1370,7 @@ the root directory. */)
|
|||
}
|
||||
#endif /* DOS_NT */
|
||||
|
||||
/* Ignore any slash at the end of newdir, unless newdir is
|
||||
just "/" or "//". */
|
||||
length = newdirlim - newdir;
|
||||
while (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1])
|
||||
&& ! (length == 2 && IS_DIRECTORY_SEP (newdir[0])))
|
||||
length--;
|
||||
|
||||
/* Now concatenate the directory and name to new space in the stack frame. */
|
||||
tlen = length + file_name_as_directory_slop + (nmlim - nm) + 1;
|
||||
|
@ -1398,25 +1389,22 @@ the root directory. */)
|
|||
|
||||
if (newdir)
|
||||
{
|
||||
if (IS_DIRECTORY_SEP (nm[0]))
|
||||
if (!collapse_newdir)
|
||||
{
|
||||
#ifdef DOS_NT
|
||||
/* If newdir is effectively "C:/", then the drive letter will have
|
||||
been stripped and newdir will be "/". Concatenating with an
|
||||
absolute directory in nm produces "//", which will then be
|
||||
incorrectly treated as a network share. Ignore newdir in
|
||||
this case (keeping the drive letter). */
|
||||
if (!(drive && nm[0] && IS_DIRECTORY_SEP (newdir[0])
|
||||
&& newdir[1] == '\0'))
|
||||
#endif
|
||||
{
|
||||
memcpy (target, newdir, length);
|
||||
target[length] = 0;
|
||||
nbytes = length;
|
||||
}
|
||||
/* With ~ or ~user, leave NEWDIR as-is to avoid transforming
|
||||
it from a symlink (or a regular file!) into a directory. */
|
||||
memcpy (target, newdir, length);
|
||||
nbytes = length;
|
||||
}
|
||||
else
|
||||
nbytes = file_name_as_directory (target, newdir, length, multibyte);
|
||||
|
||||
/* If TARGET ends in a directory separator, omit leading
|
||||
directory separators from NM so that concatenating a TARGET "/"
|
||||
to an NM "/foo" does not result in the incorrect "//foo". */
|
||||
if (nbytes && IS_DIRECTORY_SEP (target[nbytes - 1]))
|
||||
while (IS_DIRECTORY_SEP (nm[0]))
|
||||
nm++;
|
||||
}
|
||||
|
||||
memcpy (target + nbytes, nm, nmlim - nm + 1);
|
||||
|
|
|
@ -108,6 +108,14 @@ Also check that an encoding error can appear in a symlink."
|
|||
(should (equal (expand-file-name "~/bar") "x:/foo/bar")))
|
||||
(setenv "HOME" old-home)))
|
||||
|
||||
(ert-deftest fileio-tests--HOME-trailing-slash ()
|
||||
"Test that expand-file-name of \"~\" respects trailing slash."
|
||||
(let ((old-home (getenv "HOME")))
|
||||
(dolist (home '("/a/b/c" "/a/b/c/"))
|
||||
(setenv "HOME" home)
|
||||
(should (equal (expand-file-name "~") (expand-file-name home))))
|
||||
(setenv "HOME" old-home)))
|
||||
|
||||
(ert-deftest fileio-tests--expand-file-name-trailing-slash ()
|
||||
(dolist (fooslashalias '("foo/" "foo//" "foo/." "foo//." "foo///././."
|
||||
"foo/a/.."))
|
||||
|
|
Loading…
Add table
Reference in a new issue