-rw-r--r-- | rsync/readsums.c | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/rsync/readsums.c b/rsync/readsums.c new file mode 100644 index 0000000..21b5ecd --- a/dev/null +++ b/rsync/readsums.c @@ -0,0 +1,214 @@ +/*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- + * + * librsync -- the library for network deltas + * $Id$ + * + * Copyright (C) 1999, 2000, 2001 by Martin Pool <mbp@samba.org> + * Copyright (C) 1999 by Andrew Tridgell <tridge@samba.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +/* + * readsums.c -- Load signatures from a file into an ::rs_signature_t. + */ + +#include <config_rsync.h> + +#include <assert.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "rsync.h" +#include "sumset.h" +#include "job.h" +#include "trace.h" +#include "netint.h" +#include "protocol.h" +#include "util.h" +#include "stream.h" + + +static rs_result rs_loadsig_s_weak(rs_job_t *job); +static rs_result rs_loadsig_s_strong(rs_job_t *job); + + + +/** + * Add a just-read-in checksum pair to the signature block. + */ +static rs_result rs_loadsig_add_sum(rs_job_t *job, rs_strong_sum_t *strong) +{ + size_t new_size; + rs_signature_t *sig = job->signature; + rs_block_sig_t *asignature; + + sig->count++; + new_size = sig->count * sizeof(rs_block_sig_t); + + sig->block_sigs = realloc(sig->block_sigs, new_size); + + if (sig->block_sigs == NULL) { + return RS_MEM_ERROR; + } + asignature = &(sig->block_sigs[sig->count - 1]); + + asignature->weak_sum = job->weak_sig; + asignature->i = sig->count; + + memcpy(asignature->strong_sum, strong, sig->strong_sum_len); + + if (rs_trace_enabled()) { + char hexbuf[RS_MD4_LENGTH * 2 + 2]; + rs_hexify(hexbuf, strong, sig->strong_sum_len); + + rs_trace("read in checksum: weak=%#x, strong=%s", asignature->weak_sum, + hexbuf); + } + + job->stats.sig_blocks++; + + return RS_RUNNING; +} + + +static rs_result rs_loadsig_s_weak(rs_job_t *job) +{ + int l; + rs_result result; + + result = rs_suck_n4(job, &l); + if (result == RS_DONE) + ; + else if (result == RS_INPUT_ENDED) /* ending here is OK */ + return RS_DONE; + else + return result; + + job->weak_sig = l; + + job->statefn = rs_loadsig_s_strong; + + return RS_RUNNING; +} + + + +static rs_result rs_loadsig_s_strong(rs_job_t *job) +{ + rs_result result; + rs_strong_sum_t *strongsum; + + result = rs_scoop_read(job, job->signature->strong_sum_len, + (void **) &strongsum); + if (result != RS_DONE) return result; + + job->statefn = rs_loadsig_s_weak; + + return rs_loadsig_add_sum(job, strongsum); +} + + + +static rs_result rs_loadsig_s_stronglen(rs_job_t *job) +{ + int l; + rs_result result; + + if ((result = rs_suck_n4(job, &l)) != RS_DONE) + return result; + job->strong_sum_len = l; + + if (l < 0 || l > RS_MD4_LENGTH) { + rs_error("strong sum length %d is implausible", l); + return RS_CORRUPT; + } + + job->signature->block_len = job->block_len; + job->signature->strong_sum_len = job->strong_sum_len; + + rs_trace("allocated sigset_t (strong_sum_len=%d, block_len=%d)", + (int) job->strong_sum_len, (int) job->block_len); + + job->statefn = rs_loadsig_s_weak; + + return RS_RUNNING; +} + + +static rs_result rs_loadsig_s_blocklen(rs_job_t *job) +{ + int l; + rs_result result; + + if ((result = rs_suck_n4(job, &l)) != RS_DONE) + return result; + job->block_len = l; + + if (job->block_len < 1) { + rs_error("block length of %d is bogus", (int) job->block_len); + return RS_CORRUPT; + } + + job->statefn = rs_loadsig_s_stronglen; + job->stats.block_len = job->block_len; + + return RS_RUNNING; +} + + +static rs_result rs_loadsig_s_magic(rs_job_t *job) +{ + int l; + rs_result result; + + if ((result = rs_suck_n4(job, &l)) != RS_DONE) { + return result; + } else if (l != RS_SIG_MAGIC) { + rs_error("wrong magic number %#10x for signature", l); + return RS_BAD_MAGIC; + } else { + rs_trace("got signature magic %#10x", l); + } + + job->statefn = rs_loadsig_s_blocklen; + + return RS_RUNNING; +} + + +/** + * \brief Read a signature from a file into an ::rs_signature_t structure + * in memory. + * + * Once there, it can be used to generate a delta to a newer version of + * the file. + * + * \note After loading the signatures, you must call + * rs_build_hash_table() before you can use them. + */ +rs_job_t *rs_loadsig_begin(rs_signature_t **signature) +{ + rs_job_t *job; + + job = rs_job_new("loadsig", rs_loadsig_s_magic); + *signature = job->signature = rs_alloc_struct(rs_signature_t); + job->signature->count = 0; + + return job; +} + |