tree-wide: drop workarounds for statx()

struct statx in glibc header was introduced in glibc-2.28
(fd70af45528d59a00eb3190ef6706cb299488fcd), but at that time,
sys/stat.h conflicts with linux/stat.h. Since glibc-2.30
(5dad6ffbb2b76215cfcd38c3001778536ada8e8a), sys/stat.h includes
linux/stat.h if exists.

Since now our baseline of glibc is 2.31. Hence, we can drop workarounds
for struct statx by importing linux/stat.h from newer kernel (v6.14-rc4).
This commit is contained in:
Yu Watanabe
2025-02-28 02:06:32 +09:00
parent 24845c4ff6
commit 4424e6c811
15 changed files with 298 additions and 317 deletions

View File

@@ -569,14 +569,12 @@ decl_headers = '''
#include <dirent.h>
#include <sched.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <uchar.h>
'''
foreach decl : ['char16_t',
'char32_t',
'struct mount_attr',
'struct statx',
'struct dirent64',
'struct sched_attr',
]
@@ -595,21 +593,9 @@ foreach decl : ['char16_t',
endif
endif
if decl == 'struct statx'
if have
want_linux_stat_h = false
else
have = cc.sizeof(decl,
prefix : decl_headers + '#include <linux/stat.h>',
args : '-D_GNU_SOURCE') > 0
want_linux_stat_h = have
endif
endif
conf.set10('HAVE_' + decl.underscorify().to_upper(), have)
endforeach
conf.set10('WANT_LINUX_STAT_H', want_linux_stat_h)
conf.set10('WANT_LINUX_FS_H', want_linux_fs_h)
foreach ident : ['secure_getenv', '__secure_getenv']
@@ -640,9 +626,6 @@ foreach ident : [
#include <unistd.h>'''],
['bpf', '''#include <sys/syscall.h>
#include <unistd.h>'''],
['statx', '''#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>'''],
['explicit_bzero' , '''#include <string.h>'''],
['reallocarray', '''#include <stdlib.h>'''],
['set_mempolicy', '''#include <stdlib.h>

View File

@@ -9,7 +9,7 @@
#include "string-util.h"
int dirent_ensure_type(int dir_fd, struct dirent *de) {
STRUCT_STATX_DEFINE(sx);
struct statx sx;
int r;
assert(dir_fd >= 0);

View File

@@ -1087,30 +1087,29 @@ int path_is_root_at(int dir_fd, const char *path) {
}
int fds_are_same_mount(int fd1, int fd2) {
STRUCT_NEW_STATX_DEFINE(st1);
STRUCT_NEW_STATX_DEFINE(st2);
struct statx sx1 = {}, sx2 = {}; /* explicitly initialize the struct to make msan silent. */
int r;
assert(fd1 >= 0);
assert(fd2 >= 0);
r = statx_fallback(fd1, "", AT_EMPTY_PATH, STATX_TYPE|STATX_INO|STATX_MNT_ID, &st1.sx);
r = statx_fallback(fd1, "", AT_EMPTY_PATH, STATX_TYPE|STATX_INO|STATX_MNT_ID, &sx1);
if (r < 0)
return r;
r = statx_fallback(fd2, "", AT_EMPTY_PATH, STATX_TYPE|STATX_INO|STATX_MNT_ID, &st2.sx);
r = statx_fallback(fd2, "", AT_EMPTY_PATH, STATX_TYPE|STATX_INO|STATX_MNT_ID, &sx2);
if (r < 0)
return r;
/* First, compare inode. If these are different, the fd does not point to the root directory "/". */
if (!statx_inode_same(&st1.sx, &st2.sx))
if (!statx_inode_same(&sx1, &sx2))
return false;
/* Note, statx() does not provide the mount ID and path_get_mnt_id_at() does not work when an old
* kernel is used. In that case, let's assume that we do not have such spurious mount points in an
* early boot stage, and silently skip the following check. */
if (!FLAGS_SET(st1.nsx.stx_mask, STATX_MNT_ID)) {
if (!FLAGS_SET(sx1.stx_mask, STATX_MNT_ID)) {
int mntid;
r = path_get_mnt_id_at_fallback(fd1, "", &mntid);
@@ -1118,11 +1117,11 @@ int fds_are_same_mount(int fd1, int fd2) {
return r;
assert(mntid >= 0);
st1.nsx.stx_mnt_id = mntid;
st1.nsx.stx_mask |= STATX_MNT_ID;
sx1.stx_mnt_id = mntid;
sx1.stx_mask |= STATX_MNT_ID;
}
if (!FLAGS_SET(st2.nsx.stx_mask, STATX_MNT_ID)) {
if (!FLAGS_SET(sx2.stx_mask, STATX_MNT_ID)) {
int mntid;
r = path_get_mnt_id_at_fallback(fd2, "", &mntid);
@@ -1130,11 +1129,11 @@ int fds_are_same_mount(int fd1, int fd2) {
return r;
assert(mntid >= 0);
st2.nsx.stx_mnt_id = mntid;
st2.nsx.stx_mask |= STATX_MNT_ID;
sx2.stx_mnt_id = mntid;
sx2.stx_mask |= STATX_MNT_ID;
}
return statx_mount_same(&st1.nsx, &st2.nsx);
return statx_mount_same(&sx1, &sx2);
}
const char* accmode_to_string(int flags) {

254
src/basic/linux/stat.h Normal file
View File

@@ -0,0 +1,254 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _LINUX_STAT_H
#define _LINUX_STAT_H
#include <linux/types.h>
#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
#define S_IFMT 00170000
#define S_IFSOCK 0140000
#define S_IFLNK 0120000
#define S_IFREG 0100000
#define S_IFBLK 0060000
#define S_IFDIR 0040000
#define S_IFCHR 0020000
#define S_IFIFO 0010000
#define S_ISUID 0004000
#define S_ISGID 0002000
#define S_ISVTX 0001000
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
#define S_IRWXU 00700
#define S_IRUSR 00400
#define S_IWUSR 00200
#define S_IXUSR 00100
#define S_IRWXG 00070
#define S_IRGRP 00040
#define S_IWGRP 00020
#define S_IXGRP 00010
#define S_IRWXO 00007
#define S_IROTH 00004
#define S_IWOTH 00002
#define S_IXOTH 00001
#endif
/*
* Timestamp structure for the timestamps in struct statx.
*
* tv_sec holds the number of seconds before (negative) or after (positive)
* 00:00:00 1st January 1970 UTC.
*
* tv_nsec holds a number of nanoseconds (0..999,999,999) after the tv_sec time.
*
* __reserved is held in case we need a yet finer resolution.
*/
struct statx_timestamp {
__s64 tv_sec;
__u32 tv_nsec;
__s32 __reserved;
};
/*
* Structures for the extended file attribute retrieval system call
* (statx()).
*
* The caller passes a mask of what they're specifically interested in as a
* parameter to statx(). What statx() actually got will be indicated in
* st_mask upon return.
*
* For each bit in the mask argument:
*
* - if the datum is not supported:
*
* - the bit will be cleared, and
*
* - the datum will be set to an appropriate fabricated value if one is
* available (eg. CIFS can take a default uid and gid), otherwise
*
* - the field will be cleared;
*
* - otherwise, if explicitly requested:
*
* - the datum will be synchronised to the server if AT_STATX_FORCE_SYNC is
* set or if the datum is considered out of date, and
*
* - the field will be filled in and the bit will be set;
*
* - otherwise, if not requested, but available in approximate form without any
* effort, it will be filled in anyway, and the bit will be set upon return
* (it might not be up to date, however, and no attempt will be made to
* synchronise the internal state first);
*
* - otherwise the field and the bit will be cleared before returning.
*
* Items in STATX_BASIC_STATS may be marked unavailable on return, but they
* will have values installed for compatibility purposes so that stat() and
* co. can be emulated in userspace.
*/
struct statx {
/* 0x00 */
/* What results were written [uncond] */
__u32 stx_mask;
/* Preferred general I/O size [uncond] */
__u32 stx_blksize;
/* Flags conveying information about the file [uncond] */
__u64 stx_attributes;
/* 0x10 */
/* Number of hard links */
__u32 stx_nlink;
/* User ID of owner */
__u32 stx_uid;
/* Group ID of owner */
__u32 stx_gid;
/* File mode */
__u16 stx_mode;
__u16 __spare0[1];
/* 0x20 */
/* Inode number */
__u64 stx_ino;
/* File size */
__u64 stx_size;
/* Number of 512-byte blocks allocated */
__u64 stx_blocks;
/* Mask to show what's supported in stx_attributes */
__u64 stx_attributes_mask;
/* 0x40 */
/* Last access time */
struct statx_timestamp stx_atime;
/* File creation time */
struct statx_timestamp stx_btime;
/* Last attribute change time */
struct statx_timestamp stx_ctime;
/* Last data modification time */
struct statx_timestamp stx_mtime;
/* 0x80 */
/* Device ID of special file [if bdev/cdev] */
__u32 stx_rdev_major;
__u32 stx_rdev_minor;
/* ID of device containing file [uncond] */
__u32 stx_dev_major;
__u32 stx_dev_minor;
/* 0x90 */
__u64 stx_mnt_id;
/* Memory buffer alignment for direct I/O */
__u32 stx_dio_mem_align;
/* File offset alignment for direct I/O */
__u32 stx_dio_offset_align;
/* 0xa0 */
/* Subvolume identifier */
__u64 stx_subvol;
/* Min atomic write unit in bytes */
__u32 stx_atomic_write_unit_min;
/* Max atomic write unit in bytes */
__u32 stx_atomic_write_unit_max;
/* 0xb0 */
/* Max atomic write segment count */
__u32 stx_atomic_write_segments_max;
/* File offset alignment for direct I/O reads */
__u32 stx_dio_read_offset_align;
/* 0xb8 */
__u64 __spare3[9]; /* Spare space for future expansion */
/* 0x100 */
};
/*
* Flags to be stx_mask
*
* Query request/result mask for statx() and struct statx::stx_mask.
*
* These bits should be set in the mask argument of statx() to request
* particular items when calling statx().
*/
#define STATX_TYPE 0x00000001U /* Want/got stx_mode & S_IFMT */
#define STATX_MODE 0x00000002U /* Want/got stx_mode & ~S_IFMT */
#define STATX_NLINK 0x00000004U /* Want/got stx_nlink */
#define STATX_UID 0x00000008U /* Want/got stx_uid */
#define STATX_GID 0x00000010U /* Want/got stx_gid */
#define STATX_ATIME 0x00000020U /* Want/got stx_atime */
#define STATX_MTIME 0x00000040U /* Want/got stx_mtime */
#define STATX_CTIME 0x00000080U /* Want/got stx_ctime */
#define STATX_INO 0x00000100U /* Want/got stx_ino */
#define STATX_SIZE 0x00000200U /* Want/got stx_size */
#define STATX_BLOCKS 0x00000400U /* Want/got stx_blocks */
#define STATX_BASIC_STATS 0x000007ffU /* The stuff in the normal stat struct */
#define STATX_BTIME 0x00000800U /* Want/got stx_btime */
#define STATX_MNT_ID 0x00001000U /* Got stx_mnt_id */
#define STATX_DIOALIGN 0x00002000U /* Want/got direct I/O alignment info */
#define STATX_MNT_ID_UNIQUE 0x00004000U /* Want/got extended stx_mount_id */
#define STATX_SUBVOL 0x00008000U /* Want/got stx_subvol */
#define STATX_WRITE_ATOMIC 0x00010000U /* Want/got atomic_write_* fields */
#define STATX_DIO_READ_ALIGN 0x00020000U /* Want/got dio read alignment info */
#define STATX__RESERVED 0x80000000U /* Reserved for future struct statx expansion */
/*
* This is deprecated, and shall remain the same value in the future. To avoid
* confusion please use the equivalent (STATX_BASIC_STATS | STATX_BTIME)
* instead.
*/
#define STATX_ALL 0x00000fffU
/*
* Attributes to be found in stx_attributes and masked in stx_attributes_mask.
*
* These give information about the features or the state of a file that might
* be of use to ordinary userspace programs such as GUIs or ls rather than
* specialised tools.
*
* Note that the flags marked [I] correspond to the FS_IOC_SETFLAGS flags
* semantically. Where possible, the numerical value is picked to correspond
* also. Note that the DAX attribute indicates that the file is in the CPU
* direct access state. It does not correspond to the per-inode flag that
* some filesystems support.
*
*/
#define STATX_ATTR_COMPRESSED 0x00000004 /* [I] File is compressed by the fs */
#define STATX_ATTR_IMMUTABLE 0x00000010 /* [I] File is marked immutable */
#define STATX_ATTR_APPEND 0x00000020 /* [I] File is append-only */
#define STATX_ATTR_NODUMP 0x00000040 /* [I] File is not to be dumped */
#define STATX_ATTR_ENCRYPTED 0x00000800 /* [I] File requires key to decrypt in fs */
#define STATX_ATTR_AUTOMOUNT 0x00001000 /* Dir: Automount trigger */
#define STATX_ATTR_MOUNT_ROOT 0x00002000 /* Root of a mount */
#define STATX_ATTR_VERITY 0x00100000 /* [I] Verity protected file */
#define STATX_ATTR_DAX 0x00200000 /* File is currently in DAX state */
#define STATX_ATTR_WRITE_ATOMIC 0x00400000 /* File supports atomic write operations */
#endif /* _LINUX_STAT_H */

View File

@@ -1,135 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <linux/types.h>
#include <sys/stat.h>
#if WANT_LINUX_STAT_H
#include <linux/stat.h>
#endif
/* The newest definition we are aware of (fa2fcf4f1df1559a0a4ee0f46915b496cc2ebf60; 5.8) */
#define STATX_DEFINITION { \
__u32 stx_mask; \
__u32 stx_blksize; \
__u64 stx_attributes; \
__u32 stx_nlink; \
__u32 stx_uid; \
__u32 stx_gid; \
__u16 stx_mode; \
__u16 __spare0[1]; \
__u64 stx_ino; \
__u64 stx_size; \
__u64 stx_blocks; \
__u64 stx_attributes_mask; \
struct statx_timestamp stx_atime; \
struct statx_timestamp stx_btime; \
struct statx_timestamp stx_ctime; \
struct statx_timestamp stx_mtime; \
__u32 stx_rdev_major; \
__u32 stx_rdev_minor; \
__u32 stx_dev_major; \
__u32 stx_dev_minor; \
__u64 stx_mnt_id; \
__u64 __spare2; \
__u64 __spare3[12]; \
}
#if !HAVE_STRUCT_STATX
struct statx_timestamp {
__s64 tv_sec;
__u32 tv_nsec;
__s32 __reserved;
};
struct statx STATX_DEFINITION;
#endif
/* Always define the newest version we are aware of as a distinct type, so that we can use it even if glibc
* defines an older definition */
struct new_statx STATX_DEFINITION;
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef AT_STATX_SYNC_AS_STAT
#define AT_STATX_SYNC_AS_STAT 0x0000
#endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef AT_STATX_FORCE_SYNC
#define AT_STATX_FORCE_SYNC 0x2000
#endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef AT_STATX_DONT_SYNC
#define AT_STATX_DONT_SYNC 0x4000
#endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef STATX_TYPE
#define STATX_TYPE 0x00000001U
#endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef STATX_MODE
#define STATX_MODE 0x00000002U
#endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef STATX_NLINK
#define STATX_NLINK 0x00000004U
#endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef STATX_UID
#define STATX_UID 0x00000008U
#endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef STATX_GID
#define STATX_GID 0x00000010U
#endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef STATX_ATIME
#define STATX_ATIME 0x00000020U
#endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef STATX_MTIME
#define STATX_MTIME 0x00000040U
#endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef STATX_CTIME
#define STATX_CTIME 0x00000080U
#endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef STATX_INO
#define STATX_INO 0x00000100U
#endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef STATX_SIZE
#define STATX_SIZE 0x00000200U
#endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef STATX_BLOCKS
#define STATX_BLOCKS 0x00000400U
#endif
/* a528d35e8bfcc521d7cb70aaf03e1bd296c8493f (4.11) */
#ifndef STATX_BTIME
#define STATX_BTIME 0x00000800U
#endif
/* fa2fcf4f1df1559a0a4ee0f46915b496cc2ebf60 (5.8) */
#ifndef STATX_MNT_ID
#define STATX_MNT_ID 0x00001000U
#endif
/* 80340fe3605c0e78cfe496c3b3878be828cfdbfe (5.8) */
#ifndef STATX_ATTR_MOUNT_ROOT
#define STATX_ATTR_MOUNT_ROOT 0x00002000 /* Root of a mount */
#endif

View File

@@ -19,7 +19,6 @@
#include "macro.h"
#include "missing_keyctl.h"
#include "missing_sched.h"
#include "missing_stat.h"
#include "missing_syscall_def.h"
/* ======================================================================= */
@@ -223,28 +222,6 @@ static inline int missing_bpf(int cmd, union bpf_attr *attr, size_t size) {
/* ======================================================================= */
#if !HAVE_STATX
struct statx;
static inline ssize_t missing_statx(int dfd, const char *filename, unsigned flags, unsigned int mask, struct statx *buffer) {
# ifdef __NR_statx
return syscall(__NR_statx, dfd, filename, flags, mask, buffer);
# else
errno = ENOSYS;
return -1;
# endif
}
#endif
/* This typedef is supposed to be always defined. */
typedef struct statx struct_statx;
#if !HAVE_STATX
# define statx(dfd, filename, flags, mask, buffer) missing_statx(dfd, filename, flags, mask, buffer)
#endif
/* ======================================================================= */
#if !HAVE_SET_MEMPOLICY
enum {
MPOL_DEFAULT,

View File

@@ -1333,71 +1333,3 @@ assert_cc(__NR_setxattrat == systemd_NR_setxattrat);
# endif
# endif
#endif
#ifndef __IGNORE_statx
# if defined(__aarch64__)
# define systemd_NR_statx 291
# elif defined(__alpha__)
# define systemd_NR_statx 522
# elif defined(__arc__) || defined(__tilegx__)
# define systemd_NR_statx 291
# elif defined(__arm__)
# define systemd_NR_statx 397
# elif defined(__i386__)
# define systemd_NR_statx 383
# elif defined(__ia64__)
# define systemd_NR_statx 1350
# elif defined(__loongarch_lp64)
# define systemd_NR_statx 291
# elif defined(__m68k__)
# define systemd_NR_statx 379
# elif defined(_MIPS_SIM)
# if _MIPS_SIM == _MIPS_SIM_ABI32
# define systemd_NR_statx 4366
# elif _MIPS_SIM == _MIPS_SIM_NABI32
# define systemd_NR_statx 6330
# elif _MIPS_SIM == _MIPS_SIM_ABI64
# define systemd_NR_statx 5326
# else
# error "Unknown MIPS ABI"
# endif
# elif defined(__hppa__)
# define systemd_NR_statx 349
# elif defined(__powerpc__)
# define systemd_NR_statx 383
# elif defined(__riscv)
# if __riscv_xlen == 32
# define systemd_NR_statx 291
# elif __riscv_xlen == 64
# define systemd_NR_statx 291
# else
# error "Unknown RISC-V ABI"
# endif
# elif defined(__s390__)
# define systemd_NR_statx 379
# elif defined(__sparc__)
# define systemd_NR_statx 360
# elif defined(__x86_64__)
# if defined(__ILP32__)
# define systemd_NR_statx (332 | /* __X32_SYSCALL_BIT */ 0x40000000)
# else
# define systemd_NR_statx 332
# endif
# elif !defined(missing_arch_template)
# warning "statx() syscall number is unknown for your architecture"
# endif
/* may be an (invalid) negative number due to libseccomp, see PR 13319 */
# if defined __NR_statx && __NR_statx >= 0
# if defined systemd_NR_statx
assert_cc(__NR_statx == systemd_NR_statx);
# endif
# else
# if defined __NR_statx
# undef __NR_statx
# endif
# if defined systemd_NR_statx && systemd_NR_statx >= 0
# define __NR_statx systemd_NR_statx
# endif
# endif
#endif

View File

@@ -25,7 +25,6 @@ SYSCALLS = [
'renameat2',
'setns',
'setxattrat',
'statx',
]
def dictify(f):

View File

@@ -16,7 +16,6 @@
#include "missing_fcntl.h"
#include "missing_fs.h"
#include "missing_mount.h"
#include "missing_stat.h"
#include "missing_syscall.h"
#include "mkdir.h"
#include "mountpoint-util.h"
@@ -261,8 +260,7 @@ int is_mount_point_at(int fd, const char *filename, int flags) {
* with a variety of st_dev reported. Also, btrfs subvolumes have different st_dev, even though
* they aren't real mounts of their own. */
STRUCT_STATX_DEFINE(sx);
struct statx sx = {}; /* explicitly initialize the struct to make msan silent. */
if (statx(fd, filename,
at_flags_normalize_nofollow(flags) |
AT_NO_AUTOMOUNT | /* don't trigger automounts mounts are a local concept, hence no need to trigger automounts to determine STATX_ATTR_MOUNT_ROOT */
@@ -401,7 +399,7 @@ int path_get_mnt_id_at_fallback(int dir_fd, const char *path, int *ret) {
}
int path_get_mnt_id_at(int dir_fd, const char *path, int *ret) {
STRUCT_NEW_STATX_DEFINE(buf);
struct statx sx;
assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
assert(ret);
@@ -412,7 +410,7 @@ int path_get_mnt_id_at(int dir_fd, const char *path, int *ret) {
AT_NO_AUTOMOUNT | /* don't trigger automounts, mnt_id is a local concept */
AT_STATX_DONT_SYNC, /* don't go to the network, mnt_id is a local concept */
STATX_MNT_ID,
&buf.sx) < 0) {
&sx) < 0) {
if (!ERRNO_IS_NOT_SUPPORTED(errno) && /* statx() is not supported by the kernel. */
!ERRNO_IS_PRIVILEGE(errno) && /* maybe filtered by seccomp. */
errno != EINVAL) /* glibc's fallback method returns EINVAL when AT_STATX_DONT_SYNC is set. */
@@ -421,8 +419,8 @@ int path_get_mnt_id_at(int dir_fd, const char *path, int *ret) {
/* Fall back to name_to_handle_at() and then fdinfo if statx is not supported or we lack
* privileges */
} else if (FLAGS_SET(buf.nsx.stx_mask, STATX_MNT_ID)) {
*ret = buf.nsx.stx_mnt_id;
} else if (FLAGS_SET(sx.stx_mask, STATX_MNT_ID)) {
*ret = sx.stx_mnt_id;
return 0;
}

View File

@@ -151,7 +151,7 @@ int recurse_dir(
void *userdata) {
_cleanup_free_ DirectoryEntries *de = NULL;
STRUCT_STATX_DEFINE(root_sx);
struct statx root_sx;
int r;
assert(dir_fd >= 0);
@@ -193,7 +193,7 @@ int recurse_dir(
for (size_t i = 0; i < de->n_entries; i++) {
_cleanup_close_ int inode_fd = -EBADF, subdir_fd = -EBADF;
_cleanup_free_ char *joined = NULL;
STRUCT_STATX_DEFINE(sx);
struct statx sx;
bool sx_valid = false;
const char *p;

View File

@@ -470,8 +470,8 @@ bool statx_inode_same(const struct statx *a, const struct statx *b) {
a->stx_ino == b->stx_ino;
}
bool statx_mount_same(const struct new_statx *a, const struct new_statx *b) {
if (!new_statx_is_set(a) || !new_statx_is_set(b))
bool statx_mount_same(const struct statx *a, const struct statx *b) {
if (!statx_is_set(a) || !statx_is_set(b))
return false;
/* if we have the mount ID, that's all we need */

View File

@@ -11,7 +11,6 @@
#include "fs-util.h"
#include "macro.h"
#include "missing_stat.h"
#include "siphash24.h"
#include "time-util.h"
@@ -90,31 +89,12 @@ bool stat_inode_same(const struct stat *a, const struct stat *b);
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 new_statx *a, const struct new_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);
#if HAS_FEATURE_MEMORY_SANITIZER
# warning "Explicitly initializing struct statx, to work around msan limitation. Please remove as soon as msan has been updated to not require this."
# define STRUCT_STATX_DEFINE(var) \
struct statx var = {}
# define STRUCT_NEW_STATX_DEFINE(var) \
union { \
struct statx sx; \
struct new_statx nsx; \
} var = {}
#else
# define STRUCT_STATX_DEFINE(var) \
struct statx var
# define STRUCT_NEW_STATX_DEFINE(var) \
union { \
struct statx sx; \
struct new_statx nsx; \
} var
#endif
static inline usec_t statx_timestamp_load(const struct statx_timestamp *ts) {
return timespec_load(&(const struct timespec) { .tv_sec = ts->tv_sec, .tv_nsec = ts->tv_nsec });
}
@@ -140,6 +120,3 @@ static inline bool stat_is_set(const struct stat *st) {
static inline bool statx_is_set(const struct statx *sx) {
return sx && sx->stx_mask != 0;
}
static inline bool new_statx_is_set(const struct new_statx *sx) {
return sx && sx->stx_mask != 0;
}

View File

@@ -379,7 +379,7 @@ int getcrtime_at(
usec_t *ret) {
_cleanup_free_ le64_t *le = NULL;
STRUCT_STATX_DEFINE(sx);
struct statx sx;
usec_t a, b;
int r;

View File

@@ -273,8 +273,7 @@ static int verify_fsroot_dir(
bool searching = FLAGS_SET(flags, VERIFY_ESP_SEARCHING),
unprivileged_mode = FLAGS_SET(flags, VERIFY_ESP_UNPRIVILEGED_MODE);
_cleanup_free_ char *f = NULL;
STRUCT_NEW_STATX_DEFINE(sxa);
STRUCT_NEW_STATX_DEFINE(sxb);
struct statx sxa, sxb;
int r;
/* Checks if the specified directory is at the root of its file system, and returns device
@@ -292,21 +291,21 @@ static int verify_fsroot_dir(
return log_error_errno(r, "Failed to extract filename of %s: %m", path);
r = statx_fallback(dir_fd, strempty(f), AT_SYMLINK_NOFOLLOW|(isempty(f) ? AT_EMPTY_PATH : 0),
STATX_TYPE|STATX_INO|STATX_MNT_ID, &sxa.sx);
STATX_TYPE|STATX_INO|STATX_MNT_ID, &sxa);
if (r < 0)
return log_full_errno((searching && r == -ENOENT) ||
(unprivileged_mode && ERRNO_IS_PRIVILEGE(r)) ? LOG_DEBUG : LOG_ERR, r,
"Failed to determine block device node of \"%s\": %m", path);
assert(S_ISDIR(sxa.sx.stx_mode)); /* We used O_DIRECTORY above, when opening, so this must hold */
assert(S_ISDIR(sxa.stx_mode)); /* We used O_DIRECTORY above, when opening, so this must hold */
if (FLAGS_SET(sxa.sx.stx_attributes_mask, STATX_ATTR_MOUNT_ROOT)) {
if (FLAGS_SET(sxa.stx_attributes_mask, STATX_ATTR_MOUNT_ROOT)) {
/* If we have STATX_ATTR_MOUNT_ROOT, we are happy, that's all we need. We operate under the
* assumption that a top of a mount point is also the top of the file system. (Which of
* course is strictly speaking not always true...) */
if (!FLAGS_SET(sxa.sx.stx_attributes, STATX_ATTR_MOUNT_ROOT))
if (!FLAGS_SET(sxa.stx_attributes, STATX_ATTR_MOUNT_ROOT))
return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
"Directory \"%s\" is not the root of the file system.", path);
@@ -315,15 +314,15 @@ static int verify_fsroot_dir(
}
/* Now let's look at the parent */
r = statx_fallback(dir_fd, "", AT_EMPTY_PATH, STATX_TYPE|STATX_INO|STATX_MNT_ID, &sxb.sx);
r = statx_fallback(dir_fd, "", AT_EMPTY_PATH, STATX_TYPE|STATX_INO|STATX_MNT_ID, &sxb);
if (r < 0)
return log_full_errno(unprivileged_mode && ERRNO_IS_PRIVILEGE(r) ? LOG_DEBUG : LOG_ERR, r,
"Failed to determine block device node of parent of \"%s\": %m", path);
if (statx_inode_same(&sxa.sx, &sxb.sx)) /* for the root dir inode nr for both inodes will be the same */
if (statx_inode_same(&sxa, &sxb)) /* for the root dir inode nr for both inodes will be the same */
goto success;
if (statx_mount_same(&sxa.nsx, &sxb.nsx))
if (statx_mount_same(&sxa, &sxb))
return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
SYNTHETIC_ERRNO(searching ? EADDRNOTAVAIL : ENODEV),
"Directory \"%s\" is not the root of the file system.", path);
@@ -332,10 +331,10 @@ success:
if (!ret_dev)
return 0;
if (sxa.sx.stx_dev_major == 0) /* Hmm, maybe a btrfs device, and the caller asked for the backing device? Then let's try to get it. */
if (sxa.stx_dev_major == 0) /* Hmm, maybe a btrfs device, and the caller asked for the backing device? Then let's try to get it. */
return btrfs_get_block_device_at(dir_fd, strempty(f), ret_dev);
*ret_dev = makedev(sxa.sx.stx_dev_major, sxa.sx.stx_dev_minor);
*ret_dev = makedev(sxa.stx_dev_major, sxa.stx_dev_minor);
return 0;
}

View File

@@ -564,7 +564,7 @@ static int opendir_and_stat(
bool *ret_mountpoint) {
_cleanup_closedir_ DIR *d = NULL;
STRUCT_NEW_STATX_DEFINE(st1);
struct statx sx1;
int r;
assert(path);
@@ -591,24 +591,23 @@ static int opendir_and_stat(
return 0;
}
r = statx_fallback(dirfd(d), "", AT_EMPTY_PATH, STATX_MODE|STATX_INO|STATX_ATIME|STATX_MTIME, &st1.sx);
r = statx_fallback(dirfd(d), "", AT_EMPTY_PATH, STATX_MODE|STATX_INO|STATX_ATIME|STATX_MTIME, &sx1);
if (r < 0)
return log_error_errno(r, "statx(%s) failed: %m", path);
if (FLAGS_SET(st1.sx.stx_attributes_mask, STATX_ATTR_MOUNT_ROOT))
*ret_mountpoint = FLAGS_SET(st1.sx.stx_attributes, STATX_ATTR_MOUNT_ROOT);
if (FLAGS_SET(sx1.stx_attributes_mask, STATX_ATTR_MOUNT_ROOT))
*ret_mountpoint = FLAGS_SET(sx1.stx_attributes, STATX_ATTR_MOUNT_ROOT);
else {
STRUCT_NEW_STATX_DEFINE(st2);
r = statx_fallback(dirfd(d), "..", 0, STATX_INO, &st2.sx);
struct statx sx2;
r = statx_fallback(dirfd(d), "..", 0, STATX_INO, &sx2);
if (r < 0)
return log_error_errno(r, "statx(%s/..) failed: %m", path);
*ret_mountpoint = !statx_mount_same(&st1.nsx, &st2.nsx);
*ret_mountpoint = !statx_mount_same(&sx1, &sx2);
}
*ret = TAKE_PTR(d);
*ret_sx = st1.sx;
*ret_sx = sx1;
return 1;
}
@@ -707,8 +706,7 @@ static int dir_cleanup(
* systems such as overlayfs better where each file is originating from a different
* st_dev. */
STRUCT_STATX_DEFINE(sx);
struct statx sx;
r = statx_fallback(
dirfd(d), de->d_name,
AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT,
@@ -2994,7 +2992,7 @@ static int remove_recursive(
bool remove_instance) {
_cleanup_closedir_ DIR *d = NULL;
STRUCT_STATX_DEFINE(sx);
struct statx sx;
bool mountpoint;
int r;
@@ -3144,7 +3142,7 @@ static int clean_item_instance(
usec_t cutoff = n - i->age;
_cleanup_closedir_ DIR *d = NULL;
STRUCT_STATX_DEFINE(sx);
struct statx sx;
bool mountpoint;
int r;