$treeview $search $mathjax $extrastylesheet
librsync
2.0.2
$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 Generate file signatures. 00024 * 00025 * Generating checksums is pretty easy, since we can always just process 00026 * whatever data is available. When a whole block has arrived, or we've reached 00027 * the end of the file, we write the checksum out. 00028 * 00029 * \todo Perhaps force blocks to be a multiple of 64 bytes, so that we can be 00030 * sure checksum generation will be more efficient. I guess it will be OK at 00031 * the moment, though, because tails are only used if necessary. */ 00032 00033 #include "config.h" 00034 00035 #include <stdlib.h> 00036 #include <stdio.h> 00037 #include <assert.h> 00038 00039 #include "librsync.h" 00040 #include "stream.h" 00041 #include "util.h" 00042 #include "sumset.h" 00043 #include "job.h" 00044 #include "netint.h" 00045 #include "trace.h" 00046 00047 /* Possible state functions for signature generation. */ 00048 static rs_result rs_sig_s_header(rs_job_t *); 00049 static rs_result rs_sig_s_generate(rs_job_t *); 00050 00051 /** State of trying to send the signature header. \private */ 00052 static rs_result rs_sig_s_header(rs_job_t *job) 00053 { 00054 rs_signature_t *sig = job->signature; 00055 rs_result result; 00056 00057 if ((result = 00058 rs_signature_init(sig, job->sig_magic, job->sig_block_len, 00059 job->sig_strong_len, 0)) != RS_DONE) 00060 return result; 00061 rs_squirt_n4(job, sig->magic); 00062 rs_squirt_n4(job, sig->block_len); 00063 rs_squirt_n4(job, sig->strong_sum_len); 00064 rs_trace("sent header (magic %#x, block len = %d, strong sum len = %d)", 00065 sig->magic, sig->block_len, sig->strong_sum_len); 00066 job->stats.block_len = sig->block_len; 00067 00068 job->statefn = rs_sig_s_generate; 00069 return RS_RUNNING; 00070 } 00071 00072 /** Generate the checksums for a block and write it out. Called when we 00073 * already know we have enough data in memory at \p block. \private */ 00074 static rs_result rs_sig_do_block(rs_job_t *job, const void *block, size_t len) 00075 { 00076 rs_signature_t *sig = job->signature; 00077 rs_weak_sum_t weak_sum; 00078 rs_strong_sum_t strong_sum; 00079 00080 weak_sum = rs_calc_weak_sum(block, len); 00081 rs_signature_calc_strong_sum(sig, block, len, &strong_sum); 00082 rs_squirt_n4(job, weak_sum); 00083 rs_tube_write(job, strong_sum, sig->strong_sum_len); 00084 if (rs_trace_enabled()) { 00085 char strong_sum_hex[RS_MAX_STRONG_SUM_LENGTH * 2 + 1]; 00086 rs_hexify(strong_sum_hex, strong_sum, sig->strong_sum_len); 00087 rs_trace("sent block: weak=" FMT_WEAKSUM ", strong=%s", weak_sum, 00088 strong_sum_hex); 00089 } 00090 job->stats.sig_blocks++; 00091 return RS_RUNNING; 00092 } 00093 00094 /** State of reading a block and trying to generate its sum. \private */ 00095 static rs_result rs_sig_s_generate(rs_job_t *job) 00096 { 00097 rs_result result; 00098 size_t len; 00099 void *block; 00100 00101 /* must get a whole block, otherwise try again */ 00102 len = job->signature->block_len; 00103 result = rs_scoop_read(job, len, &block); 00104 /* If we are near EOF, get whatever is left. */ 00105 if (result == RS_INPUT_ENDED) 00106 result = rs_scoop_read_rest(job, &len, &block); 00107 if (result == RS_INPUT_ENDED) { 00108 return RS_DONE; 00109 } else if (result != RS_DONE) { 00110 rs_trace("generate stopped: %s", rs_strerror(result)); 00111 return result; 00112 } 00113 rs_trace("got " FMT_SIZE " byte block", len); 00114 return rs_sig_do_block(job, block, len); 00115 } 00116 00117 rs_job_t *rs_sig_begin(size_t new_block_len, size_t strong_sum_len, 00118 rs_magic_number sig_magic) 00119 { 00120 rs_job_t *job; 00121 00122 job = rs_job_new("signature", rs_sig_s_header); 00123 job->signature = rs_alloc_struct(rs_signature_t); 00124 job->job_owns_sig = 1; 00125 job->sig_magic = sig_magic; 00126 job->sig_block_len = new_block_len; 00127 job->sig_strong_len = strong_sum_len; 00128 return job; 00129 }