-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 @@ | |||
1 | /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- | ||
2 | * | ||
3 | * librsync -- library for network deltas | ||
4 | * $Id$ | ||
5 | * | ||
6 | * Copyright (C) 1999, 2000, 2001 by Martin Pool <mbp@samba.org> | ||
7 | * Copyright (C) 1999 by Andrew Tridgell <tridge@samba.org> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU Lesser General Public License as published by | ||
11 | * the Free Software Foundation; either version 2.1 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU Lesser General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU Lesser General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | |||
25 | /* | ||
26 | * mksum.c -- Generate file signatures. | ||
27 | * | ||
28 | * Generating checksums is pretty easy, since we can always just | ||
29 | * process whatever data is available. When a whole block has | ||
30 | * arrived, or we've reached the end of the file, we write the | ||
31 | * checksum out. | ||
32 | */ | ||
33 | |||
34 | /* TODO: Perhaps force blocks to be a multiple of 64 bytes, so that we | ||
35 | * can be sure checksum generation will be more efficient. I guess it | ||
36 | * will be OK at the moment, though, because tails are only used if | ||
37 | * necessary. */ | ||
38 | |||
39 | #include <config_rsync.h> | ||
40 | |||
41 | #include <stdlib.h> | ||
42 | #include <stdio.h> | ||
43 | #include <assert.h> | ||
44 | |||
45 | #include "rsync.h" | ||
46 | #include "stream.h" | ||
47 | #include "util.h" | ||
48 | #include "sumset.h" | ||
49 | #include "job.h" | ||
50 | #include "protocol.h" | ||
51 | #include "netint.h" | ||
52 | #include "trace.h" | ||
53 | #include "checksum.h" | ||
54 | |||
55 | |||
56 | /* Possible state functions for signature generation. */ | ||
57 | static rs_result rs_sig_s_header(rs_job_t *); | ||
58 | static rs_result rs_sig_s_generate(rs_job_t *); | ||
59 | |||
60 | |||
61 | |||
62 | /** | ||
63 | * State of trying to send the signature header. | ||
64 | */ | ||
65 | static rs_result rs_sig_s_header(rs_job_t *job) | ||
66 | { | ||
67 | rs_squirt_n4(job, RS_SIG_MAGIC); | ||
68 | rs_squirt_n4(job, job->block_len); | ||
69 | rs_squirt_n4(job, job->strong_sum_len); | ||
70 | rs_trace("sent header (magic %#x, block len = %d, strong sum len = %d)", | ||
71 | RS_SIG_MAGIC, (int) job->block_len, (int) job->strong_sum_len); | ||
72 | job->stats.block_len = job->block_len; | ||
73 | |||
74 | job->statefn = rs_sig_s_generate; | ||
75 | return RS_RUNNING; | ||
76 | } | ||
77 | |||
78 | |||
79 | /** | ||
80 | * Generate the checksums for a block and write it out. Called when | ||
81 | * we already know we have enough data in memory at \p block. | ||
82 | */ | ||
83 | static rs_result | ||
84 | rs_sig_do_block(rs_job_t *job, const void *block, size_t len) | ||
85 | { | ||
86 | unsigned int weak_sum; | ||
87 | rs_strong_sum_t strong_sum; | ||
88 | |||
89 | weak_sum = rs_calc_weak_sum(block, len); | ||
90 | |||
91 | rs_calc_strong_sum(block, len, &strong_sum); | ||
92 | |||
93 | rs_squirt_n4(job, weak_sum); | ||
94 | rs_tube_write(job, strong_sum, job->strong_sum_len); | ||
95 | |||
96 | if (rs_trace_enabled()) { | ||
97 | char strong_sum_hex[RS_MD4_LENGTH * 2 + 1]; | ||
98 | rs_hexify(strong_sum_hex, strong_sum, job->strong_sum_len); | ||
99 | rs_trace("sent weak sum 0x%08x and strong sum %s", weak_sum, | ||
100 | strong_sum_hex); | ||
101 | } | ||
102 | |||
103 | job->stats.sig_blocks++; | ||
104 | |||
105 | return RS_RUNNING; | ||
106 | } | ||
107 | |||
108 | |||
109 | /* | ||
110 | * State of reading a block and trying to generate its sum. | ||
111 | */ | ||
112 | static rs_result | ||
113 | rs_sig_s_generate(rs_job_t *job) | ||
114 | { | ||
115 | rs_result result; | ||
116 | size_t len; | ||
117 | void *block; | ||
118 | |||
119 | /* must get a whole block, otherwise try again */ | ||
120 | len = job->block_len; | ||
121 | result = rs_scoop_read(job, len, &block); | ||
122 | |||
123 | /* unless we're near eof, in which case we'll accept | ||
124 | * whatever's in there */ | ||
125 | if ((result == RS_BLOCKED && rs_job_input_is_ending(job))) { | ||
126 | result = rs_scoop_read_rest(job, &len, &block); | ||
127 | } else if (result == RS_INPUT_ENDED) { | ||
128 | return RS_DONE; | ||
129 | } else if (result != RS_DONE) { | ||
130 | rs_trace("generate stopped: %s", rs_strerror(result)); | ||
131 | return result; | ||
132 | } | ||
133 | |||
134 | rs_trace("got %d byte block", len); | ||
135 | |||
136 | return rs_sig_do_block(job, block, len); | ||
137 | } | ||
138 | |||
139 | |||
140 | /** \brief Set up a new encoding job. | ||
141 | * | ||
142 | * \sa rs_sig_file() | ||
143 | */ | ||
144 | rs_job_t * rs_sig_begin(size_t new_block_len, size_t strong_sum_len) | ||
145 | { | ||
146 | rs_job_t *job; | ||
147 | |||
148 | job = rs_job_new("signature", rs_sig_s_header); | ||
149 | job->block_len = new_block_len; | ||
150 | |||
151 | assert(strong_sum_len > 0 && strong_sum_len <= RS_MD4_LENGTH); | ||
152 | job->strong_sum_len = strong_sum_len; | ||
153 | |||
154 | return job; | ||
155 | } | ||