]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/shared/btrfs-util.c
tree-wide: use -EBADF for fd initialization
[thirdparty/systemd.git] / src / shared / btrfs-util.c
index ec5951b52f6f25741ed45c24ad7763977b71bb02..0a4bd48b880ffc65c2b9e05a213f3701ace14b11 100644 (file)
@@ -31,7 +31,6 @@
 #include "stat-util.h"
 #include "string-util.h"
 #include "time-util.h"
-#include "util.h"
 
 /* WARNING: Be careful with file system ioctls! When we get an fd, we
  * need to make sure it either refers to only a regular file or
@@ -86,7 +85,7 @@ int btrfs_is_subvol_fd(int fd) {
 }
 
 int btrfs_is_subvol(const char *path) {
-        _cleanup_close_ int fd = -1;
+        _cleanup_close_ int fd = -EBADF;
 
         assert(path);
 
@@ -99,7 +98,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;
+        _cleanup_close_ int real_fd = -EBADF;
         int r;
 
         assert(subvolume);
@@ -108,19 +107,11 @@ 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;
-        }
+        /* If an O_PATH fd was specified, let's convert here to a proper one, as btrfs ioctl's can't deal
+         * with O_PATH. */
+        fd = fd_reopen_condition(fd, O_RDONLY|O_CLOEXEC|O_DIRECTORY, O_PATH|O_DIRECTORY, &real_fd);
+        if (fd < 0)
+                return fd;
 
         strncpy(args.name, subvolume, sizeof(args.name)-1);
 
@@ -128,7 +119,7 @@ int btrfs_subvol_make_fd(int fd, const char *subvolume) {
 }
 
 int btrfs_subvol_make(const char *path) {
-        _cleanup_close_ int fd = -1;
+        _cleanup_close_ int fd = -EBADF;
         const char *subvolume;
         int r;
 
@@ -193,7 +184,7 @@ int btrfs_subvol_set_read_only_fd(int fd, bool b) {
 }
 
 int btrfs_subvol_set_read_only(const char *path, bool b) {
-        _cleanup_close_ int fd = -1;
+        _cleanup_close_ int fd = -EBADF;
 
         fd = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
         if (fd < 0)
@@ -246,7 +237,6 @@ int btrfs_clone_range(int infd, uint64_t in_offset, int outfd, uint64_t out_offs
 
         assert(infd >= 0);
         assert(outfd >= 0);
-        assert(sz > 0);
 
         r = fd_verify_regular(outfd);
         if (r < 0)
@@ -257,12 +247,17 @@ int btrfs_clone_range(int infd, uint64_t in_offset, int outfd, uint64_t out_offs
 
 int btrfs_get_block_device_fd(int fd, dev_t *dev) {
         struct btrfs_ioctl_fs_info_args fsi = {};
+        _cleanup_close_ int regfd = -EBADF;
         uint64_t id;
         int r;
 
         assert(fd >= 0);
         assert(dev);
 
+        fd = fd_reopen_condition(fd, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY, O_PATH, &regfd);
+        if (fd < 0)
+                return fd;
+
         r = fd_is_fs_type(fd, BTRFS_SUPER_MAGIC);
         if (r < 0)
                 return r;
@@ -317,7 +312,7 @@ int btrfs_get_block_device_fd(int fd, dev_t *dev) {
 }
 
 int btrfs_get_block_device(const char *path, dev_t *dev) {
-        _cleanup_close_ int fd = -1;
+        _cleanup_close_ int fd = -EBADF;
 
         assert(path);
         assert(dev);
@@ -352,7 +347,7 @@ int btrfs_subvol_get_id_fd(int fd, uint64_t *ret) {
 }
 
 int btrfs_subvol_get_id(int fd, const char *subvol, uint64_t *ret) {
-        _cleanup_close_ int subvol_fd = -1;
+        _cleanup_close_ int subvol_fd = -EBADF;
 
         assert(fd >= 0);
         assert(ret);
@@ -516,10 +511,7 @@ int btrfs_subvol_get_info_fd(int fd, uint64_t subvol_id, BtrfsSubvolInfo *ret) {
         }
 
 finish:
-        if (!found)
-                return -ENODATA;
-
-        return 0;
+        return found ? 0 : -ENODATA;
 }
 
 int btrfs_qgroup_get_quota_fd(int fd, uint64_t qgroupid, BtrfsQuotaInfo *ret) {
@@ -637,7 +629,7 @@ finish:
 }
 
 int btrfs_qgroup_get_quota(const char *path, uint64_t qgroupid, BtrfsQuotaInfo *ret) {
-        _cleanup_close_ int fd = -1;
+        _cleanup_close_ int fd = -EBADF;
 
         fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
         if (fd < 0)
@@ -659,7 +651,7 @@ int btrfs_subvol_find_subtree_qgroup(int fd, uint64_t subvol_id, uint64_t *ret)
          * prepared with btrfs_subvol_auto_qgroup_fd() with
          * insert_intermediary_qgroup=true (or equivalent). For others
          * it will return the leaf qgroup instead. The two cases may
-         * be distuingished via the return value, which is 1 in case
+         * be distinguished via the return value, which is 1 in case
          * an appropriate "subtree" qgroup was found, and 0
          * otherwise. */
 
@@ -730,7 +722,7 @@ int btrfs_subvol_get_subtree_quota_fd(int fd, uint64_t subvol_id, BtrfsQuotaInfo
 }
 
 int btrfs_subvol_get_subtree_quota(const char *path, uint64_t subvol_id, BtrfsQuotaInfo *ret) {
-        _cleanup_close_ int fd = -1;
+        _cleanup_close_ int fd = -EBADF;
 
         fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
         if (fd < 0)
@@ -739,8 +731,20 @@ int btrfs_subvol_get_subtree_quota(const char *path, uint64_t subvol_id, BtrfsQu
         return btrfs_subvol_get_subtree_quota_fd(fd, subvol_id, ret);
 }
 
+int btrfs_defrag_fd(int fd) {
+        int r;
+
+        assert(fd >= 0);
+
+        r = fd_verify_regular(fd);
+        if (r < 0)
+                return r;
+
+        return RET_NERRNO(ioctl(fd, BTRFS_IOC_DEFRAG, NULL));
+}
+
 int btrfs_defrag(const char *p) {
-        _cleanup_close_ int fd = -1;
+        _cleanup_close_ int fd = -EBADF;
 
         fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
         if (fd < 0)
@@ -767,7 +771,7 @@ int btrfs_quota_enable_fd(int fd, bool b) {
 }
 
 int btrfs_quota_enable(const char *path, bool b) {
-        _cleanup_close_ int fd = -1;
+        _cleanup_close_ int fd = -EBADF;
 
         fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
         if (fd < 0)
@@ -818,7 +822,7 @@ int btrfs_qgroup_set_limit_fd(int fd, uint64_t qgroupid, uint64_t referenced_max
 }
 
 int btrfs_qgroup_set_limit(const char *path, uint64_t qgroupid, uint64_t referenced_max) {
-        _cleanup_close_ int fd = -1;
+        _cleanup_close_ int fd = -EBADF;
 
         fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
         if (fd < 0)
@@ -841,7 +845,7 @@ int btrfs_subvol_set_subtree_quota_limit_fd(int fd, uint64_t subvol_id, uint64_t
 }
 
 int btrfs_subvol_set_subtree_quota_limit(const char *path, uint64_t subvol_id, uint64_t referenced_max) {
-        _cleanup_close_ int fd = -1;
+        _cleanup_close_ int fd = -EBADF;
 
         fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
         if (fd < 0)
@@ -1045,7 +1049,7 @@ static int subvol_remove_children(int fd, const char *subvolume, uint64_t subvol
         };
 
         struct btrfs_ioctl_vol_args vol_args = {};
-        _cleanup_close_ int subvol_fd = -1;
+        _cleanup_close_ int subvol_fd = -EBADF;
         struct stat st;
         bool made_writable = false;
         int r;
@@ -1145,7 +1149,7 @@ static int subvol_remove_children(int fd, const char *subvolume, uint64_t subvol
                                  * directory of the subvolume. */
                                 r = subvol_remove_children(subvol_fd, p, sh->objectid, flags);
                         else {
-                                _cleanup_close_ int child_fd = -1;
+                                _cleanup_close_ int child_fd = -EBADF;
 
                                 /* Subvolume is somewhere further down,
                                  * hence we need to open the
@@ -1176,7 +1180,7 @@ static int subvol_remove_children(int fd, const char *subvolume, uint64_t subvol
 }
 
 int btrfs_subvol_remove(const char *path, BtrfsRemoveFlags flags) {
-        _cleanup_close_ int fd = -1;
+        _cleanup_close_ int fd = -EBADF;
         const char *subvolume;
         int r;
 
@@ -1410,7 +1414,7 @@ static int subvol_snapshot_children(
                 .flags = flags & BTRFS_SNAPSHOT_READ_ONLY ? BTRFS_SUBVOL_RDONLY : 0,
                 .fd = old_fd,
         };
-        _cleanup_close_ int subvolume_fd = -1;
+        _cleanup_close_ int subvolume_fd = -EBADF;
         uint64_t new_subvol_id;
         int r;
 
@@ -1464,7 +1468,7 @@ static int subvol_snapshot_children(
                 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) {
                         _cleanup_free_ char *p = NULL, *c = NULL, *np = NULL;
                         const struct btrfs_root_ref *ref;
-                        _cleanup_close_ int old_child_fd = -1, new_child_fd = -1;
+                        _cleanup_close_ int old_child_fd = -EBADF, new_child_fd = -EBADF;
 
                         btrfs_ioctl_search_args_set(&args, sh);
 
@@ -1574,7 +1578,7 @@ int btrfs_subvol_snapshot_fd_full(
                 copy_progress_bytes_t progress_bytes,
                 void *userdata) {
 
-        _cleanup_close_ int new_fd = -1;
+        _cleanup_close_ int new_fd = -EBADF;
         const char *subvolume;
         int r;
 
@@ -1657,7 +1661,7 @@ int btrfs_subvol_snapshot_full(
                 copy_progress_bytes_t progress_bytes,
                 void *userdata) {
 
-        _cleanup_close_ int old_fd = -1;
+        _cleanup_close_ int old_fd = -EBADF;
 
         assert(old_path);
         assert(new_path);
@@ -1758,6 +1762,7 @@ int btrfs_qgroup_find_parents(int fd, uint64_t qgroupid, uint64_t **ret) {
 
 int btrfs_subvol_auto_qgroup_fd(int fd, uint64_t subvol_id, bool insert_intermediary_qgroup) {
         _cleanup_free_ uint64_t *qgroups = NULL;
+        _cleanup_close_ int real_fd = -EBADF;
         uint64_t parent_subvol;
         bool changed = false;
         int n = 0, r;
@@ -1801,6 +1806,11 @@ int btrfs_subvol_auto_qgroup_fd(int fd, uint64_t subvol_id, bool insert_intermed
          * qgroup that then includes all its own child subvolumes.
          */
 
+        /* Turn this into a proper fd, if it is currently O_PATH */
+        fd = fd_reopen_condition(fd, O_RDONLY|O_CLOEXEC, O_PATH, &real_fd);
+        if (fd < 0)
+                return fd;
+
         if (subvol_id == 0) {
                 r = btrfs_is_subvol_fd(fd);
                 if (r < 0)
@@ -1904,7 +1914,7 @@ int btrfs_subvol_auto_qgroup_fd(int fd, uint64_t subvol_id, bool insert_intermed
 }
 
 int btrfs_subvol_auto_qgroup(const char *path, uint64_t subvol_id, bool create_intermediary_qgroup) {
-        _cleanup_close_ int fd = -1;
+        _cleanup_close_ int fd = -EBADF;
 
         fd = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
         if (fd < 0)