diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/dired.c | 86 | ||||
| -rw-r--r-- | src/kqueue.c | 4 | ||||
| -rw-r--r-- | src/sysdep.c | 2 |
3 files changed, 67 insertions, 25 deletions
diff --git a/src/dired.c b/src/dired.c index 288ba6b1038..128493aff28 100644 --- a/src/dired.c +++ b/src/dired.c | |||
| @@ -51,7 +51,8 @@ extern int is_slow_fs (const char *); | |||
| 51 | #endif | 51 | #endif |
| 52 | 52 | ||
| 53 | static ptrdiff_t scmp (const char *, const char *, ptrdiff_t); | 53 | static ptrdiff_t scmp (const char *, const char *, ptrdiff_t); |
| 54 | static Lisp_Object file_attributes (int, char const *, Lisp_Object); | 54 | static Lisp_Object file_attributes (int, char const *, Lisp_Object, |
| 55 | Lisp_Object, Lisp_Object); | ||
| 55 | 56 | ||
| 56 | /* Return the number of bytes in DP's name. */ | 57 | /* Return the number of bytes in DP's name. */ |
| 57 | static ptrdiff_t | 58 | static ptrdiff_t |
| @@ -161,7 +162,7 @@ read_dirent (DIR *dir, Lisp_Object dirname) | |||
| 161 | /* Function shared by Fdirectory_files and Fdirectory_files_and_attributes. | 162 | /* Function shared by Fdirectory_files and Fdirectory_files_and_attributes. |
| 162 | If not ATTRS, return a list of directory filenames; | 163 | If not ATTRS, return a list of directory filenames; |
| 163 | if ATTRS, return a list of directory filenames and their attributes. | 164 | if ATTRS, return a list of directory filenames and their attributes. |
| 164 | In the latter case, ID_FORMAT is passed to Ffile_attributes. */ | 165 | In the latter case, pass ID_FORMAT to file_attributes. */ |
| 165 | 166 | ||
| 166 | Lisp_Object | 167 | Lisp_Object |
| 167 | directory_files_internal (Lisp_Object directory, Lisp_Object full, | 168 | directory_files_internal (Lisp_Object directory, Lisp_Object full, |
| @@ -225,7 +226,7 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full, | |||
| 225 | if (attrs) | 226 | if (attrs) |
| 226 | { | 227 | { |
| 227 | /* Do this only once to avoid doing it (in w32.c:stat) for each | 228 | /* Do this only once to avoid doing it (in w32.c:stat) for each |
| 228 | file in the directory, when we call Ffile_attributes below. */ | 229 | file in the directory, when we call file_attributes below. */ |
| 229 | record_unwind_protect (directory_files_internal_w32_unwind, | 230 | record_unwind_protect (directory_files_internal_w32_unwind, |
| 230 | Vw32_get_true_file_attributes); | 231 | Vw32_get_true_file_attributes); |
| 231 | w32_save = Vw32_get_true_file_attributes; | 232 | w32_save = Vw32_get_true_file_attributes; |
| @@ -304,7 +305,7 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full, | |||
| 304 | if (attrs) | 305 | if (attrs) |
| 305 | { | 306 | { |
| 306 | Lisp_Object fileattrs | 307 | Lisp_Object fileattrs |
| 307 | = file_attributes (fd, dp->d_name, id_format); | 308 | = file_attributes (fd, dp->d_name, directory, name, id_format); |
| 308 | list = Fcons (Fcons (finalname, fileattrs), list); | 309 | list = Fcons (Fcons (finalname, fileattrs), list); |
| 309 | } | 310 | } |
| 310 | else | 311 | else |
| @@ -351,7 +352,7 @@ If NOSORT is non-nil, the list is not sorted--its order is unpredictable. | |||
| 351 | return call5 (handler, Qdirectory_files, directory, | 352 | return call5 (handler, Qdirectory_files, directory, |
| 352 | full, match, nosort); | 353 | full, match, nosort); |
| 353 | 354 | ||
| 354 | return directory_files_internal (directory, full, match, nosort, 0, Qnil); | 355 | return directory_files_internal (directory, full, match, nosort, false, Qnil); |
| 355 | } | 356 | } |
| 356 | 357 | ||
| 357 | DEFUN ("directory-files-and-attributes", Fdirectory_files_and_attributes, | 358 | DEFUN ("directory-files-and-attributes", Fdirectory_files_and_attributes, |
| @@ -379,7 +380,8 @@ which see. */) | |||
| 379 | return call6 (handler, Qdirectory_files_and_attributes, | 380 | return call6 (handler, Qdirectory_files_and_attributes, |
| 380 | directory, full, match, nosort, id_format); | 381 | directory, full, match, nosort, id_format); |
| 381 | 382 | ||
| 382 | return directory_files_internal (directory, full, match, nosort, 1, id_format); | 383 | return directory_files_internal (directory, full, match, nosort, |
| 384 | true, id_format); | ||
| 383 | } | 385 | } |
| 384 | 386 | ||
| 385 | 387 | ||
| @@ -923,14 +925,17 @@ so last access time will always be midnight of that day. */) | |||
| 923 | } | 925 | } |
| 924 | 926 | ||
| 925 | encoded = ENCODE_FILE (filename); | 927 | encoded = ENCODE_FILE (filename); |
| 926 | return file_attributes (AT_FDCWD, SSDATA (encoded), id_format); | 928 | return file_attributes (AT_FDCWD, SSDATA (encoded), Qnil, filename, |
| 929 | id_format); | ||
| 927 | } | 930 | } |
| 928 | 931 | ||
| 929 | static Lisp_Object | 932 | static Lisp_Object |
| 930 | file_attributes (int fd, char const *name, Lisp_Object id_format) | 933 | file_attributes (int fd, char const *name, |
| 934 | Lisp_Object dirname, Lisp_Object filename, | ||
| 935 | Lisp_Object id_format) | ||
| 931 | { | 936 | { |
| 937 | ptrdiff_t count = SPECPDL_INDEX (); | ||
| 932 | struct stat s; | 938 | struct stat s; |
| 933 | int lstat_result; | ||
| 934 | 939 | ||
| 935 | /* An array to hold the mode string generated by filemodestring, | 940 | /* An array to hold the mode string generated by filemodestring, |
| 936 | including its terminating space and null byte. */ | 941 | including its terminating space and null byte. */ |
| @@ -938,22 +943,60 @@ file_attributes (int fd, char const *name, Lisp_Object id_format) | |||
| 938 | 943 | ||
| 939 | char *uname = NULL, *gname = NULL; | 944 | char *uname = NULL, *gname = NULL; |
| 940 | 945 | ||
| 941 | #ifdef WINDOWSNT | 946 | int err = EINVAL; |
| 942 | /* We usually don't request accurate owner and group info, because | ||
| 943 | it can be very expensive on Windows to get that, and most callers | ||
| 944 | of 'lstat' don't need that. But here we do want that information | ||
| 945 | to be accurate. */ | ||
| 946 | w32_stat_get_owner_group = 1; | ||
| 947 | #endif | ||
| 948 | 947 | ||
| 949 | lstat_result = fstatat (fd, name, &s, AT_SYMLINK_NOFOLLOW); | 948 | #ifdef O_PATH |
| 949 | int namefd = openat (fd, name, O_PATH | O_CLOEXEC | O_NOFOLLOW); | ||
| 950 | if (namefd < 0) | ||
| 951 | err = errno; | ||
| 952 | else | ||
| 953 | { | ||
| 954 | record_unwind_protect_int (close_file_unwind, namefd); | ||
| 955 | if (fstat (namefd, &s) != 0) | ||
| 956 | err = errno; | ||
| 957 | else | ||
| 958 | { | ||
| 959 | err = 0; | ||
| 960 | fd = namefd; | ||
| 961 | name = ""; | ||
| 962 | } | ||
| 963 | } | ||
| 964 | #endif | ||
| 950 | 965 | ||
| 966 | if (err == EINVAL) | ||
| 967 | { | ||
| 968 | #ifdef WINDOWSNT | ||
| 969 | /* We usually don't request accurate owner and group info, | ||
| 970 | because it can be expensive on Windows to get that, and most | ||
| 971 | callers of 'lstat' don't need that. But here we do want that | ||
| 972 | information to be accurate. */ | ||
| 973 | w32_stat_get_owner_group = 1; | ||
| 974 | #endif | ||
| 975 | if (fstatat (fd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) | ||
| 976 | err = 0; | ||
| 951 | #ifdef WINDOWSNT | 977 | #ifdef WINDOWSNT |
| 952 | w32_stat_get_owner_group = 0; | 978 | w32_stat_get_owner_group = 0; |
| 953 | #endif | 979 | #endif |
| 980 | } | ||
| 954 | 981 | ||
| 955 | if (lstat_result < 0) | 982 | if (err != 0) |
| 956 | return Qnil; | 983 | return unbind_to (count, Qnil); |
| 984 | |||
| 985 | Lisp_Object file_type; | ||
| 986 | if (S_ISLNK (s.st_mode)) | ||
| 987 | { | ||
| 988 | /* On systems lacking O_PATH support there is a race if the | ||
| 989 | symlink is replaced between the call to fstatat and the call | ||
| 990 | to emacs_readlinkat. Detect this race unless the replacement | ||
| 991 | is also a symlink. */ | ||
| 992 | file_type = emacs_readlinkat (fd, name); | ||
| 993 | if (NILP (file_type)) | ||
| 994 | return unbind_to (count, Qnil); | ||
| 995 | } | ||
| 996 | else | ||
| 997 | file_type = S_ISDIR (s.st_mode) ? Qt : Qnil; | ||
| 998 | |||
| 999 | unbind_to (count, Qnil); | ||
| 957 | 1000 | ||
| 958 | if (!(NILP (id_format) || EQ (id_format, Qinteger))) | 1001 | if (!(NILP (id_format) || EQ (id_format, Qinteger))) |
| 959 | { | 1002 | { |
| @@ -964,8 +1007,7 @@ file_attributes (int fd, char const *name, Lisp_Object id_format) | |||
| 964 | filemodestring (&s, modes); | 1007 | filemodestring (&s, modes); |
| 965 | 1008 | ||
| 966 | return CALLN (Flist, | 1009 | return CALLN (Flist, |
| 967 | (S_ISLNK (s.st_mode) ? emacs_readlinkat (fd, name) | 1010 | file_type, |
| 968 | : S_ISDIR (s.st_mode) ? Qt : Qnil), | ||
| 969 | make_number (s.st_nlink), | 1011 | make_number (s.st_nlink), |
| 970 | (uname | 1012 | (uname |
| 971 | ? DECODE_SYSTEM (build_unibyte_string (uname)) | 1013 | ? DECODE_SYSTEM (build_unibyte_string (uname)) |
diff --git a/src/kqueue.c b/src/kqueue.c index a8eb4cb797c..30922ef28b1 100644 --- a/src/kqueue.c +++ b/src/kqueue.c | |||
| @@ -130,7 +130,7 @@ kqueue_compare_dir_list (Lisp_Object watch_object) | |||
| 130 | return; | 130 | return; |
| 131 | } | 131 | } |
| 132 | new_directory_files = | 132 | new_directory_files = |
| 133 | directory_files_internal (dir, Qnil, Qnil, Qnil, 1, Qnil); | 133 | directory_files_internal (dir, Qnil, Qnil, Qnil, true, Qnil); |
| 134 | new_dl = kqueue_directory_listing (new_directory_files); | 134 | new_dl = kqueue_directory_listing (new_directory_files); |
| 135 | 135 | ||
| 136 | /* Parse through the old list. */ | 136 | /* Parse through the old list. */ |
| @@ -453,7 +453,7 @@ only when the upper directory of the renamed file is watched. */) | |||
| 453 | if (NILP (Ffile_directory_p (file))) | 453 | if (NILP (Ffile_directory_p (file))) |
| 454 | watch_object = list4 (watch_descriptor, file, flags, callback); | 454 | watch_object = list4 (watch_descriptor, file, flags, callback); |
| 455 | else { | 455 | else { |
| 456 | dir_list = directory_files_internal (file, Qnil, Qnil, Qnil, 1, Qnil); | 456 | dir_list = directory_files_internal (file, Qnil, Qnil, Qnil, true, Qnil); |
| 457 | watch_object = list5 (watch_descriptor, file, flags, callback, dir_list); | 457 | watch_object = list5 (watch_descriptor, file, flags, callback, dir_list); |
| 458 | } | 458 | } |
| 459 | watch_list = Fcons (watch_object, watch_list); | 459 | watch_list = Fcons (watch_object, watch_list); |
diff --git a/src/sysdep.c b/src/sysdep.c index 12e9c83ee90..b66a7453172 100644 --- a/src/sysdep.c +++ b/src/sysdep.c | |||
| @@ -2930,7 +2930,7 @@ list_system_processes (void) | |||
| 2930 | process. */ | 2930 | process. */ |
| 2931 | procdir = build_string ("/proc"); | 2931 | procdir = build_string ("/proc"); |
| 2932 | match = build_string ("[0-9]+"); | 2932 | match = build_string ("[0-9]+"); |
| 2933 | proclist = directory_files_internal (procdir, Qnil, match, Qt, 0, Qnil); | 2933 | proclist = directory_files_internal (procdir, Qnil, match, Qt, false, Qnil); |
| 2934 | 2934 | ||
| 2935 | /* `proclist' gives process IDs as strings. Destructively convert | 2935 | /* `proclist' gives process IDs as strings. Destructively convert |
| 2936 | each string into a number. */ | 2936 | each string into a number. */ |