summaryrefslogtreecommitdiff
path: root/rsync/mksum.c
Unidiff
Diffstat (limited to 'rsync/mksum.c') (more/less context) (ignore whitespace changes)
-rw-r--r--rsync/mksum.c155
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. */
57static rs_result rs_sig_s_header(rs_job_t *);
58static rs_result rs_sig_s_generate(rs_job_t *);
59
60
61
62/**
63 * State of trying to send the signature header.
64 */
65static 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 */
83static rs_result
84rs_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 */
112static rs_result
113rs_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 */
144rs_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}