stat-util: drop statx_fallback()
Now both our required baseline of glibc and kernel support statx.
This commit is contained in:
@@ -10,7 +10,6 @@
|
||||
|
||||
int dirent_ensure_type(int dir_fd, struct dirent *de) {
|
||||
struct statx sx;
|
||||
int r;
|
||||
|
||||
assert(dir_fd >= 0);
|
||||
assert(de);
|
||||
@@ -24,9 +23,8 @@ int dirent_ensure_type(int dir_fd, struct dirent *de) {
|
||||
}
|
||||
|
||||
/* Let's ask only for the type, nothing else. */
|
||||
r = statx_fallback(dir_fd, de->d_name, AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT, STATX_TYPE, &sx);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (statx(dir_fd, de->d_name, AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT, STATX_TYPE, &sx) < 0)
|
||||
return -errno;
|
||||
|
||||
assert(FLAGS_SET(sx.stx_mask, STATX_TYPE));
|
||||
de->d_type = IFTODT(sx.stx_mode);
|
||||
|
||||
+4
-6
@@ -1093,13 +1093,11 @@ int fds_are_same_mount(int fd1, int fd2) {
|
||||
assert(fd1 >= 0);
|
||||
assert(fd2 >= 0);
|
||||
|
||||
r = statx_fallback(fd1, "", AT_EMPTY_PATH, STATX_TYPE|STATX_INO|STATX_MNT_ID, &sx1);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (statx(fd1, "", AT_EMPTY_PATH, STATX_TYPE|STATX_INO|STATX_MNT_ID, &sx1) < 0)
|
||||
return -errno;
|
||||
|
||||
r = statx_fallback(fd2, "", AT_EMPTY_PATH, STATX_TYPE|STATX_INO|STATX_MNT_ID, &sx2);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (statx(fd2, "", AT_EMPTY_PATH, STATX_TYPE|STATX_INO|STATX_MNT_ID, &sx2) < 0)
|
||||
return -errno;
|
||||
|
||||
/* First, compare inode. If these are different, the fd does not point to the root directory "/". */
|
||||
if (!statx_inode_same(&sx1, &sx2))
|
||||
|
||||
+13
-16
@@ -167,9 +167,8 @@ int recurse_dir(
|
||||
|
||||
if (FLAGS_SET(flags, RECURSE_DIR_TOPLEVEL)) {
|
||||
if (statx_mask != 0) {
|
||||
r = statx_fallback(dir_fd, "", AT_EMPTY_PATH, statx_mask, &root_sx);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (statx(dir_fd, "", AT_EMPTY_PATH, statx_mask, &root_sx) < 0)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
r = func(RECURSE_DIR_ENTER,
|
||||
@@ -247,9 +246,8 @@ int recurse_dir(
|
||||
de->entries[i]->d_type = DT_DIR;
|
||||
|
||||
if (statx_mask != 0 || (flags & RECURSE_DIR_SAME_MOUNT)) {
|
||||
r = statx_fallback(subdir_fd, "", AT_EMPTY_PATH, statx_mask, &sx);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (statx(subdir_fd, "", AT_EMPTY_PATH, statx_mask, &sx) < 0)
|
||||
return -errno;
|
||||
|
||||
sx_valid = true;
|
||||
}
|
||||
@@ -289,9 +287,8 @@ int recurse_dir(
|
||||
* assume. Let's guarantee that we never pass statx data of a directory where
|
||||
* caller expects a non-directory */
|
||||
|
||||
r = statx_fallback(inode_fd, "", AT_EMPTY_PATH, statx_mask | STATX_TYPE, &sx);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (statx(inode_fd, "", AT_EMPTY_PATH, statx_mask | STATX_TYPE, &sx) < 0)
|
||||
return -errno;
|
||||
|
||||
assert(sx.stx_mask & STATX_TYPE);
|
||||
sx_valid = true;
|
||||
@@ -311,15 +308,15 @@ int recurse_dir(
|
||||
|
||||
} else if (statx_mask != 0 || (de->entries[i]->d_type == DT_UNKNOWN && (flags & RECURSE_DIR_ENSURE_TYPE))) {
|
||||
|
||||
r = statx_fallback(dir_fd, de->entries[i]->d_name, AT_SYMLINK_NOFOLLOW, statx_mask | STATX_TYPE, &sx);
|
||||
if (r == -ENOENT) /* Vanished by now? Go for next file immediately */
|
||||
continue;
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to stat directory entry '%s': %m", p);
|
||||
if (statx(dir_fd, de->entries[i]->d_name, AT_SYMLINK_NOFOLLOW, statx_mask | STATX_TYPE, &sx) < 0) {
|
||||
if (errno == ENOENT) /* Vanished by now? Go for next file immediately */
|
||||
continue;
|
||||
|
||||
assert(-r <= RECURSE_DIR_SKIP_STAT_INODE_ERROR_MAX - RECURSE_DIR_SKIP_STAT_INODE_ERROR_BASE);
|
||||
log_debug_errno(errno, "Failed to stat directory entry '%s': %m", p);
|
||||
|
||||
r = func(RECURSE_DIR_SKIP_STAT_INODE_ERROR_BASE + -r,
|
||||
assert(errno <= RECURSE_DIR_SKIP_STAT_INODE_ERROR_MAX - RECURSE_DIR_SKIP_STAT_INODE_ERROR_BASE);
|
||||
|
||||
r = func(RECURSE_DIR_SKIP_STAT_INODE_ERROR_BASE + errno,
|
||||
p,
|
||||
dir_fd,
|
||||
-1,
|
||||
|
||||
@@ -483,76 +483,6 @@ bool statx_mount_same(const struct statx *a, const struct statx *b) {
|
||||
a->stx_dev_minor == b->stx_dev_minor;
|
||||
}
|
||||
|
||||
static bool is_statx_fatal_error(int err, int flags) {
|
||||
assert(err < 0);
|
||||
|
||||
/* If statx() is not supported or if we see EPERM (which might indicate seccomp filtering or so),
|
||||
* let's do a fallback. Note that on EACCES we'll not fall back, since that is likely an indication of
|
||||
* fs access issues, which we should propagate. */
|
||||
if (ERRNO_IS_NOT_SUPPORTED(err) || err == -EPERM)
|
||||
return false;
|
||||
|
||||
/* When unsupported flags are specified, glibc's fallback function returns -EINVAL.
|
||||
* See statx_generic() in glibc. */
|
||||
if (err != -EINVAL)
|
||||
return true;
|
||||
|
||||
if ((flags & ~(AT_EMPTY_PATH | AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | AT_STATX_SYNC_AS_STAT)) != 0)
|
||||
return false; /* Unsupported flags are specified. Let's try to use our implementation. */
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int statx_fallback(int dfd, const char *path, int flags, unsigned mask, struct statx *sx) {
|
||||
static bool avoid_statx = false;
|
||||
struct stat st;
|
||||
int r;
|
||||
|
||||
if (!avoid_statx) {
|
||||
r = RET_NERRNO(statx(dfd, path, flags, mask, sx));
|
||||
if (r >= 0 || is_statx_fatal_error(r, flags))
|
||||
return r;
|
||||
|
||||
avoid_statx = true;
|
||||
}
|
||||
|
||||
/* Only do fallback if fstatat() supports the flag too, or if it's one of the sync flags, which are
|
||||
* OK to ignore */
|
||||
if ((flags & ~(AT_EMPTY_PATH|AT_NO_AUTOMOUNT|AT_SYMLINK_NOFOLLOW|
|
||||
AT_STATX_SYNC_AS_STAT|AT_STATX_FORCE_SYNC|AT_STATX_DONT_SYNC)) != 0)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (fstatat(dfd, path, &st, flags & (AT_EMPTY_PATH|AT_NO_AUTOMOUNT|AT_SYMLINK_NOFOLLOW)) < 0)
|
||||
return -errno;
|
||||
|
||||
*sx = (struct statx) {
|
||||
.stx_mask = STATX_TYPE|STATX_MODE|
|
||||
STATX_NLINK|STATX_UID|STATX_GID|
|
||||
STATX_ATIME|STATX_MTIME|STATX_CTIME|
|
||||
STATX_INO|STATX_SIZE|STATX_BLOCKS,
|
||||
.stx_blksize = st.st_blksize,
|
||||
.stx_nlink = st.st_nlink,
|
||||
.stx_uid = st.st_uid,
|
||||
.stx_gid = st.st_gid,
|
||||
.stx_mode = st.st_mode,
|
||||
.stx_ino = st.st_ino,
|
||||
.stx_size = st.st_size,
|
||||
.stx_blocks = st.st_blocks,
|
||||
.stx_rdev_major = major(st.st_rdev),
|
||||
.stx_rdev_minor = minor(st.st_rdev),
|
||||
.stx_dev_major = major(st.st_dev),
|
||||
.stx_dev_minor = minor(st.st_dev),
|
||||
.stx_atime.tv_sec = st.st_atim.tv_sec,
|
||||
.stx_atime.tv_nsec = st.st_atim.tv_nsec,
|
||||
.stx_mtime.tv_sec = st.st_mtim.tv_sec,
|
||||
.stx_mtime.tv_nsec = st.st_mtim.tv_nsec,
|
||||
.stx_ctime.tv_sec = st.st_ctim.tv_sec,
|
||||
.stx_ctime.tv_nsec = st.st_ctim.tv_nsec,
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xstatfsat(int dir_fd, const char *path, struct statfs *ret) {
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
|
||||
|
||||
@@ -91,8 +91,6 @@ bool stat_inode_unmodified(const struct stat *a, const struct stat *b);
|
||||
bool statx_inode_same(const struct statx *a, const struct statx *b);
|
||||
bool statx_mount_same(const struct statx *a, const struct statx *b);
|
||||
|
||||
int statx_fallback(int dfd, const char *path, int flags, unsigned mask, struct statx *sx);
|
||||
|
||||
int xstatfsat(int dir_fd, const char *path, struct statfs *ret);
|
||||
|
||||
static inline usec_t statx_timestamp_load(const struct statx_timestamp *ts) {
|
||||
|
||||
Reference in New Issue
Block a user