From 5c207910c4899af1c547b0e508692d846c145d48 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Fri, 14 Dec 2012 16:05:01 +0200 Subject: [PATCH] Speed up most calls to 'stat' and 'lstat' on MS-Windows. src/w32.c (stat_worker): If w32_stat_get_owner_group is zero, do not try to get accurate owner and group information from NT file security APIs. This is to make most callers of 'stat' and 'lstat', which don't need that information, much faster. src/dired.c (Ffile_attributes) [WINDOWSNT]: Set w32_stat_get_owner_group to a non-zero value, to request accurate owner and group information from 'lstat'. nt/inc/sys/stat.h: Declare w32_stat_get_owner_group. --- nt/ChangeLog | 4 ++++ nt/inc/sys/stat.h | 4 ++++ src/ChangeLog | 11 +++++++++++ src/dired.c | 17 ++++++++++++++++- src/w32.c | 38 ++++++++++++++++++++++++-------------- 5 files changed, 59 insertions(+), 15 deletions(-) diff --git a/nt/ChangeLog b/nt/ChangeLog index 4a82a97b58..56e986498a 100644 --- a/nt/ChangeLog +++ b/nt/ChangeLog @@ -1,3 +1,7 @@ +2012-12-14 Eli Zaretskii + + * inc/sys/stat.h: Declare w32_stat_get_owner_group. + 2012-12-13 Juanma Barranquero * config.nt: Sync with autogen/config.in. diff --git a/nt/inc/sys/stat.h b/nt/inc/sys/stat.h index b673b80a0e..fb56b7cab4 100644 --- a/nt/inc/sys/stat.h +++ b/nt/inc/sys/stat.h @@ -98,6 +98,10 @@ struct stat { char st_gname[260]; }; +/* Internal variable for asking 'stat'/'lstat' to produce accurate + info about owner and group of files. */ +extern int w32_stat_get_owner_group; + /* Prevent redefinition by other headers, e.g. wchar.h. */ #define _STAT_DEFINED diff --git a/src/ChangeLog b/src/ChangeLog index c64416a645..a1dc1c2ada 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,14 @@ +2012-12-14 Eli Zaretskii + + * w32.c (stat_worker): If w32_stat_get_owner_group is zero, do not + try to get accurate owner and group information from NT file + security APIs. This is to make most callers of 'stat' and + 'lstat', which don't need that information, much faster. + + * dired.c (Ffile_attributes) [WINDOWSNT]: Set + w32_stat_get_owner_group to a non-zero value, to request accurate + owner and group information from 'lstat'. + 2012-12-13 Paul Eggert * fileio.c (Finsert_file_contents): Don't put tail into head area, diff --git a/src/dired.c b/src/dired.c index bdb71c4636..85af906c1d 100644 --- a/src/dired.c +++ b/src/dired.c @@ -895,6 +895,7 @@ so last access time will always be midnight of that day. */) Lisp_Object dirname; struct stat sdir; #endif /* BSD4_2 */ + int lstat_result; /* An array to hold the mode string generated by filemodestring, including its terminating space and null byte. */ @@ -922,7 +923,21 @@ so last access time will always be midnight of that day. */) encoded = ENCODE_FILE (filename); UNGCPRO; - if (lstat (SSDATA (encoded), &s) < 0) +#ifdef WINDOWSNT + /* We usually don't request accurate owner and group info, because + it can be very expensive on Windows to get that, and most callers + of 'lstat' don't need that. But here we do want that information + to be accurate. */ + w32_stat_get_owner_group = 1; +#endif + + lstat_result = lstat (SSDATA (encoded), &s); + +#ifdef WINDOWSNT + w32_stat_get_owner_group = 0; +#endif + + if (lstat_result < 0) return Qnil; values[0] = (S_ISLNK (s.st_mode) ? Ffile_symlink_p (filename) diff --git a/src/w32.c b/src/w32.c index e163a3a1ee..7eaa38716f 100644 --- a/src/w32.c +++ b/src/w32.c @@ -3537,6 +3537,10 @@ is_slow_fs (const char *name) return !(devtype == DRIVE_FIXED || devtype == DRIVE_RAMDISK); } +/* If this is non-zero, the caller wants accurate information about + file's owner and group, which could be expensive to get. */ +int w32_stat_get_owner_group; + /* MSVC stat function can't cope with UNC names and has other bugs, so replace it with our own. This also allows us to calculate consistent inode values and owner/group without hacks in the main Emacs code. */ @@ -3708,6 +3712,7 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks) /* We produce the fallback owner and group data, based on the current user that runs Emacs, in the following cases: + . caller didn't request owner and group info . this is Windows 9X . getting security by handle failed, and we need to produce information for the target of a symlink (this is better @@ -3716,23 +3721,25 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks) If getting security by handle fails, and we don't need to resolve symlinks, we try getting security by name. */ - if (is_windows_9x () != TRUE) - psd = get_file_security_desc_by_handle (fh); - if (psd) - { - get_file_owner_and_group (psd, name, buf); - LocalFree (psd); - } - else if (is_windows_9x () == TRUE) + if (!w32_stat_get_owner_group || is_windows_9x () == TRUE) get_file_owner_and_group (NULL, name, buf); - else if (!(is_a_symlink && follow_symlinks)) + else { - psd = get_file_security_desc_by_name (name); - get_file_owner_and_group (psd, name, buf); - xfree (psd); + psd = get_file_security_desc_by_handle (fh); + if (psd) + { + get_file_owner_and_group (psd, name, buf); + LocalFree (psd); + } + else if (!(is_a_symlink && follow_symlinks)) + { + psd = get_file_security_desc_by_name (name); + get_file_owner_and_group (psd, name, buf); + xfree (psd); + } + else + get_file_owner_and_group (NULL, name, buf); } - else - get_file_owner_and_group (NULL, name, buf); CloseHandle (fh); } else @@ -6849,6 +6856,9 @@ globals_of_w32 (void) /* "None" is the default group name on standalone workstations. */ strcpy (dflt_group_name, "None"); + + /* Reset, in case it has some value inherited from dump time. */ + w32_stat_get_owner_group = 0; } /* For make-serial-process */ -- 2.39.2