diff options
Diffstat (limited to 'src/shared/btrfs-util.c')
-rw-r--r-- | src/shared/btrfs-util.c | 69 |
1 files changed, 57 insertions, 12 deletions
diff --git a/src/shared/btrfs-util.c b/src/shared/btrfs-util.c index 2ed6bf2..f6055a8 100644 --- a/src/shared/btrfs-util.c +++ b/src/shared/btrfs-util.c @@ -262,24 +262,49 @@ static int btrfs_ioctl_search_args_compare(const struct btrfs_ioctl_search_args } typedef struct BtrfsForeachIterator { - const void *p; - size_t i; + const struct btrfs_ioctl_search_args *args; + size_t offset; + unsigned index; + struct btrfs_ioctl_search_header *header; + const void **body; } BtrfsForeachIterator; +static int btrfs_iterate(BtrfsForeachIterator *i) { + assert(i); + assert(i->args); + assert(i->header); + assert(i->body); + + if (i->index >= i->args->key.nr_items) + return 0; /* end */ + + assert_cc(BTRFS_SEARCH_ARGS_BUFSIZE >= sizeof(struct btrfs_ioctl_search_header)); + if (i->offset > BTRFS_SEARCH_ARGS_BUFSIZE - sizeof(struct btrfs_ioctl_search_header)) + return -EBADMSG; + + struct btrfs_ioctl_search_header h; + memcpy(&h, (const uint8_t*) i->args->buf + i->offset, sizeof(struct btrfs_ioctl_search_header)); + + if (i->offset > BTRFS_SEARCH_ARGS_BUFSIZE - sizeof(struct btrfs_ioctl_search_header) - h.len) + return -EBADMSG; + + *i->body = (const uint8_t*) i->args->buf + i->offset + sizeof(struct btrfs_ioctl_search_header); + *i->header = h; + i->offset += sizeof(struct btrfs_ioctl_search_header) + h.len; + i->index++; + + return 1; +} + /* Iterates through a series of struct btrfs_file_extent_item elements. They are unfortunately not aligned, * hence we copy out the header from them */ -#define FOREACH_BTRFS_IOCTL_SEARCH_HEADER(sh, body, args) \ +#define FOREACH_BTRFS_IOCTL_SEARCH_HEADER(_sh, _body, _args) \ for (BtrfsForeachIterator iterator = { \ - .p = ({ \ - memcpy(&(sh), (args).buf, sizeof(struct btrfs_ioctl_search_header)); \ - (body) = (const void*) ((const uint8_t*) (args).buf + sizeof(struct btrfs_ioctl_search_header)); \ - (args).buf; \ - }), \ + .args = &(_args), \ + .header = &(_sh), \ + .body = &(_body), \ }; \ - iterator.i < (args).key.nr_items; \ - iterator.i++, \ - memcpy(&(sh), iterator.p = (const uint8_t*) iterator.p + sizeof(struct btrfs_ioctl_search_header) + (sh).len, sizeof(struct btrfs_ioctl_search_header)), \ - (body) = (const void*) ((const uint8_t*) iterator.p + sizeof(struct btrfs_ioctl_search_header))) + btrfs_iterate(&iterator) > 0; ) int btrfs_subvol_get_info_fd(int fd, uint64_t subvol_id, BtrfsSubvolInfo *ret) { struct btrfs_ioctl_search_args args = { @@ -1162,6 +1187,8 @@ static int copy_quota_hierarchy(int fd, uint64_t old_subvol_id, uint64_t new_sub if (n_old_qgroups <= 0) /* Nothing to copy */ return n_old_qgroups; + assert(old_qgroups); /* Coverity gets confused by the macro iterator allocating this, add a hint */ + r = btrfs_subvol_get_parent(fd, old_subvol_id, &old_parent_id); if (r == -ENXIO) /* We have no parent, hence nothing to copy. */ @@ -1785,6 +1812,24 @@ int btrfs_subvol_auto_qgroup(const char *path, uint64_t subvol_id, bool create_i return btrfs_subvol_auto_qgroup_fd(fd, subvol_id, create_intermediary_qgroup); } +int btrfs_subvol_make_default(const char *path) { + _cleanup_close_ int fd = -EBADF; + uint64_t id; + int r; + + assert(path); + + fd = open(path, O_NOCTTY|O_CLOEXEC|O_DIRECTORY); + if (fd < 0) + return -errno; + + r = btrfs_subvol_get_id_fd(fd, &id); + if (r < 0) + return r; + + return RET_NERRNO(ioctl(fd, BTRFS_IOC_DEFAULT_SUBVOL, &id)); +} + int btrfs_subvol_get_parent(int fd, uint64_t subvol_id, uint64_t *ret) { struct btrfs_ioctl_search_args args = { |