-rw-r--r-- | rsync/mksum.c | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/rsync/mksum.c b/rsync/mksum.c new file mode 100644 index 0000000..d55bcfb --- a/dev/null +++ b/rsync/mksum.c @@ -0,0 +1,155 @@ +/*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- + * + * librsync -- 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. + */ + + +/* + * mksum.c -- Generate file signatures. + * + * Generating checksums is pretty easy, since we can always just + * process whatever data is available. When a whole block has + * arrived, or we've reached the end of the file, we write the + * checksum out. + */ + +/* TODO: Perhaps force blocks to be a multiple of 64 bytes, so that we + * can be sure checksum generation will be more efficient. I guess it + * will be OK at the moment, though, because tails are only used if + * necessary. */ + +#include <config_rsync.h> + +#include <stdlib.h> +#include <stdio.h> +#include <assert.h> + +#include "rsync.h" +#include "stream.h" +#include "util.h" +#include "sumset.h" +#include "job.h" +#include "protocol.h" +#include "netint.h" +#include "trace.h" +#include "checksum.h" + + +/* Possible state functions for signature generation. */ +static rs_result rs_sig_s_header(rs_job_t *); +static rs_result rs_sig_s_generate(rs_job_t *); + + + +/** + * State of trying to send the signature header. + */ +static rs_result rs_sig_s_header(rs_job_t *job) +{ + rs_squirt_n4(job, RS_SIG_MAGIC); + rs_squirt_n4(job, job->block_len); + rs_squirt_n4(job, job->strong_sum_len); + rs_trace("sent header (magic %#x, block len = %d, strong sum len = %d)", + RS_SIG_MAGIC, (int) job->block_len, (int) job->strong_sum_len); + job->stats.block_len = job->block_len; + + job->statefn = rs_sig_s_generate; + return RS_RUNNING; +} + + +/** + * Generate the checksums for a block and write it out. Called when + * we already know we have enough data in memory at \p block. + */ +static rs_result +rs_sig_do_block(rs_job_t *job, const void *block, size_t len) +{ + unsigned int weak_sum; + rs_strong_sum_t strong_sum; + + weak_sum = rs_calc_weak_sum(block, len); + + rs_calc_strong_sum(block, len, &strong_sum); + + rs_squirt_n4(job, weak_sum); + rs_tube_write(job, strong_sum, job->strong_sum_len); + + if (rs_trace_enabled()) { + char strong_sum_hex[RS_MD4_LENGTH * 2 + 1]; + rs_hexify(strong_sum_hex, strong_sum, job->strong_sum_len); + rs_trace("sent weak sum 0x%08x and strong sum %s", weak_sum, + strong_sum_hex); + } + + job->stats.sig_blocks++; + + return RS_RUNNING; +} + + +/* + * State of reading a block and trying to generate its sum. + */ +static rs_result +rs_sig_s_generate(rs_job_t *job) +{ + rs_result result; + size_t len; + void *block; + + /* must get a whole block, otherwise try again */ + len = job->block_len; + result = rs_scoop_read(job, len, &block); + + /* unless we're near eof, in which case we'll accept + * whatever's in there */ + if ((result == RS_BLOCKED && rs_job_input_is_ending(job))) { + result = rs_scoop_read_rest(job, &len, &block); + } else if (result == RS_INPUT_ENDED) { + return RS_DONE; + } else if (result != RS_DONE) { + rs_trace("generate stopped: %s", rs_strerror(result)); + return result; + } + + rs_trace("got %d byte block", len); + + return rs_sig_do_block(job, block, len); +} + + +/** \brief Set up a new encoding job. + * + * \sa rs_sig_file() + */ +rs_job_t * rs_sig_begin(size_t new_block_len, size_t strong_sum_len) +{ + rs_job_t *job; + + job = rs_job_new("signature", rs_sig_s_header); + job->block_len = new_block_len; + + assert(strong_sum_len > 0 && strong_sum_len <= RS_MD4_LENGTH); + job->strong_sum_len = strong_sum_len; + + return job; +} |