$treeview $search $mathjax $extrastylesheet
librsync
2.3.0
$projectbrief
|
$projectbrief
|
$searchbox |
00001 /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- 00002 * 00003 * librsync -- library for network deltas 00004 * 00005 * Copyright 1999-2001, 2014, 2015 by Martin Pool <mbp@sourcefrog.net> 00006 * Copyright (C) 1999 by Andrew Tridgell <tridge@samba.org> 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU Lesser General Public License as published by 00010 * the Free Software Foundation; either version 2.1 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00021 */ 00022 00023 /** \file mksum.c 00024 * Generate file signatures. 00025 * 00026 * Generating checksums is pretty easy, since we can always just process 00027 * whatever data is available. When a whole block has arrived, or we've reached 00028 * the end of the file, we write the checksum out. 00029 * 00030 * \todo Perhaps force blocks to be a multiple of 64 bytes, so that we can be 00031 * sure checksum generation will be more efficient. I guess it will be OK at 00032 * the moment, though, because tails are only used if necessary. */ 00033 00034 #include "config.h" 00035 #include <assert.h> 00036 #include <stdlib.h> 00037 #include "librsync.h" 00038 #include "job.h" 00039 #include "sumset.h" 00040 #include "stream.h" 00041 #include "netint.h" 00042 #include "trace.h" 00043 #include "util.h" 00044 00045 /* Possible state functions for signature generation. */ 00046 static rs_result rs_sig_s_header(rs_job_t *); 00047 static rs_result rs_sig_s_generate(rs_job_t *); 00048 00049 /** State of trying to send the signature header. \private */ 00050 static rs_result rs_sig_s_header(rs_job_t *job) 00051 { 00052 rs_signature_t *sig = job->signature; 00053 rs_result result; 00054 00055 if ((result = 00056 rs_signature_init(sig, job->sig_magic, job->sig_block_len, 00057 job->sig_strong_len, 0)) != RS_DONE) 00058 return result; 00059 rs_squirt_n4(job, sig->magic); 00060 rs_squirt_n4(job, sig->block_len); 00061 rs_squirt_n4(job, sig->strong_sum_len); 00062 rs_trace("sent header (magic %#x, block len = %d, strong sum len = %d)", 00063 sig->magic, sig->block_len, sig->strong_sum_len); 00064 job->stats.block_len = sig->block_len; 00065 00066 job->statefn = rs_sig_s_generate; 00067 return RS_RUNNING; 00068 } 00069 00070 /** Generate the checksums for a block and write it out. Called when we 00071 * already know we have enough data in memory at \p block. \private */ 00072 static rs_result rs_sig_do_block(rs_job_t *job, const void *block, size_t len) 00073 { 00074 rs_signature_t *sig = job->signature; 00075 rs_weak_sum_t weak_sum; 00076 rs_strong_sum_t strong_sum; 00077 00078 weak_sum = rs_signature_calc_weak_sum(sig, block, len); 00079 rs_signature_calc_strong_sum(sig, block, len, &strong_sum); 00080 rs_squirt_n4(job, weak_sum); 00081 rs_tube_write(job, strong_sum, sig->strong_sum_len); 00082 if (rs_trace_enabled()) { 00083 char strong_sum_hex[RS_MAX_STRONG_SUM_LENGTH * 2 + 1]; 00084 rs_hexify(strong_sum_hex, strong_sum, sig->strong_sum_len); 00085 rs_trace("sent block: weak=" FMT_WEAKSUM ", strong=%s", weak_sum, 00086 strong_sum_hex); 00087 } 00088 job->stats.sig_blocks++; 00089 return RS_RUNNING; 00090 } 00091 00092 /** State of reading a block and trying to generate its sum. \private */ 00093 static rs_result rs_sig_s_generate(rs_job_t *job) 00094 { 00095 rs_result result; 00096 size_t len; 00097 void *block; 00098 00099 /* must get a whole block, otherwise try again */ 00100 len = job->signature->block_len; 00101 result = rs_scoop_read(job, len, &block); 00102 /* If we are near EOF, get whatever is left. */ 00103 if (result == RS_INPUT_ENDED) 00104 result = rs_scoop_read_rest(job, &len, &block); 00105 if (result == RS_INPUT_ENDED) { 00106 return RS_DONE; 00107 } else if (result != RS_DONE) { 00108 rs_trace("generate stopped: %s", rs_strerror(result)); 00109 return result; 00110 } 00111 rs_trace("got " FMT_SIZE " byte block", len); 00112 return rs_sig_do_block(job, block, len); 00113 } 00114 00115 rs_job_t *rs_sig_begin(size_t block_len, size_t strong_len, 00116 rs_magic_number sig_magic) 00117 { 00118 rs_job_t *job; 00119 00120 job = rs_job_new("signature", rs_sig_s_header); 00121 job->signature = rs_alloc_struct(rs_signature_t); 00122 job->job_owns_sig = 1; 00123 job->sig_magic = sig_magic; 00124 job->sig_block_len = block_len; 00125 job->sig_strong_len = strong_len; 00126 return job; 00127 }