aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2012-10-12 17:19:54 +0200
committerEli Zaretskii2012-10-12 17:19:54 +0200
commitbb385a92ec4f8f5bbc93641aaa274bd735826574 (patch)
tree8fff4a185dfc74f91d94edc7b45dcd9dacbfbd67 /src
parent605a3df6811c2b3ce9379149cc8fd64fc9846136 (diff)
downloademacs-bb385a92ec4f8f5bbc93641aaa274bd735826574.tar.gz
emacs-bb385a92ec4f8f5bbc93641aaa274bd735826574.zip
Fix bug #12587 with slow startup on MS-Windows with Netlogon service.
src/fileio.c (check_existing): New function. (make_temp_name, Ffile_exists_p, Ffile_writable_p): Call it instead of calling 'stat', when what's needed is to check whether a file exists. This avoids expensive system calls on MS-Windows. src/w32.c (init_environment): Call 'check_existing' instead of 'stat'. src/lread.c (openp) [WINDOWSNT]: Call 'access' instead of 'stat' to determine whether a file exists and is not a directory. src/lisp.h (check_existing): Add prototype.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog16
-rw-r--r--src/fileio.c29
-rw-r--r--src/lisp.h1
-rw-r--r--src/lread.c8
-rw-r--r--src/w32.c3
5 files changed, 45 insertions, 12 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 47b2de24844..76f0226c0bf 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,19 @@
12012-10-12 Eli Zaretskii <eliz@gnu.org>
2
3 * fileio.c (check_existing): New function.
4 (make_temp_name, Ffile_exists_p, Ffile_writable_p): Call it
5 instead of calling 'stat', when what's needed is to check whether
6 a file exists. This avoids expensive system calls on MS-Windows.
7 (Bug#12587)
8
9 * w32.c (init_environment): Call 'check_existing' instead of
10 'stat'.
11
12 * lread.c (openp) [WINDOWSNT]: Call 'access' instead of 'stat' to
13 determine whether a file exists and is not a directory.
14
15 * lisp.h (check_existing): Add prototype.
16
12012-10-12 Jan Djärv <jan.h.d@swipnet.se> 172012-10-12 Jan Djärv <jan.h.d@swipnet.se>
2 18
3 * nsfont.m (nsfont_open): Remove font cache, it is not GC correct. 19 * nsfont.m (nsfont_open): Remove font cache, it is not GC correct.
diff --git a/src/fileio.c b/src/fileio.c
index b4eda01afcc..5de5bc2b021 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -52,6 +52,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
52#define NOMINMAX 1 52#define NOMINMAX 1
53#include <windows.h> 53#include <windows.h>
54#include <fcntl.h> 54#include <fcntl.h>
55#include <sys/file.h>
55#endif /* not WINDOWSNT */ 56#endif /* not WINDOWSNT */
56 57
57#ifdef MSDOS 58#ifdef MSDOS
@@ -668,7 +669,6 @@ make_temp_name (Lisp_Object prefix, bool base64_p)
668 669
669 while (1) 670 while (1)
670 { 671 {
671 struct stat ignored;
672 unsigned num = make_temp_name_count; 672 unsigned num = make_temp_name_count;
673 673
674 p[0] = make_temp_name_tbl[num & 63], num >>= 6; 674 p[0] = make_temp_name_tbl[num & 63], num >>= 6;
@@ -680,7 +680,7 @@ make_temp_name (Lisp_Object prefix, bool base64_p)
680 make_temp_name_count += 25229; 680 make_temp_name_count += 25229;
681 make_temp_name_count %= 225307; 681 make_temp_name_count %= 225307;
682 682
683 if (stat (data, &ignored) < 0) 683 if (!check_existing (data))
684 { 684 {
685 /* We want to return only if errno is ENOENT. */ 685 /* We want to return only if errno is ENOENT. */
686 if (errno == ENOENT) 686 if (errno == ENOENT)
@@ -2423,6 +2423,21 @@ On Unix, this is a name starting with a `/' or a `~'. */)
2423 return file_name_absolute_p (SSDATA (filename)) ? Qt : Qnil; 2423 return file_name_absolute_p (SSDATA (filename)) ? Qt : Qnil;
2424} 2424}
2425 2425
2426/* Return true if FILENAME exists. */
2427bool
2428check_existing (const char *filename)
2429{
2430#ifdef DOS_NT
2431 /* The full emulation of Posix 'stat' is too expensive on
2432 DOS/Windows, when all we want to know is whether the file exists.
2433 So we use 'access' instead, which is much more lightweight. */
2434 return (access (filename, F_OK) >= 0);
2435#else
2436 struct stat st;
2437 return (stat (filename, &st) >= 0);
2438#endif
2439}
2440
2426/* Return true if file FILENAME exists and can be executed. */ 2441/* Return true if file FILENAME exists and can be executed. */
2427 2442
2428static bool 2443static bool
@@ -2490,7 +2505,6 @@ Use `file-symlink-p' to test for such links. */)
2490{ 2505{
2491 Lisp_Object absname; 2506 Lisp_Object absname;
2492 Lisp_Object handler; 2507 Lisp_Object handler;
2493 struct stat statbuf;
2494 2508
2495 CHECK_STRING (filename); 2509 CHECK_STRING (filename);
2496 absname = Fexpand_file_name (filename, Qnil); 2510 absname = Fexpand_file_name (filename, Qnil);
@@ -2503,7 +2517,7 @@ Use `file-symlink-p' to test for such links. */)
2503 2517
2504 absname = ENCODE_FILE (absname); 2518 absname = ENCODE_FILE (absname);
2505 2519
2506 return (stat (SSDATA (absname), &statbuf) >= 0) ? Qt : Qnil; 2520 return (check_existing (SSDATA (absname))) ? Qt : Qnil;
2507} 2521}
2508 2522
2509DEFUN ("file-executable-p", Ffile_executable_p, Sfile_executable_p, 1, 1, 0, 2523DEFUN ("file-executable-p", Ffile_executable_p, Sfile_executable_p, 1, 1, 0,
@@ -2584,7 +2598,6 @@ DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
2584{ 2598{
2585 Lisp_Object absname, dir, encoded; 2599 Lisp_Object absname, dir, encoded;
2586 Lisp_Object handler; 2600 Lisp_Object handler;
2587 struct stat statbuf;
2588 2601
2589 CHECK_STRING (filename); 2602 CHECK_STRING (filename);
2590 absname = Fexpand_file_name (filename, Qnil); 2603 absname = Fexpand_file_name (filename, Qnil);
@@ -2596,7 +2609,7 @@ DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
2596 return call2 (handler, Qfile_writable_p, absname); 2609 return call2 (handler, Qfile_writable_p, absname);
2597 2610
2598 encoded = ENCODE_FILE (absname); 2611 encoded = ENCODE_FILE (absname);
2599 if (stat (SSDATA (encoded), &statbuf) >= 0) 2612 if (check_existing (SSDATA (encoded)))
2600 return (check_writable (SSDATA (encoded)) 2613 return (check_writable (SSDATA (encoded))
2601 ? Qt : Qnil); 2614 ? Qt : Qnil);
2602 2615
@@ -2611,9 +2624,7 @@ DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
2611 /* The read-only attribute of the parent directory doesn't affect 2624 /* The read-only attribute of the parent directory doesn't affect
2612 whether a file or directory can be created within it. Some day we 2625 whether a file or directory can be created within it. Some day we
2613 should check ACLs though, which do affect this. */ 2626 should check ACLs though, which do affect this. */
2614 if (stat (SDATA (dir), &statbuf) < 0) 2627 return (access (SDATA (dir), D_OK) < 0) ? Qnil : Qt;
2615 return Qnil;
2616 return S_ISDIR (statbuf.st_mode) ? Qt : Qnil;
2617#else 2628#else
2618 return (check_writable (!NILP (dir) ? SSDATA (dir) : "") 2629 return (check_writable (!NILP (dir) ? SSDATA (dir) : "")
2619 ? Qt : Qnil); 2630 ? Qt : Qnil);
diff --git a/src/lisp.h b/src/lisp.h
index 62e287561cd..7afe7b373fe 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3182,6 +3182,7 @@ extern void internal_delete_file (Lisp_Object);
3182extern void syms_of_fileio (void); 3182extern void syms_of_fileio (void);
3183extern Lisp_Object make_temp_name (Lisp_Object, bool); 3183extern Lisp_Object make_temp_name (Lisp_Object, bool);
3184extern Lisp_Object Qdelete_file; 3184extern Lisp_Object Qdelete_file;
3185extern bool check_existing (const char *);
3185 3186
3186/* Defined in search.c. */ 3187/* Defined in search.c. */
3187extern void shrink_regexp_cache (void); 3188extern void shrink_regexp_cache (void);
diff --git a/src/lread.c b/src/lread.c
index dbbde694cf6..6d4c0d990af 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -1449,7 +1449,6 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *sto
1449 bool absolute = 0; 1449 bool absolute = 0;
1450 ptrdiff_t want_length; 1450 ptrdiff_t want_length;
1451 Lisp_Object filename; 1451 Lisp_Object filename;
1452 struct stat st;
1453 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6; 1452 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
1454 Lisp_Object string, tail, encoded_fn; 1453 Lisp_Object string, tail, encoded_fn;
1455 ptrdiff_t max_suffix_len = 0; 1454 ptrdiff_t max_suffix_len = 0;
@@ -1543,11 +1542,18 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *sto
1543 } 1542 }
1544 else 1543 else
1545 { 1544 {
1545#ifndef WINDOWSNT
1546 struct stat st;
1547#endif
1546 const char *pfn; 1548 const char *pfn;
1547 1549
1548 encoded_fn = ENCODE_FILE (string); 1550 encoded_fn = ENCODE_FILE (string);
1549 pfn = SSDATA (encoded_fn); 1551 pfn = SSDATA (encoded_fn);
1552#ifdef WINDOWSNT
1553 exists = access (pfn, F_OK) == 0 && access (pfn, D_OK) < 0;
1554#else
1550 exists = (stat (pfn, &st) == 0 && ! S_ISDIR (st.st_mode)); 1555 exists = (stat (pfn, &st) == 0 && ! S_ISDIR (st.st_mode));
1556#endif
1551 if (exists) 1557 if (exists)
1552 { 1558 {
1553 /* Check that we can access or open it. */ 1559 /* Check that we can access or open it. */
diff --git a/src/w32.c b/src/w32.c
index b50cd13517d..15903dbceb3 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -1612,7 +1612,6 @@ init_environment (char ** argv)
1612 LPBYTE lpval; 1612 LPBYTE lpval;
1613 DWORD dwType; 1613 DWORD dwType;
1614 char locale_name[32]; 1614 char locale_name[32];
1615 struct stat ignored;
1616 char default_home[MAX_PATH]; 1615 char default_home[MAX_PATH];
1617 int appdata = 0; 1616 int appdata = 0;
1618 1617
@@ -1653,7 +1652,7 @@ init_environment (char ** argv)
1653 /* For backwards compatibility, check if a .emacs file exists in C:/ 1652 /* For backwards compatibility, check if a .emacs file exists in C:/
1654 If not, then we can try to default to the appdata directory under the 1653 If not, then we can try to default to the appdata directory under the
1655 user's profile, which is more likely to be writable. */ 1654 user's profile, which is more likely to be writable. */
1656 if (stat ("C:/.emacs", &ignored) < 0) 1655 if (check_existing ("C:/.emacs"))
1657 { 1656 {
1658 HRESULT profile_result; 1657 HRESULT profile_result;
1659 /* Dynamically load ShGetFolderPath, as it won't exist on versions 1658 /* Dynamically load ShGetFolderPath, as it won't exist on versions