diff --git a/src/basic/btrfs-util.c b/src/basic/btrfs-util.c index 6d2490f3d7..efac0b9420 100644 --- a/src/basic/btrfs-util.c +++ b/src/basic/btrfs-util.c @@ -28,6 +28,7 @@ #include "device-nodes.h" #include "fd-util.h" #include "fileio.h" +#include "fs-util.h" #include "io-util.h" #include "macro.h" #include "missing.h" @@ -59,23 +60,6 @@ static int validate_subvolume_name(const char *name) { return 0; } -static int open_parent(const char *path, int flags) { - _cleanup_free_ char *parent = NULL; - int fd; - - assert(path); - - parent = dirname_malloc(path); - if (!parent) - return -ENOMEM; - - fd = open(parent, flags); - if (fd < 0) - return -errno; - - return fd; -} - static int extract_subvolume_name(const char *path, const char **subvolume) { const char *fn; int r; @@ -144,7 +128,7 @@ int btrfs_subvol_make(const char *path) { if (r < 0) return r; - fd = open_parent(path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); + fd = open_parent(path, O_CLOEXEC, 0); if (fd < 0) return fd; @@ -1283,7 +1267,7 @@ int btrfs_subvol_remove(const char *path, BtrfsRemoveFlags flags) { if (r < 0) return r; - fd = open_parent(path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); + fd = open_parent(path, O_CLOEXEC, 0); if (fd < 0) return fd; @@ -1723,7 +1707,7 @@ int btrfs_subvol_snapshot_fd(int old_fd, const char *new_path, BtrfsSnapshotFlag if (r < 0) return r; - new_fd = open_parent(new_path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); + new_fd = open_parent(new_path, O_CLOEXEC, 0); if (new_fd < 0) return new_fd; diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index 3a8b32d881..567f4af1ca 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -1195,3 +1195,31 @@ int fsync_directory_of_file(int fd) { return 0; } + +int open_parent(const char *path, int flags, mode_t mode) { + _cleanup_free_ char *parent = NULL; + int fd; + + if (isempty(path)) + return -EINVAL; + if (path_equal(path, "/")) /* requesting the parent of the root dir is fishy, let's prohibit that */ + return -EINVAL; + + parent = dirname_malloc(path); + if (!parent) + return -ENOMEM; + + /* Let's insist on O_DIRECTORY since the parent of a file or directory is a directory. Except if we open an + * O_TMPFILE file, because in that case we are actually create a regular file below the parent directory. */ + + if ((flags & O_PATH) == O_PATH) + flags |= O_DIRECTORY; + else if ((flags & O_TMPFILE) != O_TMPFILE) + flags |= O_DIRECTORY|O_RDONLY; + + fd = open(parent, flags, mode); + if (fd < 0) + return -errno; + + return fd; +} diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h index 28566773c6..754163defd 100644 --- a/src/basic/fs-util.h +++ b/src/basic/fs-util.h @@ -103,3 +103,5 @@ void unlink_tempfilep(char (*p)[]); int unlinkat_deallocate(int fd, const char *name, int flags); int fsync_directory_of_file(int fd); + +int open_parent(const char *path, int flags, mode_t mode);