mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-28 16:21:07 -08:00
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.
This commit is contained in:
parent
605a3df681
commit
bb385a92ec
5 changed files with 45 additions and 12 deletions
|
|
@ -1,3 +1,19 @@
|
|||
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.
|
||||
|
|
|
|||
29
src/fileio.c
29
src/fileio.c
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue