summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dired.c4
-rw-r--r--src/fileio.c39
-rw-r--r--src/filelock.c3
-rw-r--r--src/lisp.h2
-rw-r--r--src/lread.c4
-rw-r--r--src/sysdep.c36
6 files changed, 63 insertions, 25 deletions
diff --git a/src/dired.c b/src/dired.c
index 611477aa4ef..f013a4cea03 100644
--- a/src/dired.c
+++ b/src/dired.c
@@ -937,7 +937,7 @@ file_attributes (int fd, char const *name,
int err = EINVAL;
#if defined O_PATH && !defined HAVE_CYGWIN_O_PATH_BUG
- int namefd = openat (fd, name, O_PATH | O_CLOEXEC | O_NOFOLLOW);
+ int namefd = emacs_openat (fd, name, O_PATH | O_CLOEXEC | O_NOFOLLOW, 0);
if (namefd < 0)
err = errno;
else
@@ -970,7 +970,7 @@ file_attributes (int fd, char const *name,
information to be accurate. */
w32_stat_get_owner_group = 1;
#endif
- err = fstatat (fd, name, &s, AT_SYMLINK_NOFOLLOW) == 0 ? 0 : errno;
+ err = emacs_fstatat (fd, name, &s, AT_SYMLINK_NOFOLLOW) == 0 ? 0 : errno;
#ifdef WINDOWSNT
w32_stat_get_owner_group = 0;
#endif
diff --git a/src/fileio.c b/src/fileio.c
index 34934dd6df6..87a17eab425 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -1952,7 +1952,10 @@ barf_or_query_if_file_exists (Lisp_Object absname, bool known_to_exist,
encoded_filename = ENCODE_FILE (absname);
- if (! known_to_exist && lstat (SSDATA (encoded_filename), &statbuf) == 0)
+ if (! known_to_exist
+ && (emacs_fstatat (AT_FDCWD, SSDATA (encoded_filename),
+ &statbuf, AT_SYMLINK_NOFOLLOW)
+ == 0))
{
if (S_ISDIR (statbuf.st_mode))
xsignal2 (Qfile_error,
@@ -2555,7 +2558,9 @@ This is what happens in interactive use with M-x. */)
bool dirp = !NILP (Fdirectory_name_p (file));
if (!dirp)
{
- if (lstat (SSDATA (encoded_file), &file_st) != 0)
+ if (emacs_fstatat (AT_FDCWD, SSDATA (encoded_file),
+ &file_st, AT_SYMLINK_NOFOLLOW)
+ != 0)
report_file_error ("Renaming", list2 (file, newname));
dirp = S_ISDIR (file_st.st_mode) != 0;
}
@@ -2928,7 +2933,8 @@ file_directory_p (Lisp_Object file)
#else
# ifdef O_PATH
/* Use O_PATH if available, as it avoids races and EOVERFLOW issues. */
- int fd = openat (AT_FDCWD, SSDATA (file), O_PATH | O_CLOEXEC | O_DIRECTORY);
+ int fd = emacs_openat (AT_FDCWD, SSDATA (file),
+ O_PATH | O_CLOEXEC | O_DIRECTORY, 0);
if (0 <= fd)
{
emacs_close (fd);
@@ -2939,9 +2945,9 @@ file_directory_p (Lisp_Object file)
/* O_PATH is defined but evidently this Linux kernel predates 2.6.39.
Fall back on generic POSIX code. */
# endif
- /* Use file_accessible_directory_p, as it avoids stat EOVERFLOW
+ /* Use file_accessible_directory_p, as it avoids fstatat EOVERFLOW
problems and could be cheaper. However, if it fails because FILE
- is inaccessible, fall back on stat; if the latter fails with
+ is inaccessible, fall back on fstatat; if the latter fails with
EOVERFLOW then FILE must have been a directory unless a race
condition occurred (a problem hard to work around portably). */
if (file_accessible_directory_p (file))
@@ -2949,7 +2955,7 @@ file_directory_p (Lisp_Object file)
if (errno != EACCES)
return false;
struct stat st;
- if (stat (SSDATA (file), &st) != 0)
+ if (emacs_fstatat (AT_FDCWD, SSDATA (file), &st, 0) != 0)
return errno == EOVERFLOW;
if (S_ISDIR (st.st_mode))
return true;
@@ -3080,7 +3086,7 @@ See `file-symlink-p' to distinguish symlinks. */)
Vw32_get_true_file_attributes = Qt;
#endif
- int stat_result = stat (SSDATA (absname), &st);
+ int stat_result = emacs_fstatat (AT_FDCWD, SSDATA (absname), &st, 0);
#ifdef WINDOWSNT
Vw32_get_true_file_attributes = true_attributes;
@@ -3340,7 +3346,7 @@ Return nil if FILENAME does not exist. */)
if (!NILP (handler))
return call2 (handler, Qfile_modes, absname);
- if (stat (SSDATA (ENCODE_FILE (absname)), &st) != 0)
+ if (emacs_fstatat (AT_FDCWD, SSDATA (ENCODE_FILE (absname)), &st, 0) != 0)
return file_attribute_errno (absname, errno);
return make_fixnum (st.st_mode & 07777);
}
@@ -3486,7 +3492,7 @@ otherwise, if FILE2 does not exist, the answer is t. */)
return call3 (handler, Qfile_newer_than_file_p, absname1, absname2);
int err1;
- if (stat (SSDATA (ENCODE_FILE (absname1)), &st1) == 0)
+ if (emacs_fstatat (AT_FDCWD, SSDATA (ENCODE_FILE (absname1)), &st1, 0) == 0)
err1 = 0;
else
{
@@ -3494,7 +3500,7 @@ otherwise, if FILE2 does not exist, the answer is t. */)
if (err1 != EOVERFLOW)
return file_attribute_errno (absname1, err1);
}
- if (stat (SSDATA (ENCODE_FILE (absname2)), &st2) != 0)
+ if (emacs_fstatat (AT_FDCWD, SSDATA (ENCODE_FILE (absname2)), &st2, 0) != 0)
{
file_attribute_errno (absname2, errno);
return Qt;
@@ -3880,7 +3886,7 @@ by calling `format-decode', which see. */)
if (end_offset < 0)
buffer_overflow ();
- /* The file size returned from stat may be zero, but data
+ /* The file size returned from fstat may be zero, but data
may be readable nonetheless, for example when this is a
file in the /proc filesystem. */
if (end_offset == 0)
@@ -5625,7 +5631,7 @@ See Info node `(elisp)Modification Time' for more details. */)
filename = ENCODE_FILE (BVAR (b, filename));
- mtime = (stat (SSDATA (filename), &st) == 0
+ mtime = (emacs_fstatat (AT_FDCWD, SSDATA (filename), &st, 0) == 0
? get_stat_mtime (&st)
: time_error_value (errno));
if (timespec_cmp (mtime, b->modtime) == 0
@@ -5689,7 +5695,8 @@ in `current-time' or an integer flag as returned by `visited-file-modtime'. */)
/* The handler can find the file name the same way we did. */
return call2 (handler, Qset_visited_file_modtime, Qnil);
- if (stat (SSDATA (ENCODE_FILE (filename)), &st) == 0)
+ if (emacs_fstatat (AT_FDCWD, SSDATA (ENCODE_FILE (filename)), &st, 0)
+ == 0)
{
current_buffer->modtime = get_stat_mtime (&st);
current_buffer->modtime_size = st.st_size;
@@ -5728,12 +5735,14 @@ auto_save_1 (void)
/* Get visited file's mode to become the auto save file's mode. */
if (! NILP (BVAR (current_buffer, filename)))
{
- if (stat (SSDATA (BVAR (current_buffer, filename)), &st) >= 0)
+ if (emacs_fstatat (AT_FDCWD, SSDATA (BVAR (current_buffer, filename)),
+ &st, 0)
+ == 0)
/* But make sure we can overwrite it later! */
auto_save_mode_bits = (st.st_mode | 0600) & 0777;
else if (modes = Ffile_modes (BVAR (current_buffer, filename)),
FIXNUMP (modes))
- /* Remote files don't cooperate with stat. */
+ /* Remote files don't cooperate with fstatat. */
auto_save_mode_bits = (XFIXNUM (modes) | 0600) & 0777;
}
diff --git a/src/filelock.c b/src/filelock.c
index b28f16e9b5a..73202f0b2c4 100644
--- a/src/filelock.c
+++ b/src/filelock.c
@@ -347,7 +347,8 @@ rename_lock_file (char const *old, char const *new, bool force)
potential race condition since some other process may create
NEW immediately after the existence check, but it's the best
we can portably do here. */
- if (lstat (new, &st) == 0 || errno == EOVERFLOW)
+ if (emacs_fstatat (AT_FDCWD, new, &st, AT_SYMLINK_NOFOLLOW) == 0
+ || errno == EOVERFLOW)
{
errno = EEXIST;
return -1;
diff --git a/src/lisp.h b/src/lisp.h
index 4bcd1228443..0bd375658e2 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4605,6 +4605,8 @@ extern void seed_random (void *, ptrdiff_t);
extern void init_random (void);
extern void emacs_backtrace (int);
extern AVOID emacs_abort (void) NO_INLINE;
+extern int emacs_fstatat (int, char const *, void *, int);
+extern int emacs_openat (int, char const *, int, int);
extern int emacs_open (const char *, int, int);
extern int emacs_pipe (int[2]);
extern int emacs_close (int);
diff --git a/src/lread.c b/src/lread.c
index 4e9860d5dc8..69dd73912bc 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -1353,11 +1353,11 @@ Return t if the file exists and loads successfully. */)
ignores suffix order due to load_prefer_newer. */
if (!load_prefer_newer && is_elc)
{
- result = stat (SSDATA (efound), &s1);
+ result = emacs_fstatat (AT_FDCWD, SSDATA (efound), &s1, 0);
if (result == 0)
{
SSET (efound, SBYTES (efound) - 1, 0);
- result = stat (SSDATA (efound), &s2);
+ result = emacs_fstatat (AT_FDCWD, SSDATA (efound), &s2, 0);
SSET (efound, SBYTES (efound) - 1, 'c');
}
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. */