diff options
| author | Eli Zaretskii | 2017-08-12 14:44:20 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2017-08-12 14:44:20 +0300 |
| commit | fce2b2d2b40a1c0505d1ad623baef76f726c436a (patch) | |
| tree | b47d40c2cc59399db224828d8682c30cabdb1f87 | |
| parent | ec5cfaa4568327b5b0b299be2664f7fdae123292 (diff) | |
| download | emacs-fce2b2d2b40a1c0505d1ad623baef76f726c436a.tar.gz emacs-fce2b2d2b40a1c0505d1ad623baef76f726c436a.zip | |
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.
| -rw-r--r-- | src/msdos.c | 17 | ||||
| -rw-r--r-- | src/w32.c | 19 |
2 files changed, 32 insertions, 4 deletions
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) | |||
| 3950 | && !(IS_DIRECTORY_SEP (path[0]) | 3950 | && !(IS_DIRECTORY_SEP (path[0]) |
| 3951 | || IS_DEVICE_SEP (path[1]))) | 3951 | || IS_DEVICE_SEP (path[1]))) |
| 3952 | { | 3952 | { |
| 3953 | errno = EBADF; | 3953 | char lastc = dir_pathname[strlen (dir_pathname) - 1]; |
| 3954 | return -1; | 3954 | |
| 3955 | if (strlen (dir_pathname) + strlen (path) + IS_DIRECTORY_SEP (lastc) | ||
| 3956 | >= MAXPATHLEN) | ||
| 3957 | { | ||
| 3958 | errno = ENAMETOOLONG; | ||
| 3959 | return -1; | ||
| 3960 | } | ||
| 3961 | |||
| 3962 | sprintf (fullname, "%s%s%s", | ||
| 3963 | dir_pathname, IS_DIRECTORY_SEP (lastc) ? "" : "/", path); | ||
| 3964 | path = fullname; | ||
| 3955 | } | 3965 | } |
| 3956 | 3966 | ||
| 3967 | if ((mode & F_OK) != 0 && IS_DIRECTORY_SEP (path[strlen (path) - 1])) | ||
| 3968 | mode |= D_OK; | ||
| 3969 | |||
| 3957 | return access (path, mode); | 3970 | return access (path, mode); |
| 3958 | } | 3971 | } |
| 3959 | 3972 | ||
| @@ -3887,15 +3887,30 @@ int | |||
| 3887 | faccessat (int dirfd, const char * path, int mode, int flags) | 3887 | faccessat (int dirfd, const char * path, int mode, int flags) |
| 3888 | { | 3888 | { |
| 3889 | DWORD attributes; | 3889 | DWORD attributes; |
| 3890 | char fullname[MAX_UTF8_PATH]; | ||
| 3890 | 3891 | ||
| 3892 | /* Rely on a hack: an open directory is modeled as file descriptor 0, | ||
| 3893 | and its actual file name is stored in dir_pathname by opendir. | ||
| 3894 | This is good enough for the current usage in Emacs, but is fragile. */ | ||
| 3891 | if (dirfd != AT_FDCWD | 3895 | if (dirfd != AT_FDCWD |
| 3892 | && !(IS_DIRECTORY_SEP (path[0]) | 3896 | && !(IS_DIRECTORY_SEP (path[0]) |
| 3893 | || IS_DEVICE_SEP (path[1]))) | 3897 | || IS_DEVICE_SEP (path[1]))) |
| 3894 | { | 3898 | { |
| 3895 | errno = EBADF; | 3899 | char lastc = dir_pathname[strlen (dir_pathname) - 1]; |
| 3896 | return -1; | 3900 | |
| 3901 | if (_snprintf (fullname, sizeof fullname, "%s%s%s", | ||
| 3902 | dir_pathname, IS_DIRECTORY_SEP (lastc) ? "" : "/", path) | ||
| 3903 | < 0) | ||
| 3904 | { | ||
| 3905 | errno = ENAMETOOLONG; | ||
| 3906 | return -1; | ||
| 3907 | } | ||
| 3908 | path = fullname; | ||
| 3897 | } | 3909 | } |
| 3898 | 3910 | ||
| 3911 | if (IS_DIRECTORY_SEP (path[strlen (path) - 1]) && (mode & F_OK) != 0) | ||
| 3912 | mode |= D_OK; | ||
| 3913 | |||
| 3899 | /* MSVCRT implementation of 'access' doesn't recognize D_OK, and its | 3914 | /* MSVCRT implementation of 'access' doesn't recognize D_OK, and its |
| 3900 | newer versions blow up when passed D_OK. */ | 3915 | newer versions blow up when passed D_OK. */ |
| 3901 | path = map_w32_filename (path, NULL); | 3916 | path = map_w32_filename (path, NULL); |