diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/dired.c | 4 | ||||
| -rw-r--r-- | src/fileio.c | 39 | ||||
| -rw-r--r-- | src/filelock.c | 3 | ||||
| -rw-r--r-- | src/lisp.h | 2 | ||||
| -rw-r--r-- | src/lread.c | 4 | ||||
| -rw-r--r-- | src/sysdep.c | 36 |
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, | |||
| 937 | int err = EINVAL; | 937 | int err = EINVAL; |
| 938 | 938 | ||
| 939 | #if defined O_PATH && !defined HAVE_CYGWIN_O_PATH_BUG | 939 | #if defined O_PATH && !defined HAVE_CYGWIN_O_PATH_BUG |
| 940 | int namefd = openat (fd, name, O_PATH | O_CLOEXEC | O_NOFOLLOW); | 940 | int namefd = emacs_openat (fd, name, O_PATH | O_CLOEXEC | O_NOFOLLOW, 0); |
| 941 | if (namefd < 0) | 941 | if (namefd < 0) |
| 942 | err = errno; | 942 | err = errno; |
| 943 | else | 943 | else |
| @@ -970,7 +970,7 @@ file_attributes (int fd, char const *name, | |||
| 970 | information to be accurate. */ | 970 | information to be accurate. */ |
| 971 | w32_stat_get_owner_group = 1; | 971 | w32_stat_get_owner_group = 1; |
| 972 | #endif | 972 | #endif |
| 973 | err = fstatat (fd, name, &s, AT_SYMLINK_NOFOLLOW) == 0 ? 0 : errno; | 973 | err = emacs_fstatat (fd, name, &s, AT_SYMLINK_NOFOLLOW) == 0 ? 0 : errno; |
| 974 | #ifdef WINDOWSNT | 974 | #ifdef WINDOWSNT |
| 975 | w32_stat_get_owner_group = 0; | 975 | w32_stat_get_owner_group = 0; |
| 976 | #endif | 976 | #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, | |||
| 1952 | 1952 | ||
| 1953 | encoded_filename = ENCODE_FILE (absname); | 1953 | encoded_filename = ENCODE_FILE (absname); |
| 1954 | 1954 | ||
| 1955 | if (! known_to_exist && lstat (SSDATA (encoded_filename), &statbuf) == 0) | 1955 | if (! known_to_exist |
| 1956 | && (emacs_fstatat (AT_FDCWD, SSDATA (encoded_filename), | ||
| 1957 | &statbuf, AT_SYMLINK_NOFOLLOW) | ||
| 1958 | == 0)) | ||
| 1956 | { | 1959 | { |
| 1957 | if (S_ISDIR (statbuf.st_mode)) | 1960 | if (S_ISDIR (statbuf.st_mode)) |
| 1958 | xsignal2 (Qfile_error, | 1961 | xsignal2 (Qfile_error, |
| @@ -2555,7 +2558,9 @@ This is what happens in interactive use with M-x. */) | |||
| 2555 | bool dirp = !NILP (Fdirectory_name_p (file)); | 2558 | bool dirp = !NILP (Fdirectory_name_p (file)); |
| 2556 | if (!dirp) | 2559 | if (!dirp) |
| 2557 | { | 2560 | { |
| 2558 | if (lstat (SSDATA (encoded_file), &file_st) != 0) | 2561 | if (emacs_fstatat (AT_FDCWD, SSDATA (encoded_file), |
| 2562 | &file_st, AT_SYMLINK_NOFOLLOW) | ||
| 2563 | != 0) | ||
| 2559 | report_file_error ("Renaming", list2 (file, newname)); | 2564 | report_file_error ("Renaming", list2 (file, newname)); |
| 2560 | dirp = S_ISDIR (file_st.st_mode) != 0; | 2565 | dirp = S_ISDIR (file_st.st_mode) != 0; |
| 2561 | } | 2566 | } |
| @@ -2928,7 +2933,8 @@ file_directory_p (Lisp_Object file) | |||
| 2928 | #else | 2933 | #else |
| 2929 | # ifdef O_PATH | 2934 | # ifdef O_PATH |
| 2930 | /* Use O_PATH if available, as it avoids races and EOVERFLOW issues. */ | 2935 | /* Use O_PATH if available, as it avoids races and EOVERFLOW issues. */ |
| 2931 | int fd = openat (AT_FDCWD, SSDATA (file), O_PATH | O_CLOEXEC | O_DIRECTORY); | 2936 | int fd = emacs_openat (AT_FDCWD, SSDATA (file), |
| 2937 | O_PATH | O_CLOEXEC | O_DIRECTORY, 0); | ||
| 2932 | if (0 <= fd) | 2938 | if (0 <= fd) |
| 2933 | { | 2939 | { |
| 2934 | emacs_close (fd); | 2940 | emacs_close (fd); |
| @@ -2939,9 +2945,9 @@ file_directory_p (Lisp_Object file) | |||
| 2939 | /* O_PATH is defined but evidently this Linux kernel predates 2.6.39. | 2945 | /* O_PATH is defined but evidently this Linux kernel predates 2.6.39. |
| 2940 | Fall back on generic POSIX code. */ | 2946 | Fall back on generic POSIX code. */ |
| 2941 | # endif | 2947 | # endif |
| 2942 | /* Use file_accessible_directory_p, as it avoids stat EOVERFLOW | 2948 | /* Use file_accessible_directory_p, as it avoids fstatat EOVERFLOW |
| 2943 | problems and could be cheaper. However, if it fails because FILE | 2949 | problems and could be cheaper. However, if it fails because FILE |
| 2944 | is inaccessible, fall back on stat; if the latter fails with | 2950 | is inaccessible, fall back on fstatat; if the latter fails with |
| 2945 | EOVERFLOW then FILE must have been a directory unless a race | 2951 | EOVERFLOW then FILE must have been a directory unless a race |
| 2946 | condition occurred (a problem hard to work around portably). */ | 2952 | condition occurred (a problem hard to work around portably). */ |
| 2947 | if (file_accessible_directory_p (file)) | 2953 | if (file_accessible_directory_p (file)) |
| @@ -2949,7 +2955,7 @@ file_directory_p (Lisp_Object file) | |||
| 2949 | if (errno != EACCES) | 2955 | if (errno != EACCES) |
| 2950 | return false; | 2956 | return false; |
| 2951 | struct stat st; | 2957 | struct stat st; |
| 2952 | if (stat (SSDATA (file), &st) != 0) | 2958 | if (emacs_fstatat (AT_FDCWD, SSDATA (file), &st, 0) != 0) |
| 2953 | return errno == EOVERFLOW; | 2959 | return errno == EOVERFLOW; |
| 2954 | if (S_ISDIR (st.st_mode)) | 2960 | if (S_ISDIR (st.st_mode)) |
| 2955 | return true; | 2961 | return true; |
| @@ -3080,7 +3086,7 @@ See `file-symlink-p' to distinguish symlinks. */) | |||
| 3080 | Vw32_get_true_file_attributes = Qt; | 3086 | Vw32_get_true_file_attributes = Qt; |
| 3081 | #endif | 3087 | #endif |
| 3082 | 3088 | ||
| 3083 | int stat_result = stat (SSDATA (absname), &st); | 3089 | int stat_result = emacs_fstatat (AT_FDCWD, SSDATA (absname), &st, 0); |
| 3084 | 3090 | ||
| 3085 | #ifdef WINDOWSNT | 3091 | #ifdef WINDOWSNT |
| 3086 | Vw32_get_true_file_attributes = true_attributes; | 3092 | Vw32_get_true_file_attributes = true_attributes; |
| @@ -3340,7 +3346,7 @@ Return nil if FILENAME does not exist. */) | |||
| 3340 | if (!NILP (handler)) | 3346 | if (!NILP (handler)) |
| 3341 | return call2 (handler, Qfile_modes, absname); | 3347 | return call2 (handler, Qfile_modes, absname); |
| 3342 | 3348 | ||
| 3343 | if (stat (SSDATA (ENCODE_FILE (absname)), &st) != 0) | 3349 | if (emacs_fstatat (AT_FDCWD, SSDATA (ENCODE_FILE (absname)), &st, 0) != 0) |
| 3344 | return file_attribute_errno (absname, errno); | 3350 | return file_attribute_errno (absname, errno); |
| 3345 | return make_fixnum (st.st_mode & 07777); | 3351 | return make_fixnum (st.st_mode & 07777); |
| 3346 | } | 3352 | } |
| @@ -3486,7 +3492,7 @@ otherwise, if FILE2 does not exist, the answer is t. */) | |||
| 3486 | return call3 (handler, Qfile_newer_than_file_p, absname1, absname2); | 3492 | return call3 (handler, Qfile_newer_than_file_p, absname1, absname2); |
| 3487 | 3493 | ||
| 3488 | int err1; | 3494 | int err1; |
| 3489 | if (stat (SSDATA (ENCODE_FILE (absname1)), &st1) == 0) | 3495 | if (emacs_fstatat (AT_FDCWD, SSDATA (ENCODE_FILE (absname1)), &st1, 0) == 0) |
| 3490 | err1 = 0; | 3496 | err1 = 0; |
| 3491 | else | 3497 | else |
| 3492 | { | 3498 | { |
| @@ -3494,7 +3500,7 @@ otherwise, if FILE2 does not exist, the answer is t. */) | |||
| 3494 | if (err1 != EOVERFLOW) | 3500 | if (err1 != EOVERFLOW) |
| 3495 | return file_attribute_errno (absname1, err1); | 3501 | return file_attribute_errno (absname1, err1); |
| 3496 | } | 3502 | } |
| 3497 | if (stat (SSDATA (ENCODE_FILE (absname2)), &st2) != 0) | 3503 | if (emacs_fstatat (AT_FDCWD, SSDATA (ENCODE_FILE (absname2)), &st2, 0) != 0) |
| 3498 | { | 3504 | { |
| 3499 | file_attribute_errno (absname2, errno); | 3505 | file_attribute_errno (absname2, errno); |
| 3500 | return Qt; | 3506 | return Qt; |
| @@ -3880,7 +3886,7 @@ by calling `format-decode', which see. */) | |||
| 3880 | if (end_offset < 0) | 3886 | if (end_offset < 0) |
| 3881 | buffer_overflow (); | 3887 | buffer_overflow (); |
| 3882 | 3888 | ||
| 3883 | /* The file size returned from stat may be zero, but data | 3889 | /* The file size returned from fstat may be zero, but data |
| 3884 | may be readable nonetheless, for example when this is a | 3890 | may be readable nonetheless, for example when this is a |
| 3885 | file in the /proc filesystem. */ | 3891 | file in the /proc filesystem. */ |
| 3886 | if (end_offset == 0) | 3892 | if (end_offset == 0) |
| @@ -5625,7 +5631,7 @@ See Info node `(elisp)Modification Time' for more details. */) | |||
| 5625 | 5631 | ||
| 5626 | filename = ENCODE_FILE (BVAR (b, filename)); | 5632 | filename = ENCODE_FILE (BVAR (b, filename)); |
| 5627 | 5633 | ||
| 5628 | mtime = (stat (SSDATA (filename), &st) == 0 | 5634 | mtime = (emacs_fstatat (AT_FDCWD, SSDATA (filename), &st, 0) == 0 |
| 5629 | ? get_stat_mtime (&st) | 5635 | ? get_stat_mtime (&st) |
| 5630 | : time_error_value (errno)); | 5636 | : time_error_value (errno)); |
| 5631 | if (timespec_cmp (mtime, b->modtime) == 0 | 5637 | if (timespec_cmp (mtime, b->modtime) == 0 |
| @@ -5689,7 +5695,8 @@ in `current-time' or an integer flag as returned by `visited-file-modtime'. */) | |||
| 5689 | /* The handler can find the file name the same way we did. */ | 5695 | /* The handler can find the file name the same way we did. */ |
| 5690 | return call2 (handler, Qset_visited_file_modtime, Qnil); | 5696 | return call2 (handler, Qset_visited_file_modtime, Qnil); |
| 5691 | 5697 | ||
| 5692 | if (stat (SSDATA (ENCODE_FILE (filename)), &st) == 0) | 5698 | if (emacs_fstatat (AT_FDCWD, SSDATA (ENCODE_FILE (filename)), &st, 0) |
| 5699 | == 0) | ||
| 5693 | { | 5700 | { |
| 5694 | current_buffer->modtime = get_stat_mtime (&st); | 5701 | current_buffer->modtime = get_stat_mtime (&st); |
| 5695 | current_buffer->modtime_size = st.st_size; | 5702 | current_buffer->modtime_size = st.st_size; |
| @@ -5728,12 +5735,14 @@ auto_save_1 (void) | |||
| 5728 | /* Get visited file's mode to become the auto save file's mode. */ | 5735 | /* Get visited file's mode to become the auto save file's mode. */ |
| 5729 | if (! NILP (BVAR (current_buffer, filename))) | 5736 | if (! NILP (BVAR (current_buffer, filename))) |
| 5730 | { | 5737 | { |
| 5731 | if (stat (SSDATA (BVAR (current_buffer, filename)), &st) >= 0) | 5738 | if (emacs_fstatat (AT_FDCWD, SSDATA (BVAR (current_buffer, filename)), |
| 5739 | &st, 0) | ||
| 5740 | == 0) | ||
| 5732 | /* But make sure we can overwrite it later! */ | 5741 | /* But make sure we can overwrite it later! */ |
| 5733 | auto_save_mode_bits = (st.st_mode | 0600) & 0777; | 5742 | auto_save_mode_bits = (st.st_mode | 0600) & 0777; |
| 5734 | else if (modes = Ffile_modes (BVAR (current_buffer, filename)), | 5743 | else if (modes = Ffile_modes (BVAR (current_buffer, filename)), |
| 5735 | FIXNUMP (modes)) | 5744 | FIXNUMP (modes)) |
| 5736 | /* Remote files don't cooperate with stat. */ | 5745 | /* Remote files don't cooperate with fstatat. */ |
| 5737 | auto_save_mode_bits = (XFIXNUM (modes) | 0600) & 0777; | 5746 | auto_save_mode_bits = (XFIXNUM (modes) | 0600) & 0777; |
| 5738 | } | 5747 | } |
| 5739 | 5748 | ||
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) | |||
| 347 | potential race condition since some other process may create | 347 | potential race condition since some other process may create |
| 348 | NEW immediately after the existence check, but it's the best | 348 | NEW immediately after the existence check, but it's the best |
| 349 | we can portably do here. */ | 349 | we can portably do here. */ |
| 350 | if (lstat (new, &st) == 0 || errno == EOVERFLOW) | 350 | if (emacs_fstatat (AT_FDCWD, new, &st, AT_SYMLINK_NOFOLLOW) == 0 |
| 351 | || errno == EOVERFLOW) | ||
| 351 | { | 352 | { |
| 352 | errno = EEXIST; | 353 | errno = EEXIST; |
| 353 | return -1; | 354 | 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); | |||
| 4605 | extern void init_random (void); | 4605 | extern void init_random (void); |
| 4606 | extern void emacs_backtrace (int); | 4606 | extern void emacs_backtrace (int); |
| 4607 | extern AVOID emacs_abort (void) NO_INLINE; | 4607 | extern AVOID emacs_abort (void) NO_INLINE; |
| 4608 | extern int emacs_fstatat (int, char const *, void *, int); | ||
| 4609 | extern int emacs_openat (int, char const *, int, int); | ||
| 4608 | extern int emacs_open (const char *, int, int); | 4610 | extern int emacs_open (const char *, int, int); |
| 4609 | extern int emacs_pipe (int[2]); | 4611 | extern int emacs_pipe (int[2]); |
| 4610 | extern int emacs_close (int); | 4612 | 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. */) | |||
| 1353 | ignores suffix order due to load_prefer_newer. */ | 1353 | ignores suffix order due to load_prefer_newer. */ |
| 1354 | if (!load_prefer_newer && is_elc) | 1354 | if (!load_prefer_newer && is_elc) |
| 1355 | { | 1355 | { |
| 1356 | result = stat (SSDATA (efound), &s1); | 1356 | result = emacs_fstatat (AT_FDCWD, SSDATA (efound), &s1, 0); |
| 1357 | if (result == 0) | 1357 | if (result == 0) |
| 1358 | { | 1358 | { |
| 1359 | SSET (efound, SBYTES (efound) - 1, 0); | 1359 | SSET (efound, SBYTES (efound) - 1, 0); |
| 1360 | result = stat (SSDATA (efound), &s2); | 1360 | result = emacs_fstatat (AT_FDCWD, SSDATA (efound), &s2, 0); |
| 1361 | SSET (efound, SBYTES (efound) - 1, 'c'); | 1361 | SSET (efound, SBYTES (efound) - 1, 'c'); |
| 1362 | } | 1362 | } |
| 1363 | 1363 | ||
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) | |||
| 312 | if (pwd | 312 | if (pwd |
| 313 | && (pwdlen = strnlen (pwd, bufsize_max)) < bufsize_max | 313 | && (pwdlen = strnlen (pwd, bufsize_max)) < bufsize_max |
| 314 | && IS_DIRECTORY_SEP (pwd[pwdlen && IS_DEVICE_SEP (pwd[1]) ? 2 : 0]) | 314 | && IS_DIRECTORY_SEP (pwd[pwdlen && IS_DEVICE_SEP (pwd[1]) ? 2 : 0]) |
| 315 | && stat (pwd, &pwdstat) == 0 | 315 | && emacs_fstatat (AT_FDCWD, pwd, &pwdstat, 0) == 0 |
| 316 | && stat (".", &dotstat) == 0 | 316 | && emacs_fstatat (AT_FDCWD, ".", &dotstat, 0) == 0 |
| 317 | && dotstat.st_ino == pwdstat.st_ino | 317 | && dotstat.st_ino == pwdstat.st_ino |
| 318 | && dotstat.st_dev == pwdstat.st_dev) | 318 | && dotstat.st_dev == pwdstat.st_dev) |
| 319 | { | 319 | { |
| @@ -2449,7 +2449,27 @@ emacs_abort (void) | |||
| 2449 | } | 2449 | } |
| 2450 | #endif | 2450 | #endif |
| 2451 | 2451 | ||
| 2452 | /* Open FILE for Emacs use, using open flags OFLAG and mode MODE. | 2452 | /* Assuming the directory DIRFD, store information about FILENAME into *ST, |
| 2453 | using FLAGS to control how the status is obtained. | ||
| 2454 | Do not fail merely because fetching info was interrupted by a signal. | ||
| 2455 | Allow the user to quit. | ||
| 2456 | |||
| 2457 | The type of ST is void * instead of struct stat * because the | ||
| 2458 | latter type would be problematic in lisp.h. Some platforms may | ||
| 2459 | play tricks like "#define stat stat64" in <sys/stat.h>, and lisp.h | ||
| 2460 | does not include <sys/stat.h>. */ | ||
| 2461 | |||
| 2462 | int | ||
| 2463 | emacs_fstatat (int dirfd, char const *filename, void *st, int flags) | ||
| 2464 | { | ||
| 2465 | int r; | ||
| 2466 | while ((r = fstatat (dirfd, filename, st, flags)) != 0 && errno == EINTR) | ||
| 2467 | maybe_quit (); | ||
| 2468 | return r; | ||
| 2469 | } | ||
| 2470 | |||
| 2471 | /* Assuming the directory DIRFD, open FILE for Emacs use, | ||
| 2472 | using open flags OFLAGS and mode MODE. | ||
| 2453 | Use binary I/O on systems that care about text vs binary I/O. | 2473 | Use binary I/O on systems that care about text vs binary I/O. |
| 2454 | Arrange for subprograms to not inherit the file descriptor. | 2474 | Arrange for subprograms to not inherit the file descriptor. |
| 2455 | Prefer a method that is multithread-safe, if available. | 2475 | Prefer a method that is multithread-safe, if available. |
| @@ -2457,17 +2477,23 @@ emacs_abort (void) | |||
| 2457 | Allow the user to quit. */ | 2477 | Allow the user to quit. */ |
| 2458 | 2478 | ||
| 2459 | int | 2479 | int |
| 2460 | emacs_open (const char *file, int oflags, int mode) | 2480 | emacs_openat (int dirfd, char const *file, int oflags, int mode) |
| 2461 | { | 2481 | { |
| 2462 | int fd; | 2482 | int fd; |
| 2463 | if (! (oflags & O_TEXT)) | 2483 | if (! (oflags & O_TEXT)) |
| 2464 | oflags |= O_BINARY; | 2484 | oflags |= O_BINARY; |
| 2465 | oflags |= O_CLOEXEC; | 2485 | oflags |= O_CLOEXEC; |
| 2466 | while ((fd = open (file, oflags, mode)) < 0 && errno == EINTR) | 2486 | while ((fd = openat (dirfd, file, oflags, mode)) < 0 && errno == EINTR) |
| 2467 | maybe_quit (); | 2487 | maybe_quit (); |
| 2468 | return fd; | 2488 | return fd; |
| 2469 | } | 2489 | } |
| 2470 | 2490 | ||
| 2491 | int | ||
| 2492 | emacs_open (char const *file, int oflags, int mode) | ||
| 2493 | { | ||
| 2494 | return emacs_openat (AT_FDCWD, file, oflags, mode); | ||
| 2495 | } | ||
| 2496 | |||
| 2471 | /* Open FILE as a stream for Emacs use, with mode MODE. | 2497 | /* Open FILE as a stream for Emacs use, with mode MODE. |
| 2472 | Act like emacs_open with respect to threads, signals, and quits. */ | 2498 | Act like emacs_open with respect to threads, signals, and quits. */ |
| 2473 | 2499 | ||