librsync  2.0.1
mksum.c
Go to the documentation of this file.
1 /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*-
2  *
3  * librsync -- library for network deltas
4  *
5  * Copyright 1999-2001, 2014, 2015 by Martin Pool <[email protected]>
6  * Copyright (C) 1999 by Andrew Tridgell <[email protected]>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation; either version 2.1 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22 
23 
24 /**
25  * \file mksum.c Generate file signatures.
26  **/
27 
28 /*
29  * Generating checksums is pretty easy, since we can always just
30  * process whatever data is available. When a whole block has
31  * arrived, or we've reached the end of the file, we write the
32  * checksum out.
33  */
34 
35 /* TODO: Perhaps force blocks to be a multiple of 64 bytes, so that we
36  * can be sure checksum generation will be more efficient. I guess it
37  * will be OK at the moment, though, because tails are only used if
38  * necessary. */
39 
40 #include "config.h"
41 
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <assert.h>
45 
46 #include "librsync.h"
47 #include "stream.h"
48 #include "util.h"
49 #include "sumset.h"
50 #include "job.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  * \private
65  */
66 static rs_result rs_sig_s_header(rs_job_t *job)
67 {
68  rs_squirt_n4(job, job->magic);
69  rs_squirt_n4(job, job->block_len);
70  rs_squirt_n4(job, job->strong_sum_len);
71  rs_trace("sent header (magic %#x, block len = %d, strong sum len = %d)",
72  job->magic, (int) job->block_len, (int) job->strong_sum_len);
73  job->stats.block_len = job->block_len;
74 
75  job->statefn = rs_sig_s_generate;
76  return RS_RUNNING;
77 }
78 
79 
80 /**
81  * Generate the checksums for a block and write it out. Called when
82  * we already know we have enough data in memory at \p block.
83  * \private
84  */
85 static rs_result
86 rs_sig_do_block(rs_job_t *job, const void *block, size_t len)
87 {
88  unsigned int weak_sum;
89  rs_strong_sum_t strong_sum;
90 
91  weak_sum = rs_calc_weak_sum(block, len);
92 
93  if (job->magic == RS_BLAKE2_SIG_MAGIC) {
94  rs_calc_blake2_sum(block, len, &strong_sum);
95  } else if(job->magic == RS_MD4_SIG_MAGIC) {
96  rs_calc_md4_sum(block, len, &strong_sum);
97  } else {
98  rs_error("BUG: invalid job magic %#lx", (unsigned long) job->magic);
99  return RS_INTERNAL_ERROR;
100  }
101 
102  rs_squirt_n4(job, weak_sum);
103  rs_tube_write(job, strong_sum, job->strong_sum_len);
104 
105  if (rs_trace_enabled()) {
106  char strong_sum_hex[RS_MAX_STRONG_SUM_LENGTH * 2 + 1];
107  rs_hexify(strong_sum_hex, strong_sum, job->strong_sum_len);
108  rs_trace("sent weak sum 0x%08x and strong sum %s", weak_sum,
109  strong_sum_hex);
110  }
111 
112  job->stats.sig_blocks++;
113 
114  return RS_RUNNING;
115 }
116 
117 
118 /**
119  * State of reading a block and trying to generate its sum.
120  * \private
121  */
122 static rs_result
123 rs_sig_s_generate(rs_job_t *job)
124 {
125  rs_result result;
126  size_t len;
127  void *block;
128 
129  /* must get a whole block, otherwise try again */
130  len = job->block_len;
131  result = rs_scoop_read(job, len, &block);
132 
133  /* unless we're near eof, in which case we'll accept
134  * whatever's in there */
135  if ((result == RS_BLOCKED && rs_job_input_is_ending(job))) {
136  result = rs_scoop_read_rest(job, &len, &block);
137  } else if (result == RS_INPUT_ENDED) {
138  return RS_DONE;
139  } else if (result != RS_DONE) {
140  rs_trace("generate stopped: %s", rs_strerror(result));
141  return result;
142  }
143 
144  rs_trace("got %ld byte block", (long) len);
145 
146  return rs_sig_do_block(job, block, len);
147 }
148 
149 
150 rs_job_t * rs_sig_begin(size_t new_block_len, size_t strong_sum_len,
151  rs_magic_number sig_magic)
152 {
153  rs_job_t *job;
154  int native_length;
155 
156  job = rs_job_new("signature", rs_sig_s_header);
157  job->block_len = new_block_len;
158 
159  if (!sig_magic)
160  sig_magic = RS_BLAKE2_SIG_MAGIC;
161 
162  switch (sig_magic) {
163  case RS_BLAKE2_SIG_MAGIC:
164  native_length = RS_BLAKE2_SUM_LENGTH;
165  job->magic = sig_magic;
166  break;
167  case RS_MD4_SIG_MAGIC:
168  job->magic = sig_magic;
169  native_length = RS_MD4_SUM_LENGTH;
170  break;
171  default:
172  rs_error("invalid sig_magic %#lx", (unsigned long) sig_magic);
173  return NULL;
174  }
175 
176  if (!strong_sum_len)
177  job->strong_sum_len = native_length;
178  else {
179  assert(strong_sum_len <= native_length);
180  job->strong_sum_len = strong_sum_len;
181  }
182 
183  return job;
184 }
185 
186 /* vim: expandtab shiftwidth=4
187  */
A signature file using the BLAKE2 hash.
Definition: librsync.h:106
rs_long_t sig_blocks
Number of blocks described by the signature.
Definition: librsync.h:247
void rs_hexify(char *to_buf, void const *from_buf, int from_len)
Convert from_len bytes at from_buf into a hex representation in to_buf, which must be twice as long p...
Definition: hex.c:34
A signature file with MD4 signatures.
Definition: librsync.h:97
rs_result(* statefn)(rs_job_t *)
Callback for each processing step.
Definition: job.h:38
rs_stats_t stats
Encoding statistics.
Definition: job.h:69
Public header for librsync.
char const * rs_strerror(rs_result r)
Return an English description of a rs_result value.
Definition: msg.c:51
rs_result
Return codes from nonblocking rsync operations.
Definition: librsync.h:192
Unexpected end of input file, perhaps due to a truncated file or dropped network connection.
Definition: librsync.h:207
Blocked waiting for more data.
Definition: librsync.h:194
Probably a library bug.
Definition: librsync.h:215
rs_magic_number
A uint32 magic number, emitted in bigendian/network order at the start of librsync files...
Definition: librsync.h:75
rs_job_t * rs_sig_begin(size_t new_block_len, size_t strong_sum_len, rs_magic_number sig_magic)
Start generating a signature.
Definition: mksum.c:150
The job is still running, and not yet finished or blocked.
Definition: librsync.h:198
Completed successfully.
Definition: librsync.h:193
The contents of this structure are private.
Definition: job.h:29