summaryrefslogtreecommitdiff
path: root/src/sysdep.c
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2020-01-20 01:08:42 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2020-01-20 01:21:52 -0800
commitb3ad638a60845f17938ff812efcf2b2edfbd8c57 (patch)
treeda4d1f416f9e06fe7f3e3318dd7127a39d812bec /src/sysdep.c
parent6cc1db8174bcbe4fabc3627505a7d945cae7029d (diff)
downloademacs-b3ad638a60845f17938ff812efcf2b2edfbd8c57.tar.gz
Work better if stat etc. are interrupted
Quit or retry if fstat, lstat, stat or openat fail with EINTR. This should fix some bugs on platforms where accessing files via NFS can fail that way (Bug#9256). * src/dired.c (file_attributes): * src/fileio.c (file_directory_p) [O_PATH]: Use emacs_openat instead of openat. * src/dired.c (file_attributes): Use emacs_fstatat instead of fstatat. * src/fileio.c (barf_or_query_if_file_exists, Frename_file): * src/filelock.c (rename_lock_file): Use emacs_fstatat instead of lstat. * src/fileio.c (file_directory_p, Ffile_regular_p, Ffile_modes) (Ffile_newer_than_file_p, Fverify_visited_file_modtime) (Fset_visited_file_modtime, auto_save_1): * src/lread.c (Fload): * src/sysdep.c (get_current_dir_name_or_unreachable): Use emacs_fstatat instead of stat. * src/sysdep.c (emacs_fstatat, emacs_openat): New functions. (emacs_open): Redo in terms of emacs_open.
Diffstat (limited to 'src/sysdep.c')
-rw-r--r--src/sysdep.c36
1 files changed, 31 insertions, 5 deletions
diff --git a/src/sysdep.c b/src/sysdep.c
index c6344d8cec7..e8e8bbfb502 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -312,8 +312,8 @@ get_current_dir_name_or_unreachable (void)
if (pwd
&& (pwdlen = strnlen (pwd, bufsize_max)) < bufsize_max
&& IS_DIRECTORY_SEP (pwd[pwdlen && IS_DEVICE_SEP (pwd[1]) ? 2 : 0])
- && stat (pwd, &pwdstat) == 0
- && stat (".", &dotstat) == 0
+ && emacs_fstatat (AT_FDCWD, pwd, &pwdstat, 0) == 0
+ && emacs_fstatat (AT_FDCWD, ".", &dotstat, 0) == 0
&& dotstat.st_ino == pwdstat.st_ino
&& dotstat.st_dev == pwdstat.st_dev)
{
@@ -2449,7 +2449,27 @@ emacs_abort (void)
}
#endif
-/* Open FILE for Emacs use, using open flags OFLAG and mode MODE.
+/* Assuming the directory DIRFD, store information about FILENAME into *ST,
+ using FLAGS to control how the status is obtained.
+ Do not fail merely because fetching info was interrupted by a signal.
+ Allow the user to quit.
+
+ The type of ST is void * instead of struct stat * because the
+ latter type would be problematic in lisp.h. Some platforms may
+ play tricks like "#define stat stat64" in <sys/stat.h>, and lisp.h
+ does not include <sys/stat.h>. */
+
+int
+emacs_fstatat (int dirfd, char const *filename, void *st, int flags)
+{
+ int r;
+ while ((r = fstatat (dirfd, filename, st, flags)) != 0 && errno == EINTR)
+ maybe_quit ();
+ return r;
+}
+
+/* Assuming the directory DIRFD, open FILE for Emacs use,
+ using open flags OFLAGS and mode MODE.
Use binary I/O on systems that care about text vs binary I/O.
Arrange for subprograms to not inherit the file descriptor.
Prefer a method that is multithread-safe, if available.
@@ -2457,17 +2477,23 @@ emacs_abort (void)
Allow the user to quit. */
int
-emacs_open (const char *file, int oflags, int mode)
+emacs_openat (int dirfd, char const *file, int oflags, int mode)
{
int fd;
if (! (oflags & O_TEXT))
oflags |= O_BINARY;
oflags |= O_CLOEXEC;
- while ((fd = open (file, oflags, mode)) < 0 && errno == EINTR)
+ while ((fd = openat (dirfd, file, oflags, mode)) < 0 && errno == EINTR)
maybe_quit ();
return fd;
}
+int
+emacs_open (char const *file, int oflags, int mode)
+{
+ return emacs_openat (AT_FDCWD, file, oflags, mode);
+}
+
/* Open FILE as a stream for Emacs use, with mode MODE.
Act like emacs_open with respect to threads, signals, and quits. */