Commit bb385a92 authored by Eli Zaretskii's avatar Eli Zaretskii

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.
parent 605a3df6
2012-10-12 Eli Zaretskii <eliz@gnu.org>
* 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.
(Bug#12587)
* w32.c (init_environment): Call 'check_existing' instead of
'stat'.
* lread.c (openp) [WINDOWSNT]: Call 'access' instead of 'stat' to
determine whether a file exists and is not a directory.
* lisp.h (check_existing): Add prototype.
2012-10-12 Jan Djärv <jan.h.d@swipnet.se>
* nsfont.m (nsfont_open): Remove font cache, it is not GC correct.
......
......@@ -52,6 +52,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#define NOMINMAX 1
#include <windows.h>
#include <fcntl.h>
#include <sys/file.h>
#endif /* not WINDOWSNT */
#ifdef MSDOS
......@@ -668,7 +669,6 @@ make_temp_name (Lisp_Object prefix, bool base64_p)
while (1)
{
struct stat ignored;
unsigned num = make_temp_name_count;
p[0] = make_temp_name_tbl[num & 63], num >>= 6;
......@@ -680,7 +680,7 @@ make_temp_name (Lisp_Object prefix, bool base64_p)
make_temp_name_count += 25229;
make_temp_name_count %= 225307;
if (stat (data, &ignored) < 0)
if (!check_existing (data))
{
/* We want to return only if errno is ENOENT. */
if (errno == ENOENT)
......@@ -2423,6 +2423,21 @@ On Unix, this is a name starting with a `/' or a `~'. */)
return file_name_absolute_p (SSDATA (filename)) ? Qt : Qnil;
}
/* Return true if FILENAME exists. */
bool
check_existing (const char *filename)
{
#ifdef DOS_NT
/* The full emulation of Posix 'stat' is too expensive on
DOS/Windows, when all we want to know is whether the file exists.
So we use 'access' instead, which is much more lightweight. */
return (access (filename, F_OK) >= 0);
#else
struct stat st;
return (stat (filename, &st) >= 0);
#endif
}
/* Return true if file FILENAME exists and can be executed. */
static bool
......@@ -2490,7 +2505,6 @@ Use `file-symlink-p' to test for such links. */)
{
Lisp_Object absname;
Lisp_Object handler;
struct stat statbuf;
CHECK_STRING (filename);
absname = Fexpand_file_name (filename, Qnil);
......@@ -2503,7 +2517,7 @@ Use `file-symlink-p' to test for such links. */)
absname = ENCODE_FILE (absname);
return (stat (SSDATA (absname), &statbuf) >= 0) ? Qt : Qnil;
return (check_existing (SSDATA (absname))) ? Qt : Qnil;
}
DEFUN ("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,
{
Lisp_Object absname, dir, encoded;
Lisp_Object handler;
struct stat statbuf;
CHECK_STRING (filename);
absname = Fexpand_file_name (filename, Qnil);
......@@ -2596,7 +2609,7 @@ DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
return call2 (handler, Qfile_writable_p, absname);
encoded = ENCODE_FILE (absname);
if (stat (SSDATA (encoded), &statbuf) >= 0)
if (check_existing (SSDATA (encoded)))
return (check_writable (SSDATA (encoded))
? Qt : Qnil);
......@@ -2611,9 +2624,7 @@ DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
/* The read-only attribute of the parent directory doesn't affect
whether a file or directory can be created within it. Some day we
should check ACLs though, which do affect this. */
if (stat (SDATA (dir), &statbuf) < 0)
return Qnil;
return S_ISDIR (statbuf.st_mode) ? Qt : Qnil;
return (access (SDATA (dir), D_OK) < 0) ? Qnil : Qt;
#else
return (check_writable (!NILP (dir) ? SSDATA (dir) : "")
? Qt : Qnil);
......
......@@ -3182,6 +3182,7 @@ extern void internal_delete_file (Lisp_Object);
extern void syms_of_fileio (void);
extern Lisp_Object make_temp_name (Lisp_Object, bool);
extern Lisp_Object Qdelete_file;
extern bool check_existing (const char *);
/* Defined in search.c. */
extern void shrink_regexp_cache (void);
......
......@@ -1449,7 +1449,6 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *sto
bool absolute = 0;
ptrdiff_t want_length;
Lisp_Object filename;
struct stat st;
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
Lisp_Object string, tail, encoded_fn;
ptrdiff_t max_suffix_len = 0;
......@@ -1543,11 +1542,18 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *sto
}
else
{
#ifndef WINDOWSNT
struct stat st;
#endif
const char *pfn;
encoded_fn = ENCODE_FILE (string);
pfn = SSDATA (encoded_fn);
#ifdef WINDOWSNT
exists = access (pfn, F_OK) == 0 && access (pfn, D_OK) < 0;
#else
exists = (stat (pfn, &st) == 0 && ! S_ISDIR (st.st_mode));
#endif
if (exists)
{
/* Check that we can access or open it. */
......
......@@ -1612,7 +1612,6 @@ init_environment (char ** argv)
LPBYTE lpval;
DWORD dwType;
char locale_name[32];
struct stat ignored;
char default_home[MAX_PATH];
int appdata = 0;
......@@ -1653,7 +1652,7 @@ init_environment (char ** argv)
/* For backwards compatibility, check if a .emacs file exists in C:/
If not, then we can try to default to the appdata directory under the
user's profile, which is more likely to be writable. */
if (stat ("C:/.emacs", &ignored) < 0)
if (check_existing ("C:/.emacs"))
{
HRESULT profile_result;
/* Dynamically load ShGetFolderPath, as it won't exist on versions
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment