warn("could not read header for extent starting at chunk "U64FMT" of "U64FMT" total chunks: %s", chunk_num, chunk_count, strerror(-err));
goto out;
apply_magic_error:
err = -ERANGE;
warn("wrong magic in header for extent starting at chunk "U64FMT" of "U64FMT" total chunks", chunk_num, chunk_count);
goto out;
apply_deltaread_error:
warn("could not properly read delta data for extent at offset "U64FMT": %s", extent_addr, strerror(-err));
goto out;
apply_devread_error:
warn("could not read "U64FMT" chunk extent at offset "U64FMT" from downstream snapshot device \"%s\": %s", deh.num_of_chunks, extent_addr, dev1name, strerror(-err));
goto out;
apply_compmem_error:
warn("not enough buffer memory for decompression of delta for "U64FMT" chunk extent starting at offset "U64FMT, deh.num_of_chunks, extent_addr);
goto out;
apply_compbuf_error:
warn("not enough room in the output buffer for decompression of delta for "U64FMT" chunk extent starting at offset "U64FMT, deh.num_of_chunks, extent_addr);
goto out;
apply_compdata_error:
warn("compressed data corrupted in delta for "U64FMT" chunk extent starting at offset "U64FMT, deh.num_of_chunks, extent_addr);
goto out;
apply_chunk_error:
err = -ERANGE; /* FIXME: find better error */
warn("delta could not be applied for "U64FMT" chunk extent with start address of "U64FMT, deh.num_of_chunks, extent_addr);
goto out;
apply_checksum_error_snap0:
err = -ERANGE;
warn("checksum failed for "U64FMT" chunk extent with start address of "U64FMT" snapshot0 is not the same on the upstream and the downstream", deh.num_of_chunks, extent_addr);
goto out;
apply_checksum_error:
err = -ERANGE;
warn("checksum failed for "U64FMT" chunk extent with start address of "U64FMT, deh.num_of_chunks, extent_addr);
goto out;
apply_write_error:
warn("updated extent could not be written at start address "U64FMT" in snapshot device \"%s\": %s", extent_addr, dev2name, strerror(-err));
out:
if (up_extent2)
free(up_extent2);
if (up_extent1)
free(up_extent1);
if (comp_delta)
free(comp_delta);
if (extent_data)
free(extent_data);
if (delta_data)
free(delta_data);
if (updated)
free(updated);
close(snapdev2);
if (!fullvolume)
close(snapdev1);
return err;
}
static int apply_delta(int deltafile, char const *devstem)
{
struct delta_header dh;
if (fdread(deltafile, &dh, sizeof(dh)) < 0) {
warn("not a proper delta file (too short)");
return -1; /* FIXME: use named error */
}
/* Make sure it's a proper delta file */
if (strncmp(dh.magic, DELTA_MAGIC_ID, MAGIC_SIZE) != 0) {
warn("not a proper delta file (wrong magic in header)");
return -1; /* FIXME: use named error */
}
if (dh.chunk_size == 0) {
warn("not a proper delta file (zero chunk size)");
return -1; /* FIXME: use named error */
}
char *dev1name = NULL;
int err, fullvolume = (dh.src_snap == ~0U);
/* check to see if the replication is full volume replication (dh.src_snap == -1)
* or replication via snapshot. In case of full volume replication, pass NULL dev1name
* to apply_delta_extents */
if (!fullvolume && !(dev1name = malloc_snapshot_name(devstem, dh.src_snap))) {
{ "foreground", 'f', POPT_ARG_NONE, &nobg, 0, "run in foreground. daemonized by default.", NULL }, // !!! unusual semantics, we should be foreground by default, and optionally daemonize
"Transmit\n\t Function: Stream delta of the given two snapshots to downstream\n\t Usage: transmit [OPTION...] <sockname> <host>[:<port>] [snapshot1] <snapshot2>", NULL},