On 2018/02/16 4:04, Omar Sandoval wrote:
> From: Omar Sandoval <osandov@xxxxxx>
> +PUBLIC enum btrfs_util_error btrfs_util_subvolume_path_fd(int fd, uint64_t id,
> + char **path_ret)
> +{
> + char *path, *p;
> + size_t capacity = 4096;
> +
> + path = malloc(capacity);
> + if (!path)
> + return BTRFS_UTIL_ERROR_NO_MEMORY;
> + p = path + capacity - 1;
> + p[0] = '\0';
> +
> + if (id == 0) {
> + enum btrfs_util_error err;
> +
> + err = btrfs_util_is_subvolume_fd(fd);
> + if (err)
> + return err;
'path' should be freed here and below.
> +
> + err = btrfs_util_subvolume_id_fd(fd, &id);
> + if (err)
> + return err;
> + }
> +
> + while (id != BTRFS_FS_TREE_OBJECTID) {
> + struct btrfs_ioctl_search_args search = {
> + .key = {
> + .tree_id = BTRFS_ROOT_TREE_OBJECTID,
> + .min_objectid = id,
> + .max_objectid = id,
> + .min_type = BTRFS_ROOT_BACKREF_KEY,
> + .max_type = BTRFS_ROOT_BACKREF_KEY,
> + .min_offset = 0,
> + .max_offset = UINT64_MAX,
> + .min_transid = 0,
> + .max_transid = UINT64_MAX,
> + .nr_items = 1,
> + },
> + };
> + struct btrfs_ioctl_ino_lookup_args lookup;
> + const struct btrfs_ioctl_search_header *header;
> + const struct btrfs_root_ref *ref;
> + const char *name;
> + uint16_t name_len;
> + size_t lookup_len;
> + size_t total_len;
> + int ret;
> +
> + ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &search);
> + if (ret == -1) {
> + free(path);
> + return BTRFS_UTIL_ERROR_SEARCH_FAILED;
> + }
> +
> + if (search.key.nr_items == 0) {
> + free(path);
> + errno = ENOENT;
> + return BTRFS_UTIL_ERROR_SUBVOLUME_NOT_FOUND;
> + }
> +
> + header = (struct btrfs_ioctl_search_header *)search.buf;
> + ref = (struct btrfs_root_ref *)(header + 1);
> + name = (char *)(ref + 1);
> + name_len = le16_to_cpu(ref->name_len);
> +
> + id = header->offset;
> +
> + lookup.treeid = id;
> + lookup.objectid = le64_to_cpu(ref->dirid);
> + ret = ioctl(fd, BTRFS_IOC_INO_LOOKUP, &lookup);
> + if (ret == -1) {
> + free(path);
> + return BTRFS_UTIL_ERROR_SEARCH_FAILED;
> + }
> + lookup_len = strlen(lookup.name);
> +
> + total_len = name_len + lookup_len + (id != BTRFS_FS_TREE_OBJECTID);
> + if (p - total_len < path) {
> + char *new_path, *new_p;
> + size_t new_capacity = capacity * 2;
> +
> + new_path = malloc(new_capacity);
> + if (!new_path) {
> + free(path);
> + return BTRFS_UTIL_ERROR_NO_MEMORY;
> + }
> + new_p = new_path + new_capacity - (path + capacity - p);
> + memcpy(new_p, p, path + capacity - p);
> + free(path);
> + path = new_path;
> + p = new_p;
> + capacity = new_capacity;
> + }
> + p -= name_len;
> + memcpy(p, name, name_len);
> + p -= lookup_len;
> + memcpy(p, lookup.name, lookup_len);
> + if (id != BTRFS_FS_TREE_OBJECTID)
> + *--p = '/';
> + }
> +
> + if (p != path)
> + memmove(path, p, path + capacity - p);
> +
> + *path_ret = path;
> +
> + return BTRFS_UTIL_OK;
> +}
> +
> static enum btrfs_util_error openat_parent_and_name(int dirfd, const char *path,
> char *name, size_t name_len,
> int *fd)
>
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html