aboutsummaryrefslogtreecommitdiffstats
path: root/src/fileio.c
diff options
context:
space:
mode:
authorStephen Leake2019-09-18 17:43:28 -0700
committerStephen Leake2019-09-18 17:43:28 -0700
commit34f1035e878a06ad181ff7fc533cd1fa0a565847 (patch)
tree7708b0e62b09571ba5b2c625d810cd932c380508 /src/fileio.c
parentb478444099655f36f7b243e21e8f98051299ca8f (diff)
parent107ce3050fc37b9a13d8304ae1bb73fac9de5f61 (diff)
downloademacs-34f1035e878a06ad181ff7fc533cd1fa0a565847.tar.gz
emacs-34f1035e878a06ad181ff7fc533cd1fa0a565847.zip
Merge commit '107ce3050fc37b9a13d8304ae1bb73fac9de5f61'
Diffstat (limited to 'src/fileio.c')
-rw-r--r--src/fileio.c480
1 files changed, 276 insertions, 204 deletions
diff --git a/src/fileio.c b/src/fileio.c
index 968a55e5956..5337ea5c800 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -134,60 +134,45 @@ static dev_t timestamp_file_system;
134 is added here. */ 134 is added here. */
135static Lisp_Object Vwrite_region_annotation_buffers; 135static Lisp_Object Vwrite_region_annotation_buffers;
136 136
137static Lisp_Object file_name_directory (Lisp_Object);
137static bool a_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t, 138static bool a_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t,
138 Lisp_Object *, struct coding_system *); 139 Lisp_Object *, struct coding_system *);
139static bool e_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t, 140static bool e_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t,
140 struct coding_system *); 141 struct coding_system *);
141 142
142 143
143/* Return true if FILENAME exists, otherwise return false and set errno. */ 144/* Test whether FILE is accessible for AMODE.
145 Return true if successful, false (setting errno) otherwise. */
144 146
145static bool 147bool
146check_existing (const char *filename) 148file_access_p (char const *file, int amode)
147{
148 return faccessat (AT_FDCWD, filename, F_OK, AT_EACCESS) == 0;
149}
150
151/* Return true if file FILENAME exists and can be executed. */
152
153static bool
154check_executable (char *filename)
155{
156 return faccessat (AT_FDCWD, filename, X_OK, AT_EACCESS) == 0;
157}
158
159/* Return true if file FILENAME exists and can be accessed
160 according to AMODE, which should include W_OK.
161 On failure, return false and set errno. */
162
163static bool
164check_writable (const char *filename, int amode)
165{ 149{
166#ifdef MSDOS 150#ifdef MSDOS
167 /* FIXME: an faccessat implementation should be added to the 151 if (amode & W_OK)
168 DOS/Windows ports and this #ifdef branch should be removed. */
169 struct stat st;
170 if (stat (filename, &st) < 0)
171 return 0;
172 errno = EPERM;
173 return (st.st_mode & S_IWRITE || S_ISDIR (st.st_mode));
174#else /* not MSDOS */
175 bool res = faccessat (AT_FDCWD, filename, amode, AT_EACCESS) == 0;
176#ifdef CYGWIN
177 /* faccessat may have returned failure because Cygwin couldn't
178 determine the file's UID or GID; if so, we return success. */
179 if (!res)
180 { 152 {
181 int faccessat_errno = errno; 153 /* FIXME: The MS-DOS faccessat implementation should handle this. */
182 struct stat st; 154 struct stat st;
183 if (stat (filename, &st) < 0) 155 if (stat (file, &st) != 0)
184 return 0; 156 return false;
185 res = (st.st_uid == -1 || st.st_gid == -1); 157 errno = EPERM;
186 errno = faccessat_errno; 158 return st.st_mode & S_IWRITE || S_ISDIR (st.st_mode);
187 } 159 }
188#endif /* CYGWIN */ 160#endif
189 return res; 161
190#endif /* not MSDOS */ 162 if (faccessat (AT_FDCWD, file, amode, AT_EACCESS) == 0)
163 return true;
164
165#ifdef CYGWIN
166 /* Return success if faccessat failed because Cygwin couldn't
167 determine the file's UID or GID. */
168 int err = errno;
169 struct stat st;
170 if (stat (file, &st) == 0 && (st.st_uid == -1 || st.st_gid == -1))
171 return true;
172 errno = err;
173#endif
174
175 return false;
191} 176}
192 177
193/* Signal a file-access failure. STRING describes the failure, 178/* Signal a file-access failure. STRING describes the failure,
@@ -250,6 +235,44 @@ report_file_notify_error (const char *string, Lisp_Object name)
250} 235}
251#endif 236#endif
252 237
238/* ACTION failed for FILE with errno ERR. Signal an error if ERR
239 means the file's metadata could not be retrieved even though it may
240 exist, otherwise return nil. */
241
242static Lisp_Object
243file_metadata_errno (char const *action, Lisp_Object file, int err)
244{
245 if (err == ENOENT || err == ENOTDIR || err == 0)
246 return Qnil;
247 report_file_errno (action, file, err);
248}
249
250Lisp_Object
251file_attribute_errno (Lisp_Object file, int err)
252{
253 return file_metadata_errno ("Getting attributes", file, err);
254}
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, such errors are common enough that signaling them can be
261 annoying even if the errors are real (e.g., Bug#37445). So return
262 nil for EACCES unless compiling with -DPICKY_EACCES, which is off
263 by default. */
264#ifndef PICKY_EACCES
265enum { PICKY_EACCES = false };
266#endif
267
268Lisp_Object
269file_test_errno (Lisp_Object file, int err)
270{
271 if (!PICKY_EACCES && err == EACCES)
272 return Qnil;
273 return file_metadata_errno ("Testing file", file, err);
274}
275
253void 276void
254close_file_unwind (int fd) 277close_file_unwind (int fd)
255{ 278{
@@ -356,6 +379,15 @@ Given a Unix syntax file name, returns a string ending in slash. */)
356 return STRINGP (handled_name) ? handled_name : Qnil; 379 return STRINGP (handled_name) ? handled_name : Qnil;
357 } 380 }
358 381
382 return file_name_directory (filename);
383}
384
385/* Return the directory component of FILENAME, or nil if FILENAME does
386 not contain a directory component. */
387
388static Lisp_Object
389file_name_directory (Lisp_Object filename)
390{
359 char *beg = SSDATA (filename); 391 char *beg = SSDATA (filename);
360 char const *p = beg + SBYTES (filename); 392 char const *p = beg + SBYTES (filename);
361 393
@@ -2369,41 +2401,48 @@ internal_delete_file (Lisp_Object filename)
2369 return NILP (tem); 2401 return NILP (tem);
2370} 2402}
2371 2403
2372/* Filesystems are case-sensitive on all supported systems except 2404/* Return -1 if FILE is a case-insensitive file name, 0 if not,
2373 MS-Windows, MS-DOS, Cygwin, and Mac OS X. They are always 2405 and a positive errno value if the result cannot be determined. */
2374 case-insensitive on the first two, but they may or may not be
2375 case-insensitive on Cygwin and OS X. The following function
2376 attempts to provide a runtime test on those two systems. If the
2377 test is not conclusive, we assume case-insensitivity on Cygwin and
2378 case-sensitivity on Mac OS X.
2379
2380 FIXME: Mounted filesystems on Posix hosts, like Samba shares or
2381 NFS-mounted Windows volumes, might be case-insensitive. Can we
2382 detect this? */
2383 2406
2384static bool 2407static int
2385file_name_case_insensitive_p (const char *filename) 2408file_name_case_insensitive_err (Lisp_Object file)
2386{ 2409{
2387 /* Use pathconf with _PC_CASE_INSENSITIVE or _PC_CASE_SENSITIVE if 2410 /* Filesystems are case-sensitive on all supported systems except
2388 those flags are available. As of this writing (2017-05-20), 2411 MS-Windows, MS-DOS, Cygwin, and macOS. They are always
2412 case-insensitive on the first two, but they may or may not be
2413 case-insensitive on Cygwin and macOS so do a runtime test on
2414 those two systems. If the test is not conclusive, assume
2415 case-insensitivity on Cygwin and case-sensitivity on macOS.
2416
2417 FIXME: Mounted filesystems on Posix hosts, like Samba shares or
2418 NFS-mounted Windows volumes, might be case-insensitive. Can we
2419 detect this?
2420
2421 Use pathconf with _PC_CASE_INSENSITIVE or _PC_CASE_SENSITIVE if
2422 those flags are available. As of this writing (2019-09-15),
2389 Cygwin is the only platform known to support the former (starting 2423 Cygwin is the only platform known to support the former (starting
2390 with Cygwin-2.6.1), and macOS is the only platform known to 2424 with Cygwin-2.6.1), and macOS is the only platform known to
2391 support the latter. */ 2425 support the latter. */
2392 2426
2393#ifdef _PC_CASE_INSENSITIVE 2427#if defined _PC_CASE_INSENSITIVE || defined _PC_CASE_SENSITIVE
2394 int res = pathconf (filename, _PC_CASE_INSENSITIVE); 2428 char *filename = SSDATA (ENCODE_FILE (file));
2429# ifdef _PC_CASE_INSENSITIVE
2430 long int res = pathconf (filename, _PC_CASE_INSENSITIVE);
2395 if (res >= 0) 2431 if (res >= 0)
2396 return res > 0; 2432 return - (res > 0);
2397#elif defined _PC_CASE_SENSITIVE 2433# else
2398 int res = pathconf (filename, _PC_CASE_SENSITIVE); 2434 long int res = pathconf (filename, _PC_CASE_SENSITIVE);
2399 if (res >= 0) 2435 if (res >= 0)
2400 return res == 0; 2436 return - (res == 0);
2437# endif
2438 if (errno != EINVAL)
2439 return errno;
2401#endif 2440#endif
2402 2441
2403#if defined CYGWIN || defined DOS_NT 2442#if defined CYGWIN || defined DOS_NT
2404 return true; 2443 return -1;
2405#else 2444#else
2406 return false; 2445 return 0;
2407#endif 2446#endif
2408} 2447}
2409 2448
@@ -2426,21 +2465,22 @@ The arg must be a string. */)
2426 2465
2427 /* If the file doesn't exist, move up the filesystem tree until we 2466 /* If the file doesn't exist, move up the filesystem tree until we
2428 reach an existing directory or the root. */ 2467 reach an existing directory or the root. */
2429 if (NILP (Ffile_exists_p (filename))) 2468 while (true)
2430 { 2469 {
2431 filename = Ffile_name_directory (filename); 2470 int err = file_name_case_insensitive_err (filename);
2432 while (NILP (Ffile_exists_p (filename))) 2471 switch (err)
2433 { 2472 {
2434 Lisp_Object newname = expand_and_dir_to_file (filename); 2473 case -1: return Qt;
2435 /* Avoid infinite loop if the root is reported as non-existing 2474 default: return file_test_errno (filename, err);
2436 (impossible?). */ 2475 case ENOENT: case ENOTDIR: break;
2437 if (!NILP (Fstring_equal (newname, filename)))
2438 break;
2439 filename = newname;
2440 } 2476 }
2477 Lisp_Object parent = file_name_directory (filename);
2478 /* Avoid infinite loop if the root is reported as non-existing
2479 (impossible?). */
2480 if (!NILP (Fstring_equal (parent, filename)))
2481 return Qnil;
2482 filename = parent;
2441 } 2483 }
2442 filename = ENCODE_FILE (filename);
2443 return file_name_case_insensitive_p (SSDATA (filename)) ? Qt : Qnil;
2444} 2484}
2445 2485
2446DEFUN ("rename-file", Frename_file, Srename_file, 2, 3, 2486DEFUN ("rename-file", Frename_file, Srename_file, 2, 3,
@@ -2546,7 +2586,7 @@ This is what happens in interactive use with M-x. */)
2546 { 2586 {
2547 Lisp_Object symlink_target 2587 Lisp_Object symlink_target
2548 = (S_ISLNK (file_st.st_mode) 2588 = (S_ISLNK (file_st.st_mode)
2549 ? emacs_readlinkat (AT_FDCWD, SSDATA (encoded_file)) 2589 ? check_emacs_readlinkat (AT_FDCWD, file, SSDATA (encoded_file))
2550 : Qnil); 2590 : Qnil);
2551 if (!NILP (symlink_target)) 2591 if (!NILP (symlink_target))
2552 Fmake_symbolic_link (symlink_target, newname, ok_if_already_exists); 2592 Fmake_symbolic_link (symlink_target, newname, ok_if_already_exists);
@@ -2694,32 +2734,48 @@ file_name_absolute_p (char const *filename)
2694 || user_homedir (&filename[1])))); 2734 || user_homedir (&filename[1]))));
2695} 2735}
2696 2736
2697DEFUN ("file-exists-p", Ffile_exists_p, Sfile_exists_p, 1, 1, 0, 2737/* Return t if FILE exists and is accessible via OPERATION and AMODE,
2698 doc: /* Return t if file FILENAME exists (whether or not you can read it). 2738 nil (setting errno) if not. Signal an error if the result cannot
2699See also `file-readable-p' and `file-attributes'. 2739 be determined. */
2700This returns nil for a symlink to a nonexistent file.
2701Use `file-symlink-p' to test for such links. */)
2702 (Lisp_Object filename)
2703{
2704 Lisp_Object absname;
2705 Lisp_Object handler;
2706 2740
2707 CHECK_STRING (filename); 2741static Lisp_Object
2708 absname = Fexpand_file_name (filename, Qnil); 2742check_file_access (Lisp_Object file, Lisp_Object operation, int amode)
2709 2743{
2710 /* If the file name has special constructs in it, 2744 file = Fexpand_file_name (file, Qnil);
2711 call the corresponding file name handler. */ 2745 Lisp_Object handler = Ffind_file_name_handler (file, operation);
2712 handler = Ffind_file_name_handler (absname, Qfile_exists_p);
2713 if (!NILP (handler)) 2746 if (!NILP (handler))
2714 { 2747 {
2715 Lisp_Object result = call2 (handler, Qfile_exists_p, absname); 2748 Lisp_Object ok = call2 (handler, operation, file);
2749 /* This errno value is bogus. Any caller that depends on errno
2750 should be rethought anyway, to avoid a race between testing a
2751 handled file's accessibility and using the file. */
2716 errno = 0; 2752 errno = 0;
2717 return result; 2753 return ok;
2718 } 2754 }
2719 2755
2720 absname = ENCODE_FILE (absname); 2756 char *encoded_file = SSDATA (ENCODE_FILE (file));
2757 bool ok = file_access_p (encoded_file, amode);
2758 if (ok)
2759 return Qt;
2760 int err = errno;
2761 if (err == EROFS || err == ETXTBSY
2762 || (PICKY_EACCES && err == EACCES && amode != F_OK
2763 && file_access_p (encoded_file, F_OK)))
2764 {
2765 errno = err;
2766 return Qnil;
2767 }
2768 return file_test_errno (file, err);
2769}
2721 2770
2722 return check_existing (SSDATA (absname)) ? Qt : Qnil; 2771DEFUN ("file-exists-p", Ffile_exists_p, Sfile_exists_p, 1, 1, 0,
2772 doc: /* Return t if file FILENAME exists (whether or not you can read it).
2773See also `file-readable-p' and `file-attributes'.
2774This returns nil for a symlink to a nonexistent file.
2775Use `file-symlink-p' to test for such links. */)
2776 (Lisp_Object filename)
2777{
2778 return check_file_access (filename, Qfile_exists_p, F_OK);
2723} 2779}
2724 2780
2725DEFUN ("file-executable-p", Ffile_executable_p, Sfile_executable_p, 1, 1, 0, 2781DEFUN ("file-executable-p", Ffile_executable_p, Sfile_executable_p, 1, 1, 0,
@@ -2729,21 +2785,7 @@ For a directory, this means you can access files in that directory.
2729purpose, though.) */) 2785purpose, though.) */)
2730 (Lisp_Object filename) 2786 (Lisp_Object filename)
2731{ 2787{
2732 Lisp_Object absname; 2788 return check_file_access (filename, Qfile_executable_p, X_OK);
2733 Lisp_Object handler;
2734
2735 CHECK_STRING (filename);
2736 absname = Fexpand_file_name (filename, Qnil);
2737
2738 /* If the file name has special constructs in it,
2739 call the corresponding file name handler. */
2740 handler = Ffind_file_name_handler (absname, Qfile_executable_p);
2741 if (!NILP (handler))
2742 return call2 (handler, Qfile_executable_p, absname);
2743
2744 absname = ENCODE_FILE (absname);
2745
2746 return (check_executable (SSDATA (absname)) ? Qt : Qnil);
2747} 2789}
2748 2790
2749DEFUN ("file-readable-p", Ffile_readable_p, Sfile_readable_p, 1, 1, 0, 2791DEFUN ("file-readable-p", Ffile_readable_p, Sfile_readable_p, 1, 1, 0,
@@ -2751,21 +2793,7 @@ DEFUN ("file-readable-p", Ffile_readable_p, Sfile_readable_p, 1, 1, 0,
2751See also `file-exists-p' and `file-attributes'. */) 2793See also `file-exists-p' and `file-attributes'. */)
2752 (Lisp_Object filename) 2794 (Lisp_Object filename)
2753{ 2795{
2754 Lisp_Object absname; 2796 return check_file_access (filename, Qfile_readable_p, R_OK);
2755 Lisp_Object handler;
2756
2757 CHECK_STRING (filename);
2758 absname = Fexpand_file_name (filename, Qnil);
2759
2760 /* If the file name has special constructs in it,
2761 call the corresponding file name handler. */
2762 handler = Ffind_file_name_handler (absname, Qfile_readable_p);
2763 if (!NILP (handler))
2764 return call2 (handler, Qfile_readable_p, absname);
2765
2766 absname = ENCODE_FILE (absname);
2767 return (faccessat (AT_FDCWD, SSDATA (absname), R_OK, AT_EACCESS) == 0
2768 ? Qt : Qnil);
2769} 2797}
2770 2798
2771DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0, 2799DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
@@ -2775,7 +2803,6 @@ DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
2775 Lisp_Object absname, dir, encoded; 2803 Lisp_Object absname, dir, encoded;
2776 Lisp_Object handler; 2804 Lisp_Object handler;
2777 2805
2778 CHECK_STRING (filename);
2779 absname = Fexpand_file_name (filename, Qnil); 2806 absname = Fexpand_file_name (filename, Qnil);
2780 2807
2781 /* If the file name has special constructs in it, 2808 /* If the file name has special constructs in it,
@@ -2785,25 +2812,34 @@ DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
2785 return call2 (handler, Qfile_writable_p, absname); 2812 return call2 (handler, Qfile_writable_p, absname);
2786 2813
2787 encoded = ENCODE_FILE (absname); 2814 encoded = ENCODE_FILE (absname);
2788 if (check_writable (SSDATA (encoded), W_OK)) 2815 if (file_access_p (SSDATA (encoded), W_OK))
2789 return Qt; 2816 return Qt;
2790 if (errno != ENOENT) 2817 if (errno != ENOENT)
2791 return Qnil; 2818 return Qnil;
2792 2819
2793 dir = Ffile_name_directory (absname); 2820 dir = file_name_directory (absname);
2794 eassert (!NILP (dir)); 2821 eassert (!NILP (dir));
2795#ifdef MSDOS 2822#ifdef MSDOS
2796 dir = Fdirectory_file_name (dir); 2823 dir = Fdirectory_file_name (dir);
2797#endif /* MSDOS */ 2824#endif /* MSDOS */
2798 2825
2799 dir = ENCODE_FILE (dir); 2826 encoded = ENCODE_FILE (dir);
2800#ifdef WINDOWSNT 2827#ifdef WINDOWSNT
2801 /* The read-only attribute of the parent directory doesn't affect 2828 /* The read-only attribute of the parent directory doesn't affect
2802 whether a file or directory can be created within it. Some day we 2829 whether a file or directory can be created within it. Some day we
2803 should check ACLs though, which do affect this. */ 2830 should check ACLs though, which do affect this. */
2804 return file_directory_p (dir) ? Qt : Qnil; 2831 return file_directory_p (encoded) ? Qt : Qnil;
2805#else 2832#else
2806 return check_writable (SSDATA (dir), W_OK | X_OK) ? Qt : Qnil; 2833 if (file_access_p (SSDATA (encoded), W_OK | X_OK))
2834 return Qt;
2835 int err = errno;
2836 if (err == EROFS
2837 || (err == EACCES && file_access_p (SSDATA (encoded), F_OK)))
2838 {
2839 errno = err;
2840 return Qnil;
2841 }
2842 return file_test_errno (absname, err);
2807#endif 2843#endif
2808} 2844}
2809 2845
@@ -2835,8 +2871,8 @@ If there is no error, returns nil. */)
2835} 2871}
2836 2872
2837/* Relative to directory FD, return the symbolic link value of FILENAME. 2873/* Relative to directory FD, return the symbolic link value of FILENAME.
2838 On failure, return nil. */ 2874 On failure, return nil (setting errno). */
2839Lisp_Object 2875static Lisp_Object
2840emacs_readlinkat (int fd, char const *filename) 2876emacs_readlinkat (int fd, char const *filename)
2841{ 2877{
2842 static struct allocator const emacs_norealloc_allocator = 2878 static struct allocator const emacs_norealloc_allocator =
@@ -2855,6 +2891,27 @@ emacs_readlinkat (int fd, char const *filename)
2855 return val; 2891 return val;
2856} 2892}
2857 2893
2894/* Relative to directory FD, return the symbolic link value of FILE.
2895 If FILE is not a symbolic link, return nil (setting errno).
2896 Signal an error if the result cannot be determined. */
2897Lisp_Object
2898check_emacs_readlinkat (int fd, Lisp_Object file, char const *encoded_file)
2899{
2900 Lisp_Object val = emacs_readlinkat (fd, encoded_file);
2901 if (NILP (val))
2902 {
2903 if (errno == EINVAL)
2904 return val;
2905#ifdef CYGWIN
2906 /* Work around Cygwin bugs. */
2907 if (errno == EIO || errno == EACCES)
2908 return val;
2909#endif
2910 return file_metadata_errno ("Reading symbolic link", file, errno);
2911 }
2912 return val;
2913}
2914
2858DEFUN ("file-symlink-p", Ffile_symlink_p, Sfile_symlink_p, 1, 1, 0, 2915DEFUN ("file-symlink-p", Ffile_symlink_p, Sfile_symlink_p, 1, 1, 0,
2859 doc: /* Return non-nil if file FILENAME is the name of a symbolic link. 2916 doc: /* Return non-nil if file FILENAME is the name of a symbolic link.
2860The value is the link target, as a string. 2917The value is the link target, as a string.
@@ -2874,9 +2931,8 @@ This function does not check whether the link target exists. */)
2874 if (!NILP (handler)) 2931 if (!NILP (handler))
2875 return call2 (handler, Qfile_symlink_p, filename); 2932 return call2 (handler, Qfile_symlink_p, filename);
2876 2933
2877 filename = ENCODE_FILE (filename); 2934 return check_emacs_readlinkat (AT_FDCWD, filename,
2878 2935 SSDATA (ENCODE_FILE (filename)));
2879 return emacs_readlinkat (AT_FDCWD, SSDATA (filename));
2880} 2936}
2881 2937
2882DEFUN ("file-directory-p", Ffile_directory_p, Sfile_directory_p, 1, 1, 0, 2938DEFUN ("file-directory-p", Ffile_directory_p, Sfile_directory_p, 1, 1, 0,
@@ -2893,9 +2949,9 @@ See `file-symlink-p' to distinguish symlinks. */)
2893 if (!NILP (handler)) 2949 if (!NILP (handler))
2894 return call2 (handler, Qfile_directory_p, absname); 2950 return call2 (handler, Qfile_directory_p, absname);
2895 2951
2896 absname = ENCODE_FILE (absname); 2952 if (file_directory_p (absname))
2897 2953 return Qt;
2898 return file_directory_p (absname) ? Qt : Qnil; 2954 return file_test_errno (absname, errno);
2899} 2955}
2900 2956
2901/* Return true if FILE is a directory or a symlink to a directory. 2957/* Return true if FILE is a directory or a symlink to a directory.
@@ -2905,7 +2961,10 @@ file_directory_p (Lisp_Object file)
2905{ 2961{
2906#ifdef DOS_NT 2962#ifdef DOS_NT
2907 /* This is cheaper than 'stat'. */ 2963 /* This is cheaper than 'stat'. */
2908 return faccessat (AT_FDCWD, SSDATA (file), D_OK, AT_EACCESS) == 0; 2964 bool retval = faccessat (AT_FDCWD, SSDATA (file), D_OK, AT_EACCESS) == 0;
2965 if (!retval && errno == EACCES)
2966 errno = ENOTDIR; /* like the non-DOS_NT branch below does */
2967 return retval;
2909#else 2968#else
2910# ifdef O_PATH 2969# ifdef O_PATH
2911 /* Use O_PATH if available, as it avoids races and EOVERFLOW issues. */ 2970 /* Use O_PATH if available, as it avoids races and EOVERFLOW issues. */
@@ -2920,7 +2979,7 @@ file_directory_p (Lisp_Object file)
2920 /* O_PATH is defined but evidently this Linux kernel predates 2.6.39. 2979 /* O_PATH is defined but evidently this Linux kernel predates 2.6.39.
2921 Fall back on generic POSIX code. */ 2980 Fall back on generic POSIX code. */
2922# endif 2981# endif
2923 /* Use file_accessible_directory, as it avoids stat EOVERFLOW 2982 /* Use file_accessible_directory_p, as it avoids stat EOVERFLOW
2924 problems and could be cheaper. However, if it fails because FILE 2983 problems and could be cheaper. However, if it fails because FILE
2925 is inaccessible, fall back on stat; if the latter fails with 2984 is inaccessible, fall back on stat; if the latter fails with
2926 EOVERFLOW then FILE must have been a directory unless a race 2985 EOVERFLOW then FILE must have been a directory unless a race
@@ -2976,8 +3035,13 @@ really is a readable and searchable directory. */)
2976 return r; 3035 return r;
2977 } 3036 }
2978 3037
2979 absname = ENCODE_FILE (absname); 3038 Lisp_Object encoded_absname = ENCODE_FILE (absname);
2980 return file_accessible_directory_p (absname) ? Qt : Qnil; 3039 if (file_accessible_directory_p (encoded_absname))
3040 return Qt;
3041 int err = errno;
3042 if (err == EACCES && file_access_p (SSDATA (encoded_absname), F_OK))
3043 return Qnil;
3044 return file_test_errno (absname, err);
2981} 3045}
2982 3046
2983/* If FILE is a searchable directory or a symlink to a 3047/* If FILE is a searchable directory or a symlink to a
@@ -3029,7 +3093,7 @@ file_accessible_directory_p (Lisp_Object file)
3029 dir = buf; 3093 dir = buf;
3030 } 3094 }
3031 3095
3032 ok = check_existing (dir); 3096 ok = file_access_p (dir, F_OK);
3033 saved_errno = errno; 3097 saved_errno = errno;
3034 SAFE_FREE (); 3098 SAFE_FREE ();
3035 errno = saved_errno; 3099 errno = saved_errno;
@@ -3053,27 +3117,21 @@ See `file-symlink-p' to distinguish symlinks. */)
3053 if (!NILP (handler)) 3117 if (!NILP (handler))
3054 return call2 (handler, Qfile_regular_p, absname); 3118 return call2 (handler, Qfile_regular_p, absname);
3055 3119
3056 absname = ENCODE_FILE (absname);
3057
3058#ifdef WINDOWSNT 3120#ifdef WINDOWSNT
3059 { 3121 /* Tell stat to use expensive method to get accurate info. */
3060 int result; 3122 Lisp_Object true_attributes = Vw32_get_true_file_attributes;
3061 Lisp_Object tem = Vw32_get_true_file_attributes; 3123 Vw32_get_true_file_attributes = Qt;
3124#endif
3062 3125
3063 /* Tell stat to use expensive method to get accurate info. */ 3126 int stat_result = stat (SSDATA (absname), &st);
3064 Vw32_get_true_file_attributes = Qt;
3065 result = stat (SSDATA (absname), &st);
3066 Vw32_get_true_file_attributes = tem;
3067 3127
3068 if (result < 0) 3128#ifdef WINDOWSNT
3069 return Qnil; 3129 Vw32_get_true_file_attributes = true_attributes;
3070 return S_ISREG (st.st_mode) ? Qt : Qnil;
3071 }
3072#else
3073 if (stat (SSDATA (absname), &st) < 0)
3074 return Qnil;
3075 return S_ISREG (st.st_mode) ? Qt : Qnil;
3076#endif 3130#endif
3131
3132 if (stat_result == 0)
3133 return S_ISREG (st.st_mode) ? Qt : Qnil;
3134 return file_test_errno (absname, errno);
3077} 3135}
3078 3136
3079DEFUN ("file-selinux-context", Ffile_selinux_context, 3137DEFUN ("file-selinux-context", Ffile_selinux_context,
@@ -3083,7 +3141,7 @@ The return value is a list (USER ROLE TYPE RANGE), where the list
3083elements are strings naming the user, role, type, and range of the 3141elements are strings naming the user, role, type, and range of the
3084file's SELinux security context. 3142file's SELinux security context.
3085 3143
3086Return (nil nil nil nil) if the file is nonexistent or inaccessible, 3144Return (nil nil nil nil) if the file is nonexistent,
3087or if SELinux is disabled, or if Emacs lacks SELinux support. */) 3145or if SELinux is disabled, or if Emacs lacks SELinux support. */)
3088 (Lisp_Object filename) 3146 (Lisp_Object filename)
3089{ 3147{
@@ -3097,13 +3155,11 @@ or if SELinux is disabled, or if Emacs lacks SELinux support. */)
3097 if (!NILP (handler)) 3155 if (!NILP (handler))
3098 return call2 (handler, Qfile_selinux_context, absname); 3156 return call2 (handler, Qfile_selinux_context, absname);
3099 3157
3100 absname = ENCODE_FILE (absname);
3101
3102#if HAVE_LIBSELINUX 3158#if HAVE_LIBSELINUX
3103 if (is_selinux_enabled ()) 3159 if (is_selinux_enabled ())
3104 { 3160 {
3105 security_context_t con; 3161 security_context_t con;
3106 int conlength = lgetfilecon (SSDATA (absname), &con); 3162 int conlength = lgetfilecon (SSDATA (ENCODE_FILE (absname)), &con);
3107 if (conlength > 0) 3163 if (conlength > 0)
3108 { 3164 {
3109 context_t context = context_new (con); 3165 context_t context = context_new (con);
@@ -3118,6 +3174,9 @@ or if SELinux is disabled, or if Emacs lacks SELinux support. */)
3118 context_free (context); 3174 context_free (context);
3119 freecon (con); 3175 freecon (con);
3120 } 3176 }
3177 else if (! (errno == ENOENT || errno == ENOTDIR || errno == ENODATA
3178 || errno == ENOTSUP))
3179 report_file_error ("getting SELinux context", absname);
3121 } 3180 }
3122#endif 3181#endif
3123 3182
@@ -3213,8 +3272,7 @@ DEFUN ("file-acl", Ffile_acl, Sfile_acl, 1, 1, 0,
3213 doc: /* Return ACL entries of file named FILENAME. 3272 doc: /* Return ACL entries of file named FILENAME.
3214The entries are returned in a format suitable for use in `set-file-acl' 3273The entries are returned in a format suitable for use in `set-file-acl'
3215but is otherwise undocumented and subject to change. 3274but is otherwise undocumented and subject to change.
3216Return nil if file does not exist or is not accessible, or if Emacs 3275Return nil if file does not exist. */)
3217was unable to determine the ACL entries. */)
3218 (Lisp_Object filename) 3276 (Lisp_Object filename)
3219{ 3277{
3220 Lisp_Object acl_string = Qnil; 3278 Lisp_Object acl_string = Qnil;
@@ -3229,20 +3287,22 @@ was unable to determine the ACL entries. */)
3229 return call2 (handler, Qfile_acl, absname); 3287 return call2 (handler, Qfile_acl, absname);
3230 3288
3231# ifdef HAVE_ACL_SET_FILE 3289# ifdef HAVE_ACL_SET_FILE
3232 absname = ENCODE_FILE (absname);
3233
3234# ifndef HAVE_ACL_TYPE_EXTENDED 3290# ifndef HAVE_ACL_TYPE_EXTENDED
3235 acl_type_t ACL_TYPE_EXTENDED = ACL_TYPE_ACCESS; 3291 acl_type_t ACL_TYPE_EXTENDED = ACL_TYPE_ACCESS;
3236# endif 3292# endif
3237 acl_t acl = acl_get_file (SSDATA (absname), ACL_TYPE_EXTENDED); 3293 acl_t acl = acl_get_file (SSDATA (ENCODE_FILE (absname)), ACL_TYPE_EXTENDED);
3238 if (acl == NULL) 3294 if (acl == NULL)
3239 return Qnil; 3295 {
3240 3296 if (errno == ENOENT || errno == ENOTDIR || errno == ENOTSUP)
3297 return Qnil;
3298 report_file_error ("Getting ACLs", absname);
3299 }
3241 char *str = acl_to_text (acl, NULL); 3300 char *str = acl_to_text (acl, NULL);
3242 if (str == NULL) 3301 if (str == NULL)
3243 { 3302 {
3303 int err = errno;
3244 acl_free (acl); 3304 acl_free (acl);
3245 return Qnil; 3305 report_file_errno ("Getting ACLs", absname, err);
3246 } 3306 }
3247 3307
3248 acl_string = build_string (str); 3308 acl_string = build_string (str);
@@ -3313,7 +3373,7 @@ support. */)
3313 3373
3314DEFUN ("file-modes", Ffile_modes, Sfile_modes, 1, 1, 0, 3374DEFUN ("file-modes", Ffile_modes, Sfile_modes, 1, 1, 0,
3315 doc: /* Return mode bits of file named FILENAME, as an integer. 3375 doc: /* Return mode bits of file named FILENAME, as an integer.
3316Return nil, if file does not exist or is not accessible. */) 3376Return nil if FILENAME does not exist. */)
3317 (Lisp_Object filename) 3377 (Lisp_Object filename)
3318{ 3378{
3319 struct stat st; 3379 struct stat st;
@@ -3325,11 +3385,8 @@ Return nil, if file does not exist or is not accessible. */)
3325 if (!NILP (handler)) 3385 if (!NILP (handler))
3326 return call2 (handler, Qfile_modes, absname); 3386 return call2 (handler, Qfile_modes, absname);
3327 3387
3328 absname = ENCODE_FILE (absname); 3388 if (stat (SSDATA (ENCODE_FILE (absname)), &st) != 0)
3329 3389 return file_attribute_errno (absname, errno);
3330 if (stat (SSDATA (absname), &st) < 0)
3331 return Qnil;
3332
3333 return make_fixnum (st.st_mode & 07777); 3390 return make_fixnum (st.st_mode & 07777);
3334} 3391}
3335 3392
@@ -3473,14 +3530,27 @@ otherwise, if FILE2 does not exist, the answer is t. */)
3473 if (!NILP (handler)) 3530 if (!NILP (handler))
3474 return call3 (handler, Qfile_newer_than_file_p, absname1, absname2); 3531 return call3 (handler, Qfile_newer_than_file_p, absname1, absname2);
3475 3532
3476 absname1 = ENCODE_FILE (absname1); 3533 int err1;
3477 absname2 = ENCODE_FILE (absname2); 3534 if (stat (SSDATA (ENCODE_FILE (absname1)), &st1) == 0)
3535 err1 = 0;
3536 else
3537 {
3538 err1 = errno;
3539 if (err1 != EOVERFLOW)
3540 return file_test_errno (absname1, err1);
3541 }
3478 3542
3479 if (stat (SSDATA (absname1), &st1) < 0) 3543 if (stat (SSDATA (ENCODE_FILE (absname2)), &st2) != 0)
3480 return Qnil; 3544 {
3545 file_test_errno (absname2, errno);
3546 return Qt;
3547 }
3481 3548
3482 if (stat (SSDATA (absname2), &st2) < 0) 3549 if (err1)
3483 return Qt; 3550 {
3551 file_test_errno (absname1, err1);
3552 eassume (false);
3553 }
3484 3554
3485 return (timespec_cmp (get_stat_mtime (&st2), get_stat_mtime (&st1)) < 0 3555 return (timespec_cmp (get_stat_mtime (&st2), get_stat_mtime (&st1)) < 0
3486 ? Qt : Qnil); 3556 ? Qt : Qnil);
@@ -3612,7 +3682,7 @@ file_offset (Lisp_Object val)
3612static struct timespec 3682static struct timespec
3613time_error_value (int errnum) 3683time_error_value (int errnum)
3614{ 3684{
3615 int ns = (errnum == ENOENT || errnum == EACCES || errnum == ENOTDIR 3685 int ns = (errnum == ENOENT || errnum == ENOTDIR
3616 ? NONEXISTENT_MODTIME_NSECS 3686 ? NONEXISTENT_MODTIME_NSECS
3617 : UNKNOWN_MODTIME_NSECS); 3687 : UNKNOWN_MODTIME_NSECS);
3618 return make_timespec (0, ns); 3688 return make_timespec (0, ns);
@@ -5672,13 +5742,13 @@ in `current-time' or an integer flag as returned by `visited-file-modtime'. */)
5672 /* The handler can find the file name the same way we did. */ 5742 /* The handler can find the file name the same way we did. */
5673 return call2 (handler, Qset_visited_file_modtime, Qnil); 5743 return call2 (handler, Qset_visited_file_modtime, Qnil);
5674 5744
5675 filename = ENCODE_FILE (filename); 5745 if (stat (SSDATA (ENCODE_FILE (filename)), &st) == 0)
5676
5677 if (stat (SSDATA (filename), &st) >= 0)
5678 { 5746 {
5679 current_buffer->modtime = get_stat_mtime (&st); 5747 current_buffer->modtime = get_stat_mtime (&st);
5680 current_buffer->modtime_size = st.st_size; 5748 current_buffer->modtime_size = st.st_size;
5681 } 5749 }
5750 else
5751 file_attribute_errno (filename, errno);
5682 } 5752 }
5683 5753
5684 return Qnil; 5754 return Qnil;
@@ -5822,7 +5892,7 @@ A non-nil CURRENT-ONLY argument means save only current buffer. */)
5822 if (!NILP (Vrun_hooks)) 5892 if (!NILP (Vrun_hooks))
5823 { 5893 {
5824 Lisp_Object dir; 5894 Lisp_Object dir;
5825 dir = Ffile_name_directory (listfile); 5895 dir = file_name_directory (listfile);
5826 if (NILP (Ffile_directory_p (dir))) 5896 if (NILP (Ffile_directory_p (dir)))
5827 internal_condition_case_1 (do_auto_save_make_dir, 5897 internal_condition_case_1 (do_auto_save_make_dir,
5828 dir, Qt, 5898 dir, Qt,
@@ -6067,16 +6137,18 @@ effect except for flushing STREAM's data. */)
6067 6137
6068#ifndef DOS_NT 6138#ifndef DOS_NT
6069 6139
6070/* Yield a Lisp float as close as possible to BLOCKSIZE * BLOCKS, with 6140/* Yield a Lisp number equal to BLOCKSIZE * BLOCKS, with the result
6071 the result negated if NEGATE. */ 6141 negated if NEGATE. */
6072static Lisp_Object 6142static Lisp_Object
6073blocks_to_bytes (uintmax_t blocksize, uintmax_t blocks, bool negate) 6143blocks_to_bytes (uintmax_t blocksize, uintmax_t blocks, bool negate)
6074{ 6144{
6075 /* On typical platforms the following code is accurate to 53 bits, 6145 intmax_t n;
6076 which is close enough. BLOCKSIZE is invariably a power of 2, so 6146 if (!INT_MULTIPLY_WRAPV (blocksize, blocks, &n))
6077 converting it to double does not lose information. */ 6147 return make_int (negate ? -n : n);
6078 double bs = blocksize; 6148 Lisp_Object bs = make_uint (blocksize);
6079 return make_float (negate ? -bs * -blocks : bs * blocks); 6149 if (negate)
6150 bs = CALLN (Fminus, bs);
6151 return CALLN (Ftimes, bs, make_uint (blocks));
6080} 6152}
6081 6153
6082DEFUN ("file-system-info", Ffile_system_info, Sfile_system_info, 1, 1, 0, 6154DEFUN ("file-system-info", Ffile_system_info, Sfile_system_info, 1, 1, 0,
@@ -6087,22 +6159,22 @@ storage available to a non-superuser. All 3 numbers are in bytes.
6087If the underlying system call fails, value is nil. */) 6159If the underlying system call fails, value is nil. */)
6088 (Lisp_Object filename) 6160 (Lisp_Object filename)
6089{ 6161{
6090 Lisp_Object encoded = ENCODE_FILE (Fexpand_file_name (filename, Qnil)); 6162 filename = Fexpand_file_name (filename, Qnil);
6091 6163
6092 /* If the file name has special constructs in it, 6164 /* If the file name has special constructs in it,
6093 call the corresponding file name handler. */ 6165 call the corresponding file name handler. */
6094 Lisp_Object handler = Ffind_file_name_handler (encoded, Qfile_system_info); 6166 Lisp_Object handler = Ffind_file_name_handler (filename, Qfile_system_info);
6095 if (!NILP (handler)) 6167 if (!NILP (handler))
6096 { 6168 {
6097 Lisp_Object result = call2 (handler, Qfile_system_info, encoded); 6169 Lisp_Object result = call2 (handler, Qfile_system_info, filename);
6098 if (CONSP (result) || NILP (result)) 6170 if (CONSP (result) || NILP (result))
6099 return result; 6171 return result;
6100 error ("Invalid handler in `file-name-handler-alist'"); 6172 error ("Invalid handler in `file-name-handler-alist'");
6101 } 6173 }
6102 6174
6103 struct fs_usage u; 6175 struct fs_usage u;
6104 if (get_fs_usage (SSDATA (encoded), NULL, &u) != 0) 6176 if (get_fs_usage (SSDATA (ENCODE_FILE (filename)), NULL, &u) != 0)
6105 return Qnil; 6177 return errno == ENOSYS ? Qnil : file_attribute_errno (filename, errno);
6106 return list3 (blocks_to_bytes (u.fsu_blocksize, u.fsu_blocks, false), 6178 return list3 (blocks_to_bytes (u.fsu_blocksize, u.fsu_blocks, false),
6107 blocks_to_bytes (u.fsu_blocksize, u.fsu_bfree, false), 6179 blocks_to_bytes (u.fsu_blocksize, u.fsu_bfree, false),
6108 blocks_to_bytes (u.fsu_blocksize, u.fsu_bavail, 6180 blocks_to_bytes (u.fsu_blocksize, u.fsu_bavail,