]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
btrfs-util: unfuck tmpfiles' subvol creation
authorLennart Poettering <lennart@poettering.net>
Mon, 6 Aug 2018 17:32:00 +0000 (19:32 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 8 Aug 2018 09:59:39 +0000 (11:59 +0200)
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...

src/basic/btrfs-util.c

index abd34824e7d047ea990b8de011124d19d1f5d1c2..376844b7b17f9e0c3e0c76aa1b849fb76a0d8fd8 100644 (file)
@@ -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)