static int cmd_inspect_subvolid_resolve(int argc, char **argv) { int ret; int fd = -1; u64 subvol_id; char path[PATH_MAX]; DIR *dirstream = NULL; clean_args_no_options(argc, argv, cmd_inspect_subvolid_resolve_usage); if (check_argc_exact(argc - optind, 2)) usage(cmd_inspect_subvolid_resolve_usage); fd = btrfs_open_dir(argv[optind + 1], &dirstream, 1); if (fd < 0) { ret = -ENOENT; goto out; } subvol_id = arg_strtou64(argv[optind]); ret = btrfs_subvolid_resolve(fd, path, sizeof(path), subvol_id); if (ret) { error("resolving subvolid %llu error %d", (unsigned long long)subvol_id, ret); goto out; } path[PATH_MAX - 1] = '\0'; printf("%s\n", path); out: close_file_or_dir(fd, dirstream); return ret ? 1 : 0; }
static int do_receive(struct btrfs_receive *r, const char *tomnt, char *realmnt, int r_fd, u64 max_errors) { u64 subvol_id; int ret; char *dest_dir_full_path; char root_subvol_path[PATH_MAX]; int end = 0; dest_dir_full_path = realpath(tomnt, NULL); if (!dest_dir_full_path) { ret = -errno; error("realpath(%s) failed: %s", tomnt, strerror(-ret)); goto out; } r->dest_dir_fd = open(dest_dir_full_path, O_RDONLY | O_NOATIME); if (r->dest_dir_fd < 0) { ret = -errno; error("cannot open destination directory %s: %s", dest_dir_full_path, strerror(-ret)); goto out; } if (realmnt[0]) { r->root_path = realmnt; } else { ret = find_mount_root(dest_dir_full_path, &r->root_path); if (ret < 0) { error("failed to determine mount point for %s: %s", dest_dir_full_path, strerror(-ret)); ret = -EINVAL; goto out; } if (ret > 0) { error("%s doesn't belong to btrfs mount point", dest_dir_full_path); ret = -EINVAL; goto out; } } r->mnt_fd = open(r->root_path, O_RDONLY | O_NOATIME); if (r->mnt_fd < 0) { ret = -errno; error("cannot open %s: %s", r->root_path, strerror(-ret)); goto out; } /* * If we use -m or a default subvol we want to resolve the path to the * subvolume we're sitting in so that we can adjust the paths of any * subvols we want to receive in. */ ret = btrfs_list_get_path_rootid(r->mnt_fd, &subvol_id); if (ret) { error("cannot resolve our subvolid: %d", ret); goto out; } root_subvol_path[0] = 0; ret = btrfs_subvolid_resolve(r->mnt_fd, root_subvol_path, PATH_MAX, subvol_id); if (ret) { error("cannot resolve our subvol path"); goto out; } /* * Ok we're inside of a subvol off of the root subvol, we need to * actually set full_root_path. */ if (*root_subvol_path) r->full_root_path = root_subvol_path; if (r->dest_dir_chroot) { if (chroot(dest_dir_full_path)) { ret = -errno; error("failed to chroot to %s: %s", dest_dir_full_path, strerror(-ret)); goto out; } if (chdir("/")) { ret = -errno; error("failed to chdir to / after chroot: %s", strerror(-ret)); goto out; } fprintf(stderr, "Chroot to %s\n", dest_dir_full_path); r->root_path = strdup("/"); r->dest_dir_path = r->root_path; } else { /* * find_mount_root returns a root_path that is a subpath of * dest_dir_full_path. Now get the other part of root_path, * which is the destination dir relative to root_path. */ r->dest_dir_path = dest_dir_full_path + strlen(r->root_path); while (r->dest_dir_path[0] == '/') r->dest_dir_path++; } ret = subvol_uuid_search_init(r->mnt_fd, &r->sus); if (ret < 0) goto out; while (!end) { if (r->cached_capabilities_len) { if (g_verbose >= 3) fprintf(stderr, "clear cached capabilities\n"); memset(r->cached_capabilities, 0, sizeof(r->cached_capabilities)); r->cached_capabilities_len = 0; } ret = btrfs_read_and_process_send_stream(r_fd, &send_ops, r, r->honor_end_cmd, max_errors); if (ret < 0) goto out; if (ret) end = 1; close_inode_for_write(r); ret = finish_subvol(r); if (ret < 0) goto out; } ret = 0; out: if (r->write_fd != -1) { close(r->write_fd); r->write_fd = -1; } if (r->root_path != realmnt) free(r->root_path); r->root_path = NULL; r->dest_dir_path = NULL; free(dest_dir_full_path); subvol_uuid_search_finit(&r->sus); if (r->mnt_fd != -1) { close(r->mnt_fd); r->mnt_fd = -1; } if (r->dest_dir_fd != -1) { close(r->dest_dir_fd); r->dest_dir_fd = -1; } return ret; }