diff options
author | Lennart Poettering <lennart@poettering.net> | 2018-08-06 19:32:00 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2018-08-08 11:59:39 +0200 |
commit | 2e6e61688748473c4230ca49b402aea2bec9b8ab (patch) | |
tree | ec550a0636f6349e760f1cd097a1cd80ba130f9b | |
parent | 713998cfc8c2f08d096edf047bc0707c3e53286d (diff) | |
download | systemd-2e6e61688748473c4230ca49b402aea2bec9b8ab.tar.gz |
btrfs-util: unfuck tmpfiles' subvol creation
tmpfiles now passes an O_PATH fd to btrfs_subvol_make_fd() under the
assumption it will accept it like mkdirat() does. So far this assumption
was wrong, let's correct that.
Without that tmpfiles' on btrfs file systems failed systematically...
-rw-r--r-- | src/basic/btrfs-util.c | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/src/basic/btrfs-util.c b/src/basic/btrfs-util.c index abd34824e7..376844b7b1 100644 --- a/src/basic/btrfs-util.c +++ b/src/basic/btrfs-util.c @@ -118,6 +118,7 @@ int btrfs_is_subvol(const char *path) { int btrfs_subvol_make_fd(int fd, const char *subvolume) { struct btrfs_ioctl_vol_args args = {}; + _cleanup_close_ int real_fd = -1; int r; assert(subvolume); @@ -126,6 +127,20 @@ int btrfs_subvol_make_fd(int fd, const char *subvolume) { if (r < 0) return r; + r = fcntl(fd, F_GETFL); + if (r < 0) + return -errno; + if (FLAGS_SET(r, O_PATH)) { + /* An O_PATH fd was specified, let's convert here to a proper one, as btrfs ioctl's can't deal with + * O_PATH. */ + + real_fd = fd_reopen(fd, O_RDONLY|O_CLOEXEC|O_DIRECTORY); + if (real_fd < 0) + return real_fd; + + fd = real_fd; + } + strncpy(args.name, subvolume, sizeof(args.name)-1); if (ioctl(fd, BTRFS_IOC_SUBVOL_CREATE, &args) < 0) |