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;
}
Exemplo n.º 2
0
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;
}