On 2018/02/16 4:04, Omar Sandoval wrote:
> From: Omar Sandoval <osan...@fb.com>

> +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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to