]> code.delx.au - gnu-emacs/commitdiff
Speed up most calls to 'stat' and 'lstat' on MS-Windows.
authorEli Zaretskii <eliz@gnu.org>
Fri, 14 Dec 2012 14:05:01 +0000 (16:05 +0200)
committerEli Zaretskii <eliz@gnu.org>
Fri, 14 Dec 2012 14:05:01 +0000 (16:05 +0200)
 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
nt/inc/sys/stat.h
src/ChangeLog
src/dired.c
src/w32.c

index 4a82a97b58e529d1d477e71a4c547552f9d48c8b..56e986498ae85b98a2bd1cfb3b3a8b5a9e6f47c6 100644 (file)
@@ -1,3 +1,7 @@
+2012-12-14  Eli Zaretskii  <eliz@gnu.org>
+
+       * inc/sys/stat.h: Declare w32_stat_get_owner_group.
+
 2012-12-13  Juanma Barranquero  <lekktu@gmail.com>
 
        * config.nt: Sync with autogen/config.in.
index b673b80a0e3cecdb39a660ea05b52adbb3c9ea66..fb56b7cab40e6c05ae1da94fda2c7f6160c0d9b1 100644 (file)
@@ -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
 
index c64416a645460b96c501070833b9c256b82eb9ac..a1dc1c2adab15bc86ffd1fa42567145551e430e3 100644 (file)
@@ -1,3 +1,14 @@
+2012-12-14  Eli Zaretskii  <eliz@gnu.org>
+
+       * 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  <eggert@cs.ucla.edu>
 
        * fileio.c (Finsert_file_contents): Don't put tail into head area,
index bdb71c46364f1b2de05edd3e7d4998afc879628c..85af906c1daebf24c09480ac3f48721bbfd10b7b 100644 (file)
@@ -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)
index e163a3a1ee309457a9af83ac1020b1ce02c0a4be..7eaa38716f9878569190bb5c22949419fb187212 100644 (file)
--- 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  */