aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2019-09-21 11:27:46 -0700
committerPaul Eggert2019-09-21 11:38:36 -0700
commitd49d6ea9677eea1d30aae4244934b1c7336e35a3 (patch)
treec671f33693f458a7ba992a2a97250f620aec861d /src
parent56213b15e65a350f3f8cd9426a97691d8ff217ee (diff)
downloademacs-d49d6ea9677eea1d30aae4244934b1c7336e35a3.tar.gz
emacs-d49d6ea9677eea1d30aae4244934b1c7336e35a3.zip
Revert too-picky file-access tests
Problem reported by Andreas Schwab (Bug#37475). * doc/lispref/files.texi (Writing to Files) (Testing Accessibility, Kinds of Files): Document that accessibility and file-type predicates return nil if there is trouble determining accessibility or type. * etc/NEWS: Adjust, and list the affected primitives. * src/callproc.c (init_callproc): Go back to Ffile_exists_p. * src/fileio.c (PICKY_EACCES, file_test_errno): Remove. All uses removed. (Ffile_name_case_insensitive_p, Ffile_exists_p, Ffile_symlink_p) (Ffile_directory_p, Ffile_regular_p): Document that these functions return nil if there is trouble. (Ffile_name_case_insensitive_p, check_file_access) (Ffile_writable_p, Ffile_symlink_p, Ffile_directory_p) (Ffile_accessible_directory_p, Ffile_regular_p) * src/lread.c (Fload): Go back to treating trouble in determining the answer as if the file were missing. * src/fileio.c (Ffile_newer_than_file_p): Use file_attribute_errno not file_test_errno, since returning nil is not appropriate when there are two files to test; e.g., in the rare cases where both file timestamps have overflowed then neither t nor nil is correct.
Diffstat (limited to 'src')
-rw-r--r--src/callproc.c4
-rw-r--r--src/fileio.c108
-rw-r--r--src/lisp.h1
-rw-r--r--src/lread.c14
4 files changed, 32 insertions, 95 deletions
diff --git a/src/callproc.c b/src/callproc.c
index dbbf15c792a..007465cd405 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -1567,12 +1567,12 @@ init_callproc (void)
1567 1567
1568 tem = Fexpand_file_name (build_string ("NEWS"), Vdata_directory); 1568 tem = Fexpand_file_name (build_string ("NEWS"), Vdata_directory);
1569 if (!NILP (Fequal (srcdir, Vinvocation_directory)) 1569 if (!NILP (Fequal (srcdir, Vinvocation_directory))
1570 || !file_access_p (SSDATA (tem), F_OK)) 1570 || NILP (Ffile_exists_p (tem)))
1571 { 1571 {
1572 Lisp_Object newdir; 1572 Lisp_Object newdir;
1573 newdir = Fexpand_file_name (build_string ("../etc/"), lispdir); 1573 newdir = Fexpand_file_name (build_string ("../etc/"), lispdir);
1574 tem = Fexpand_file_name (build_string ("NEWS"), newdir); 1574 tem = Fexpand_file_name (build_string ("NEWS"), newdir);
1575 if (file_access_p (SSDATA (tem), F_OK)) 1575 if (!NILP (Ffile_exists_p (tem)))
1576 Vdata_directory = newdir; 1576 Vdata_directory = newdir;
1577 } 1577 }
1578 } 1578 }
diff --git a/src/fileio.c b/src/fileio.c
index b2896c1fe1e..b510d48dbaa 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -253,30 +253,6 @@ file_attribute_errno (Lisp_Object file, int err)
253 return file_metadata_errno ("Getting attributes", file, err); 253 return file_metadata_errno ("Getting attributes", file, err);
254} 254}
255 255
256/* In theory, EACCES errors for predicates like file-readable-p should
257 be checked further because they may be problems with an ancestor
258 directory instead of with the file itself, which means that we
259 don't have reliable info about the requested file. In practice,
260 though, DOS_NT platforms set errno to EACCES for missing files like
261 "/var/mail", so signaling EACCES errors would be a mistake there.
262 So return nil for EACCES unless PICKY_EACCES, which is false by
263 default on DOS_NT. */
264#ifndef PICKY_EACCES
265# ifdef DOS_NT
266enum { PICKY_EACCES = false };
267# else
268enum { PICKY_EACCES = true };
269# endif
270#endif
271
272Lisp_Object
273file_test_errno (Lisp_Object file, int err)
274{
275 if (!PICKY_EACCES && err == EACCES)
276 return Qnil;
277 return file_metadata_errno ("Testing file", file, err);
278}
279
280void 256void
281close_file_unwind (int fd) 257close_file_unwind (int fd)
282{ 258{
@@ -2453,7 +2429,9 @@ file_name_case_insensitive_err (Lisp_Object file)
2453DEFUN ("file-name-case-insensitive-p", Ffile_name_case_insensitive_p, 2429DEFUN ("file-name-case-insensitive-p", Ffile_name_case_insensitive_p,
2454 Sfile_name_case_insensitive_p, 1, 1, 0, 2430 Sfile_name_case_insensitive_p, 1, 1, 0,
2455 doc: /* Return t if file FILENAME is on a case-insensitive filesystem. 2431 doc: /* Return t if file FILENAME is on a case-insensitive filesystem.
2456The arg must be a string. */) 2432Return nil if FILENAME does not exist or is not on a case-insensitive
2433filesystem, or if there was trouble determining whether the filesystem
2434is case-insensitive. */)
2457 (Lisp_Object filename) 2435 (Lisp_Object filename)
2458{ 2436{
2459 Lisp_Object handler; 2437 Lisp_Object handler;
@@ -2467,19 +2445,16 @@ The arg must be a string. */)
2467 if (!NILP (handler)) 2445 if (!NILP (handler))
2468 return call2 (handler, Qfile_name_case_insensitive_p, filename); 2446 return call2 (handler, Qfile_name_case_insensitive_p, filename);
2469 2447
2470 /* If the file doesn't exist, move up the filesystem tree until we 2448 /* If the file doesn't exist or there is trouble checking its
2471 reach an existing directory or the root. */ 2449 filesystem, move up the filesystem tree until we reach an
2450 existing, trouble-free directory or the root. */
2472 while (true) 2451 while (true)
2473 { 2452 {
2474 int err = file_name_case_insensitive_err (filename); 2453 int err = file_name_case_insensitive_err (filename);
2475 switch (err) 2454 if (err <= 0)
2476 { 2455 return err < 0 ? Qt : Qnil;
2477 case -1: return Qt;
2478 default: return file_test_errno (filename, err);
2479 case ENOENT: case ENOTDIR: break;
2480 }
2481 Lisp_Object parent = file_name_directory (filename); 2456 Lisp_Object parent = file_name_directory (filename);
2482 /* Avoid infinite loop if the root is reported as non-existing 2457 /* Avoid infinite loop if the root has trouble
2483 (impossible?). */ 2458 (impossible?). */
2484 if (!NILP (Fstring_equal (parent, filename))) 2459 if (!NILP (Fstring_equal (parent, filename)))
2485 return Qnil; 2460 return Qnil;
@@ -2739,8 +2714,7 @@ file_name_absolute_p (char const *filename)
2739} 2714}
2740 2715
2741/* Return t if FILE exists and is accessible via OPERATION and AMODE, 2716/* Return t if FILE exists and is accessible via OPERATION and AMODE,
2742 nil (setting errno) if not. Signal an error if the result cannot 2717 nil (setting errno) if not. */
2743 be determined. */
2744 2718
2745static Lisp_Object 2719static Lisp_Object
2746check_file_access (Lisp_Object file, Lisp_Object operation, int amode) 2720check_file_access (Lisp_Object file, Lisp_Object operation, int amode)
@@ -2758,22 +2732,13 @@ check_file_access (Lisp_Object file, Lisp_Object operation, int amode)
2758 } 2732 }
2759 2733
2760 char *encoded_file = SSDATA (ENCODE_FILE (file)); 2734 char *encoded_file = SSDATA (ENCODE_FILE (file));
2761 bool ok = file_access_p (encoded_file, amode); 2735 return file_access_p (encoded_file, amode) ? Qt : Qnil;
2762 if (ok)
2763 return Qt;
2764 int err = errno;
2765 if (err == EROFS || err == ETXTBSY
2766 || (PICKY_EACCES && err == EACCES && amode != F_OK
2767 && file_access_p (encoded_file, F_OK)))
2768 {
2769 errno = err;
2770 return Qnil;
2771 }
2772 return file_test_errno (file, err);
2773} 2736}
2774 2737
2775DEFUN ("file-exists-p", Ffile_exists_p, Sfile_exists_p, 1, 1, 0, 2738DEFUN ("file-exists-p", Ffile_exists_p, Sfile_exists_p, 1, 1, 0,
2776 doc: /* Return t if file FILENAME exists (whether or not you can read it). 2739 doc: /* Return t if file FILENAME exists (whether or not you can read it).
2740Return nil if FILENAME does not exist, or if there was trouble
2741determining whether the file exists.
2777See also `file-readable-p' and `file-attributes'. 2742See also `file-readable-p' and `file-attributes'.
2778This returns nil for a symlink to a nonexistent file. 2743This returns nil for a symlink to a nonexistent file.
2779Use `file-symlink-p' to test for such links. */) 2744Use `file-symlink-p' to test for such links. */)
@@ -2834,16 +2799,7 @@ DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
2834 should check ACLs though, which do affect this. */ 2799 should check ACLs though, which do affect this. */
2835 return file_directory_p (encoded) ? Qt : Qnil; 2800 return file_directory_p (encoded) ? Qt : Qnil;
2836#else 2801#else
2837 if (file_access_p (SSDATA (encoded), W_OK | X_OK)) 2802 return file_access_p (SSDATA (encoded), W_OK | X_OK) ? Qt : Qnil;
2838 return Qt;
2839 int err = errno;
2840 if (err == EROFS
2841 || (err == EACCES && file_access_p (SSDATA (encoded), F_OK)))
2842 {
2843 errno = err;
2844 return Qnil;
2845 }
2846 return file_test_errno (absname, err);
2847#endif 2803#endif
2848} 2804}
2849 2805
@@ -2919,7 +2875,8 @@ check_emacs_readlinkat (int fd, Lisp_Object file, char const *encoded_file)
2919DEFUN ("file-symlink-p", Ffile_symlink_p, Sfile_symlink_p, 1, 1, 0, 2875DEFUN ("file-symlink-p", Ffile_symlink_p, Sfile_symlink_p, 1, 1, 0,
2920 doc: /* Return non-nil if file FILENAME is the name of a symbolic link. 2876 doc: /* Return non-nil if file FILENAME is the name of a symbolic link.
2921The value is the link target, as a string. 2877The value is the link target, as a string.
2922Otherwise it returns nil. 2878Return nil if FILENAME does not exist or is not a symbolic link,
2879of there was trouble determining whether the file is a symbolic link.
2923 2880
2924This function does not check whether the link target exists. */) 2881This function does not check whether the link target exists. */)
2925 (Lisp_Object filename) 2882 (Lisp_Object filename)
@@ -2935,12 +2892,13 @@ This function does not check whether the link target exists. */)
2935 if (!NILP (handler)) 2892 if (!NILP (handler))
2936 return call2 (handler, Qfile_symlink_p, filename); 2893 return call2 (handler, Qfile_symlink_p, filename);
2937 2894
2938 return check_emacs_readlinkat (AT_FDCWD, filename, 2895 return emacs_readlinkat (AT_FDCWD, SSDATA (ENCODE_FILE (filename)));
2939 SSDATA (ENCODE_FILE (filename)));
2940} 2896}
2941 2897
2942DEFUN ("file-directory-p", Ffile_directory_p, Sfile_directory_p, 1, 1, 0, 2898DEFUN ("file-directory-p", Ffile_directory_p, Sfile_directory_p, 1, 1, 0,
2943 doc: /* Return t if FILENAME names an existing directory. 2899 doc: /* Return t if FILENAME names an existing directory.
2900Return nil if FILENAME does not name a directory, or if there
2901was trouble determining whether FILENAME is a directory.
2944Symbolic links to directories count as directories. 2902Symbolic links to directories count as directories.
2945See `file-symlink-p' to distinguish symlinks. */) 2903See `file-symlink-p' to distinguish symlinks. */)
2946 (Lisp_Object filename) 2904 (Lisp_Object filename)
@@ -2953,9 +2911,7 @@ See `file-symlink-p' to distinguish symlinks. */)
2953 if (!NILP (handler)) 2911 if (!NILP (handler))
2954 return call2 (handler, Qfile_directory_p, absname); 2912 return call2 (handler, Qfile_directory_p, absname);
2955 2913
2956 if (file_directory_p (absname)) 2914 return file_directory_p (absname) ? Qt : Qnil;
2957 return Qt;
2958 return file_test_errno (absname, errno);
2959} 2915}
2960 2916
2961/* Return true if FILE is a directory or a symlink to a directory. 2917/* Return true if FILE is a directory or a symlink to a directory.
@@ -3040,12 +2996,7 @@ really is a readable and searchable directory. */)
3040 } 2996 }
3041 2997
3042 Lisp_Object encoded_absname = ENCODE_FILE (absname); 2998 Lisp_Object encoded_absname = ENCODE_FILE (absname);
3043 if (file_accessible_directory_p (encoded_absname)) 2999 return file_accessible_directory_p (encoded_absname) ? Qt : Qnil;
3044 return Qt;
3045 int err = errno;
3046 if (err == EACCES && file_access_p (SSDATA (encoded_absname), F_OK))
3047 return Qnil;
3048 return file_test_errno (absname, err);
3049} 3000}
3050 3001
3051/* If FILE is a searchable directory or a symlink to a 3002/* If FILE is a searchable directory or a symlink to a
@@ -3108,6 +3059,8 @@ file_accessible_directory_p (Lisp_Object file)
3108DEFUN ("file-regular-p", Ffile_regular_p, Sfile_regular_p, 1, 1, 0, 3059DEFUN ("file-regular-p", Ffile_regular_p, Sfile_regular_p, 1, 1, 0,
3109 doc: /* Return t if FILENAME names a regular file. 3060 doc: /* Return t if FILENAME names a regular file.
3110This is the sort of file that holds an ordinary stream of data bytes. 3061This is the sort of file that holds an ordinary stream of data bytes.
3062Return nil if FILENAME does not exist or is not a regular file,
3063or there was trouble determining whether FILENAME is a regular file.
3111Symbolic links to regular files count as regular files. 3064Symbolic links to regular files count as regular files.
3112See `file-symlink-p' to distinguish symlinks. */) 3065See `file-symlink-p' to distinguish symlinks. */)
3113 (Lisp_Object filename) 3066 (Lisp_Object filename)
@@ -3133,9 +3086,7 @@ See `file-symlink-p' to distinguish symlinks. */)
3133 Vw32_get_true_file_attributes = true_attributes; 3086 Vw32_get_true_file_attributes = true_attributes;
3134#endif 3087#endif
3135 3088
3136 if (stat_result == 0) 3089 return stat_result == 0 && S_ISREG (st.st_mode) ? Qt : Qnil;
3137 return S_ISREG (st.st_mode) ? Qt : Qnil;
3138 return file_test_errno (absname, errno);
3139} 3090}
3140 3091
3141DEFUN ("file-selinux-context", Ffile_selinux_context, 3092DEFUN ("file-selinux-context", Ffile_selinux_context,
@@ -3541,20 +3492,15 @@ otherwise, if FILE2 does not exist, the answer is t. */)
3541 { 3492 {
3542 err1 = errno; 3493 err1 = errno;
3543 if (err1 != EOVERFLOW) 3494 if (err1 != EOVERFLOW)
3544 return file_test_errno (absname1, err1); 3495 return file_attribute_errno (absname1, err1);
3545 } 3496 }
3546
3547 if (stat (SSDATA (ENCODE_FILE (absname2)), &st2) != 0) 3497 if (stat (SSDATA (ENCODE_FILE (absname2)), &st2) != 0)
3548 { 3498 {
3549 file_test_errno (absname2, errno); 3499 file_attribute_errno (absname2, errno);
3550 return Qt; 3500 return Qt;
3551 } 3501 }
3552
3553 if (err1) 3502 if (err1)
3554 { 3503 file_attribute_errno (absname1, err1);
3555 file_test_errno (absname1, err1);
3556 eassume (false);
3557 }
3558 3504
3559 return (timespec_cmp (get_stat_mtime (&st2), get_stat_mtime (&st1)) < 0 3505 return (timespec_cmp (get_stat_mtime (&st2), get_stat_mtime (&st1)) < 0
3560 ? Qt : Qnil); 3506 ? Qt : Qnil);
diff --git a/src/lisp.h b/src/lisp.h
index b081ae1cee8..e68d2732e21 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4315,7 +4315,6 @@ extern AVOID report_file_errno (const char *, Lisp_Object, int);
4315extern AVOID report_file_error (const char *, Lisp_Object); 4315extern AVOID report_file_error (const char *, Lisp_Object);
4316extern AVOID report_file_notify_error (const char *, Lisp_Object); 4316extern AVOID report_file_notify_error (const char *, Lisp_Object);
4317extern Lisp_Object file_attribute_errno (Lisp_Object, int); 4317extern Lisp_Object file_attribute_errno (Lisp_Object, int);
4318extern Lisp_Object file_test_errno (Lisp_Object, int);
4319extern bool internal_delete_file (Lisp_Object); 4318extern bool internal_delete_file (Lisp_Object);
4320extern Lisp_Object check_emacs_readlinkat (int, Lisp_Object, char const *); 4319extern Lisp_Object check_emacs_readlinkat (int, Lisp_Object, char const *);
4321extern bool file_directory_p (Lisp_Object); 4320extern bool file_directory_p (Lisp_Object);
diff --git a/src/lread.c b/src/lread.c
index 4f3446b09db..151731a81d9 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -1343,26 +1343,18 @@ Return t if the file exists and loads successfully. */)
1343 /* openp already checked for newness, no point doing it again. 1343 /* openp already checked for newness, no point doing it again.
1344 FIXME would be nice to get a message when openp 1344 FIXME would be nice to get a message when openp
1345 ignores suffix order due to load_prefer_newer. */ 1345 ignores suffix order due to load_prefer_newer. */
1346 Lisp_Object notfound = found;
1347 if (!load_prefer_newer && is_elc) 1346 if (!load_prefer_newer && is_elc)
1348 { 1347 {
1349 result = stat (SSDATA (efound), &s1); 1348 result = stat (SSDATA (efound), &s1);
1350 int err = errno;
1351 if (result == 0) 1349 if (result == 0)
1352 { 1350 {
1353 SSET (efound, SBYTES (efound) - 1, 0); 1351 SSET (efound, SBYTES (efound) - 1, 0);
1354 result = stat (SSDATA (efound), &s2); 1352 result = stat (SSDATA (efound), &s2);
1355 err = errno;
1356 SSET (efound, SBYTES (efound) - 1, 'c'); 1353 SSET (efound, SBYTES (efound) - 1, 'c');
1357 if (result != 0)
1358 notfound = Fsubstring (found, make_fixnum (0),
1359 make_fixnum (-1));
1360 } 1354 }
1361 if (result != 0) 1355
1362 file_test_errno (notfound, err); 1356 if (result == 0
1363 else if (timespec_cmp (get_stat_mtime (&s1), 1357 && timespec_cmp (get_stat_mtime (&s1), get_stat_mtime (&s2)) < 0)
1364 get_stat_mtime (&s2))
1365 < 0)
1366 { 1358 {
1367 /* Make the progress messages mention that source is newer. */ 1359 /* Make the progress messages mention that source is newer. */
1368 newer = 1; 1360 newer = 1;