File: mksum.c

package info (click to toggle)
libhsync 0.5.7-1.2
  • links: PTS
  • area: main
  • in suites: woody
  • size: 1,060 kB
  • ctags: 543
  • sloc: sh: 7,944; ansic: 5,413; makefile: 154
file content (187 lines) | stat: -rw-r--r-- 4,971 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/*				       	-*- c-file-style: "bsd" -*-
 * rproxy -- dynamic caching and delta update in HTTP
 * $Id: mksum.c,v 1.8 2000/08/07 01:47:04 mbp Exp $
 * 
 * Copyright (C) 1999, 2000 by Martin Pool <mbp@humbug.org.au>
 * Copyright (C) 1999 by Andrew Tridgell
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */


/* 
 * Generate a checksum set, using the newstyle nonblocking
 * arrangement and mapptrs.
 */

#include "includes.h"

#include "mapptr.h"

const int       hs_mksum_job_magic = 123123;

struct hs_mksum_job {
    int             dogtag;
    hs_map_t       *in_map;
    int             in_fd;
    hs_write_fn_t   write_fn;
    void           *write_priv;
    size_t          block_len;
    hs_stats_t      stats;
    int             sent_header;

    /* On next call, we will try to calculate the sum of the block * starting 
       at CURSOR. */
    off_t        cursor;

    size_t          strong_sum_len;
};


/* Set up a new encoding job. */
hs_mksum_job_t *
hs_mksum_begin(int in_fd,
	       hs_write_fn_t write_fn, void *write_priv,
	       size_t new_block_len, size_t strong_sum_len)
{
    hs_mksum_job_t *job;

    job = _hs_alloc_struct(hs_mksum_job_t);

    job->in_fd = in_fd;
    job->write_fn = write_fn;
    job->write_priv = write_priv;
    job->block_len = new_block_len;
    job->dogtag = hs_mksum_job_magic;

    assert(strong_sum_len > 0 && strong_sum_len <= MD4_LENGTH);
    job->strong_sum_len = strong_sum_len;

    if (!(job->in_map = hs_map_file(in_fd))) {
	_hs_fatal("can't map input file");
    }

    return job;
}


static void
_hs_mksum_finish(hs_mksum_job_t * job)
{
    assert(job->dogtag == hs_mksum_job_magic);
    _hs_unmap_file(job->in_map);
    /* We don't close or flush the files because they belong to the * caller. 
     */
    hs_bzero(job, sizeof *job);
    free(job);
}


/* 
 * Generate and write out the checksums of a block.
 */
void
_hs_mksum_of_block(byte_t const *p, ssize_t len,
		   hs_write_fn_t write_fn, void *write_priv,
		   size_t strong_sum_len)
{
    uint32_t        weak_sum;
    byte_t            strong_sum[MD4_LENGTH];

#ifdef DO_HS_TRACE
    char            strong_hex[MD4_LENGTH * 2 + 2];
#endif

    weak_sum = _hs_calc_weak_sum(p, len);
    _hs_calc_strong_sum(p, len, strong_sum, strong_sum_len);

#ifdef DO_HS_TRACE
    hs_hexify_buf(strong_hex, strong_sum, strong_sum_len);
    _hs_trace("calculated weak sum %08lx, strong sum %s",
	      (long) weak_sum, strong_hex);
#endif

    _hs_write_netint(write_fn, write_priv, weak_sum);
    _hs_write_loop(write_fn, write_priv, strong_sum, strong_sum_len);
}


/* 
 * Nonblocking iteration interface for making up a file sum.  Returns
 * HS_AGAIN, HS_DONE or HS_FAILED.  Unless it returns HS_AGAIN, then
 * the job is closed on return.
 */
hs_result_t
hs_mksum_iter(hs_mksum_job_t * job)
{
    int             ret;
    byte_t const     *p;
    size_t         map_len;
    int             saw_eof;

    assert(job->dogtag = hs_mksum_job_magic);

    if (!job->sent_header) {
	ret = _hs_newsig_header(job->block_len,
				job->write_fn, job->write_priv);
	if (ret < 0) {
	    _hs_fatal("error writing new sum signature");
	    return HS_FAILED;
	}
	job->sent_header = 1;
    }

    /* Map a block of data */
    map_len = job->block_len;
    saw_eof = 0;
    p = hs_map_ptr(job->in_map, job->cursor, &map_len, &saw_eof);
    if (!p) {
	_hs_error("error mapping file");
	_hs_mksum_finish(job);
	return HS_FAILED;
    }

    /* Calculate and write out the sums, if any. */
    while (map_len > (size_t) job->block_len) {
	_hs_trace("calc sum for @%ld+%ld", (long) job->cursor,
		  (long) job->block_len);

	_hs_mksum_of_block(p, job->block_len,
			   job->write_fn, job->write_priv,
			   job->strong_sum_len);

	p += job->block_len;
	job->cursor += job->block_len;
	map_len -= job->block_len;
    }

    /* If we're at the end of the file, generate a signature for the * last
       short block and go home. */
    if (saw_eof) {
	_hs_trace("calc sum for @%ld+%ld", (long) job->cursor,
		  (long) map_len);

	_hs_mksum_of_block(p, map_len,
			   job->write_fn, job->write_priv,
			   job->strong_sum_len);

	_hs_mksum_finish(job);
	return HS_DONE;
    }

    /* Well, we haven't finished yet.  Return and hopefully we'll be * called 
       back. */
    return HS_AGAIN;
}