From a586dc791ca465f4087473d2ad6794b7776aee2d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 13 Jul 2022 23:43:36 +0200 Subject: [PATCH 1/2] stat-util: replace is_dir() + is_dir_fd() by single is_dir_full() call This new call can execute both of the old operations, but also do generic fstatat() like behaviour. --- src/basic/stat-util.c | 20 ++++++-------------- src/basic/stat-util.h | 9 +++++++-- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c index 64c2f80f3c..c31b4d89d0 100644 --- a/src/basic/stat-util.c +++ b/src/basic/stat-util.c @@ -35,31 +35,23 @@ int is_symlink(const char *path) { return !!S_ISLNK(info.st_mode); } -int is_dir(const char* path, bool follow) { +int is_dir_full(int atfd, const char* path, bool follow) { struct stat st; int r; - assert(path); + assert(atfd >= 0 || atfd == AT_FDCWD); + assert(atfd >= 0 || path); - if (follow) - r = stat(path, &st); + if (path) + r = fstatat(atfd, path, &st, follow ? 0 : AT_SYMLINK_NOFOLLOW); else - r = lstat(path, &st); + r = fstat(atfd, &st); if (r < 0) return -errno; return !!S_ISDIR(st.st_mode); } -int is_dir_fd(int fd) { - struct stat st; - - if (fstat(fd, &st) < 0) - return -errno; - - return !!S_ISDIR(st.st_mode); -} - int is_device_node(const char *path) { struct stat info; diff --git a/src/basic/stat-util.h b/src/basic/stat-util.h index 7f0b3dc0af..56f15534aa 100644 --- a/src/basic/stat-util.h +++ b/src/basic/stat-util.h @@ -13,8 +13,13 @@ #include "missing_stat.h" int is_symlink(const char *path); -int is_dir(const char *path, bool follow); -int is_dir_fd(int fd); +int is_dir_full(int atfd, const char *fname, bool follow); +static inline int is_dir(const char *path, bool follow) { + return is_dir_full(AT_FDCWD, path, follow); +} +static inline int is_dir_fd(int fd) { + return is_dir_full(fd, NULL, false); +} int is_device_node(const char *path); int dir_is_empty_at(int dir_fd, const char *path, bool ignore_hidden_or_backup); From 92631578fff1568fa8e99f96de05baae5b258ffe Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 13 Jul 2022 23:44:45 +0200 Subject: [PATCH 2/2] tmpfiles: check the directory we were supposed to create, not its parent This current code checks the wrong directory. This was broken in 4c39d899ff00e90b7290e4985696f321d7f2726f which converted the previous code incorrectly. --- src/tmpfiles/tmpfiles.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 0e389d3a31..0069f444e9 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -1629,15 +1629,12 @@ static int create_directory_or_subvolume(const char *path, mode_t mode, bool sub r = btrfs_is_subvol(empty_to_root(arg_root)) > 0; } if (!r) - /* Don't create a subvolume unless the root directory is - * one, too. We do this under the assumption that if the - * root directory is just a plain directory (i.e. very - * light-weight), we shouldn't try to split it up into - * subvolumes (i.e. more heavy-weight). Thus, chroot() - * environments and suchlike will get a full brtfs - * subvolume set up below their tree only if they - * specifically set up a btrfs subvolume for the root - * dir too. */ + /* Don't create a subvolume unless the root directory is one, too. We do this under + * the assumption that if the root directory is just a plain directory (i.e. very + * light-weight), we shouldn't try to split it up into subvolumes (i.e. more + * heavy-weight). Thus, chroot() environments and suchlike will get a full brtfs + * subvolume set up below their tree only if they specifically set up a btrfs + * subvolume for the root dir too. */ subvol = false; else { @@ -1657,7 +1654,7 @@ static int create_directory_or_subvolume(const char *path, mode_t mode, bool sub if (!IN_SET(r, -EEXIST, -EROFS)) return log_error_errno(r, "Failed to create directory or subvolume \"%s\": %m", path); - k = is_dir_fd(pfd); + k = is_dir_full(pfd, bn, /* follow= */ false); if (k == -ENOENT && r == -EROFS) return log_error_errno(r, "%s does not exist and cannot be created as the file system is read-only.", path); if (k < 0)