diff options
| -rw-r--r-- | src/ChangeLog | 16 | ||||
| -rw-r--r-- | src/fileio.c | 29 | ||||
| -rw-r--r-- | src/lisp.h | 1 | ||||
| -rw-r--r-- | src/lread.c | 8 | ||||
| -rw-r--r-- | src/w32.c | 3 |
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 @@ | |||
| 1 | 2012-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 | |||
| 1 | 2012-10-12 Jan Djärv <jan.h.d@swipnet.se> | 17 | 2012-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. */ | ||
| 2427 | bool | ||
| 2428 | check_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 | ||
| 2428 | static bool | 2443 | static 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 | ||
| 2509 | DEFUN ("file-executable-p", Ffile_executable_p, Sfile_executable_p, 1, 1, 0, | 2523 | 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, | |||
| 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); | |||
| 3182 | extern void syms_of_fileio (void); | 3182 | extern void syms_of_fileio (void); |
| 3183 | extern Lisp_Object make_temp_name (Lisp_Object, bool); | 3183 | extern Lisp_Object make_temp_name (Lisp_Object, bool); |
| 3184 | extern Lisp_Object Qdelete_file; | 3184 | extern Lisp_Object Qdelete_file; |
| 3185 | extern bool check_existing (const char *); | ||
| 3185 | 3186 | ||
| 3186 | /* Defined in search.c. */ | 3187 | /* Defined in search.c. */ |
| 3187 | extern void shrink_regexp_cache (void); | 3188 | extern 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. */ |
| @@ -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 |