static int process_write(const char *path, const void *data, u64 offset, u64 len, void *user) { int ret = 0; struct btrfs_receive *r = user; char full_path[PATH_MAX]; u64 pos = 0; int w; ret = path_cat_out(full_path, r->full_subvol_path, path); if (ret < 0) { error("write: path invalid: %s", path); goto out; } ret = open_inode_for_write(r, full_path); if (ret < 0) goto out; while (pos < len) { w = pwrite(r->write_fd, (char*)data + pos, len - pos, offset + pos); if (w < 0) { ret = -errno; error("writing to %s failed: %s\n", path, strerror(-ret)); goto out; } pos += w; } out: return ret; }
static int process_write(const char *path, const void *data, u64 offset, u64 len, void *user) { int ret = 0; struct btrfs_receive *r = user; char *full_path = path_cat(r->full_subvol_path, path); u64 pos = 0; int w; ret = open_inode_for_write(r, full_path); if (ret < 0) goto out; while (pos < len) { w = pwrite(r->write_fd, (char*)data + pos, len - pos, offset + pos); if (w < 0) { ret = -errno; fprintf(stderr, "ERROR: writing to %s failed. %s\n", path, strerror(-ret)); goto out; } pos += w; } out: free(full_path); return ret; }
static int process_clone(const char *path, u64 offset, u64 len, const u8 *clone_uuid, u64 clone_ctransid, const char *clone_path, u64 clone_offset, void *user) { int ret; struct btrfs_receive *r = user; struct btrfs_ioctl_clone_range_args clone_args; struct subvol_info *si = NULL; char full_path[PATH_MAX]; char *subvol_path = NULL; char full_clone_path[PATH_MAX]; int clone_fd = -1; ret = path_cat_out(full_path, r->full_subvol_path, path); if (ret < 0) { error("clone: source path invalid: %s", path); goto out; } ret = open_inode_for_write(r, full_path); if (ret < 0) goto out; si = subvol_uuid_search(&r->sus, 0, clone_uuid, clone_ctransid, NULL, subvol_search_by_received_uuid); if (!si) { if (memcmp(clone_uuid, r->cur_subvol.received_uuid, BTRFS_UUID_SIZE) == 0) { /* TODO check generation of extent */ subvol_path = strdup(r->cur_subvol_path); } else { ret = -ENOENT; error("clone: did not find source subvol"); goto out; } } else { /*if (rs_args.ctransid > rs_args.rtransid) { if (!r->force) { ret = -EINVAL; fprintf(stderr, "ERROR: subvolume %s was " "modified after it was " "received.\n", r->subvol_parent_name); goto out; } else { fprintf(stderr, "WARNING: subvolume %s was " "modified after it was " "received.\n", r->subvol_parent_name); } }*/ subvol_path = strdup(si->path); } ret = path_cat_out(full_clone_path, subvol_path, clone_path); if (ret < 0) { error("clone: target path invalid: %s", clone_path); goto out; } clone_fd = openat(r->mnt_fd, full_clone_path, O_RDONLY | O_NOATIME); if (clone_fd < 0) { ret = -errno; error("cannot open %s: %s", full_clone_path, strerror(-ret)); goto out; } clone_args.src_fd = clone_fd; clone_args.src_offset = clone_offset; clone_args.src_length = len; clone_args.dest_offset = offset; ret = ioctl(r->write_fd, BTRFS_IOC_CLONE_RANGE, &clone_args); if (ret < 0) { ret = -errno; error("failed to clone extents to %s\n%s\n", path, strerror(-ret)); goto out; } out: if (si) { free(si->path); free(si); } free(subvol_path); if (clone_fd != -1) close(clone_fd); return ret; }