mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 00:14:32 +09:00
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:
17
meson.build
17
meson.build
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
254
src/basic/linux/stat.h
Normal 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 */
|
||||
@@ -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
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -25,7 +25,6 @@ SYSCALLS = [
|
||||
'renameat2',
|
||||
'setns',
|
||||
'setxattrat',
|
||||
'statx',
|
||||
]
|
||||
|
||||
def dictify(f):
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user