From: Eli Zaretskii Date: Sat, 12 Aug 2017 11:44:20 +0000 (+0300) Subject: Fix completion on directory names on MS-DOS/MS-Windows X-Git-Tag: emacs-26.0.90~483 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=fce2b2d2b40a1c0505d1ad623baef76f726c436a;p=emacs.git Fix completion on directory names on MS-DOS/MS-Windows * src/msdos.c (faccessat): * src/w32.c (faccessat): Support relative file names, and add D_OK to 'mode' if the argument is a directory. This unbreaks file-name completion when the completion result is a directory. --- diff --git a/src/msdos.c b/src/msdos.c index 87b6f84148c..5b025753d98 100644 --- a/src/msdos.c +++ b/src/msdos.c @@ -3950,10 +3950,23 @@ faccessat (int dirfd, const char * path, int mode, int flags) && !(IS_DIRECTORY_SEP (path[0]) || IS_DEVICE_SEP (path[1]))) { - errno = EBADF; - return -1; + char lastc = dir_pathname[strlen (dir_pathname) - 1]; + + if (strlen (dir_pathname) + strlen (path) + IS_DIRECTORY_SEP (lastc) + >= MAXPATHLEN) + { + errno = ENAMETOOLONG; + return -1; + } + + sprintf (fullname, "%s%s%s", + dir_pathname, IS_DIRECTORY_SEP (lastc) ? "" : "/", path); + path = fullname; } + if ((mode & F_OK) != 0 && IS_DIRECTORY_SEP (path[strlen (path) - 1])) + mode |= D_OK; + return access (path, mode); } diff --git a/src/w32.c b/src/w32.c index bdeaed0675b..c5b51bb6b0e 100644 --- a/src/w32.c +++ b/src/w32.c @@ -3887,15 +3887,30 @@ int faccessat (int dirfd, const char * path, int mode, int flags) { DWORD attributes; + char fullname[MAX_UTF8_PATH]; + /* Rely on a hack: an open directory is modeled as file descriptor 0, + and its actual file name is stored in dir_pathname by opendir. + This is good enough for the current usage in Emacs, but is fragile. */ if (dirfd != AT_FDCWD && !(IS_DIRECTORY_SEP (path[0]) || IS_DEVICE_SEP (path[1]))) { - errno = EBADF; - return -1; + char lastc = dir_pathname[strlen (dir_pathname) - 1]; + + if (_snprintf (fullname, sizeof fullname, "%s%s%s", + dir_pathname, IS_DIRECTORY_SEP (lastc) ? "" : "/", path) + < 0) + { + errno = ENAMETOOLONG; + return -1; + } + path = fullname; } + if (IS_DIRECTORY_SEP (path[strlen (path) - 1]) && (mode & F_OK) != 0) + mode |= D_OK; + /* MSVCRT implementation of 'access' doesn't recognize D_OK, and its newer versions blow up when passed D_OK. */ path = map_w32_filename (path, NULL);