up io error count if not exiting
[tridge/junkcode.git] / rproxy / signature.c
1 #include "rproxy.h"
2
3 struct mem_buf {
4         char *buf;
5         off_t ofs;
6         ssize_t length;
7 };
8
9 struct file_buf {
10         FILE *f;
11         FILE *f_cache;
12         ssize_t length;
13         char buf[8192];
14         void *fn;
15 };
16
17
18 typedef enum rs_result {RS_DONE} rs_result;
19
20 size_t sig_inbytes, sig_outbytes, sig_zinbytes, sig_zoutbytes;
21
22 typedef struct {
23         char *next_in;          /**< Next input byte */
24         size_t avail_in;            /**< Number of bytes available at next_in */
25         int eof_in;                 /**< True if there is no more data
26                                      * after this.  */
27         
28         char *next_out;         /**< Next output byte should be put there */
29         size_t avail_out;           /**< Remaining free space at next_out */
30 } rs_buffers_t;
31
32 static ssize_t sig_writebuf(void *private, char *buf, size_t len)
33 {
34         struct mem_buf *bofs = (struct mem_buf *)private;
35
36         if (bofs->length != -1) {
37                 len = MIN(len, bofs->length - bofs->ofs);
38         }
39
40         memcpy(bofs->buf+bofs->ofs, buf, len);
41         bofs->ofs += len;
42         return len;
43 }
44
45 static ssize_t sig_readbuf(void *private, char *buf, size_t len)
46 {
47         struct mem_buf *bofs = (struct mem_buf *)private;
48
49         if (bofs->length != -1) {
50                 len = MIN(len, bofs->length - bofs->ofs);
51         }
52
53         memcpy(buf, bofs->buf+bofs->ofs, len);
54         bofs->ofs += len;
55         return len;
56 }
57
58 static ssize_t sig_readfn(void *private, char *buf, size_t len)
59 {
60         struct file_buf *fbuf = (struct file_buf *)private;
61         ssize_t n;
62         size_t len2;
63
64         if (fbuf->length == 0) {
65                 n = 0;
66                 goto out;
67         }
68
69         if (fbuf->length == -1) {
70                 n = fread(buf, 1, len, fbuf->f);
71
72                 if (n > 0 && fbuf->f_cache) {
73                         fwrite(buf, 1, n, fbuf->f_cache);
74                 }
75                 goto out;
76         }
77
78         len2 = MIN(len, fbuf->length);
79
80         n = fread(buf, 1, len2, fbuf->f);
81
82         if (n <= 0) {
83                 fbuf->length = 0;
84                 n = 0;
85                 goto out;
86         }
87
88         fbuf->length -= n;
89
90         if (n > 0 && fbuf->f_cache) {
91                 fwrite(buf, 1, n, fbuf->f_cache);
92         }
93
94  out:
95         sig_inbytes += n;
96
97         return n;
98 }
99
100
101 static ssize_t sig_zreadfn(void *private, char *buf, size_t len)
102 {
103         ssize_t ret;
104
105         ret = decomp_read(sig_readfn, private, buf, len);
106
107         sig_zinbytes += ret;
108
109         return ret;
110 }
111
112 static ssize_t sig_writefn(void *private, char *buf, size_t len)
113 {
114         struct file_buf *fbuf = (struct file_buf *)private;
115         ssize_t n;
116
117         n = fwrite(buf, 1, len, fbuf->f);
118         if (fbuf->f_cache && n > 0) {
119                 fwrite(buf, 1, n, fbuf->f_cache);
120         }
121
122         sig_outbytes += n;
123
124         return n;
125 }
126
127 static ssize_t sig_zwritefn(void *private, char *buf, size_t len)
128 {
129         ssize_t ret;
130
131         ret = comp_write(sig_writefn, private, buf, len);
132
133         sig_zoutbytes += ret;
134
135         return ret;
136 }
137
138 static ssize_t sig_readfn_ofs(void *private, char *buf, size_t len, off_t ofs)
139 {
140         struct file_buf *fbuf = (struct file_buf *)private;
141         ssize_t n;
142
143
144         fseek(fbuf->f, ofs, SEEK_SET);
145         n = fread(buf, 1, len, fbuf->f);
146
147         return n;
148 }
149
150
151 static rs_result rsig_readfn(rs_job_t *job, rs_buffers_t *buf,
152                              void *opaque)
153 {
154         struct file_buf *fbuf = (struct file_buf *)opaque;
155         int len;
156
157         if (buf->eof_in) {
158                 return RS_DONE;
159         }
160
161         if (buf->avail_in) {
162                 return RS_DONE;
163         }
164
165         len = sig_readfn(fbuf, fbuf->buf, sizeof(fbuf->buf));
166         if (len == 0) {
167                 buf->eof_in = 1;
168                 return RS_DONE;
169         }
170         if (len == -1) {
171             return RS_IO_ERROR;
172         }
173
174         buf->avail_in = len;
175         buf->next_in = fbuf->buf;
176
177         return RS_DONE;
178 }
179
180
181 static rs_result rsig_zreadfn(rs_job_t *job, rs_buffers_t *buf,
182                              void *opaque)
183 {
184         struct file_buf *fbuf = (struct file_buf *)opaque;
185         int len;
186
187         if (buf->eof_in) {
188                 return RS_DONE;
189         }
190
191         if (buf->avail_in) {
192                 return RS_DONE;
193         }
194
195         len = sig_zreadfn(fbuf, fbuf->buf, sizeof(fbuf->buf));
196         if (len == 0) {
197                 buf->eof_in = 1;
198                 return RS_DONE;
199         }
200         if (len == -1) {
201             return RS_IO_ERROR;
202         }
203
204         buf->avail_in = len;
205         buf->next_in = fbuf->buf;
206
207         return RS_DONE;
208 }
209
210
211 rs_result rsig_writebuf(rs_job_t *job, rs_buffers_t *buf, void *opaque)
212 {
213         struct mem_buf *mbuf = (struct mem_buf *)opaque;
214
215         if (buf->next_out == NULL) {
216                 buf->next_out = mbuf->buf;
217                 buf->avail_out = mbuf->length;
218                 return RS_DONE;
219         }
220         
221         mbuf->ofs = buf->next_out - mbuf->buf;
222         if (mbuf->ofs >= mbuf->length) {
223                 return RS_IO_ERROR;
224         }
225
226         buf->avail_out = mbuf->length - mbuf->ofs;
227
228         return RS_DONE;
229 }
230
231
232 /* generate the signatures for a file putting them in a sigblock,
233    and return a pointer to the sigblock, which must be base64 encoded */
234 char *sig_generate(FILE *f)
235 {
236         rs_buffers_t rbuf;
237         struct stat st;
238         size_t block_size;
239         char *buf, *buf2;
240         struct mem_buf mbuf;
241         struct file_buf fbuf;
242         rs_job_t *job;
243         rs_result r;
244
245         if (fstat(fileno(f), &st)) {
246                 errmsg("fstat error in sig_generate\n");
247                 exit_cleanup(1);
248         }
249
250         block_size = (st.st_size / (MAX_SIG_SIZE/(8+8))) & ~15;
251         if (block_size < 128) block_size = 128;
252
253         buf  = (char *)xmalloc(MAX_SIG_SIZE*2);
254         buf2 = (char *)xmalloc(MAX_SIG_SIZE*2); /* plenty of extra space */
255
256         mbuf.buf = buf;
257         mbuf.ofs = 0;
258         mbuf.length = MAX_SIG_SIZE*2;
259
260         fbuf.f = f;
261         fbuf.f_cache = NULL;
262         fbuf.length = -1;
263
264         sig_inbytes = sig_outbytes = sig_zinbytes = sig_zoutbytes = 0;
265
266         memset(&rbuf, 0, sizeof(rbuf));
267
268         job = rs_sig_begin(block_size, 8);
269         r = rs_job_drive(job, &rbuf,
270                          rsig_readfn, (void *)&fbuf,
271                          rsig_writebuf, (void *)&mbuf);
272         rs_job_free(job);
273
274         base64_encode((unsigned char *)buf, mbuf.ofs, buf2);
275
276         logmsg("generated signature of size %u block_size=%d inbytes=%d\n", 
277                (unsigned)mbuf.ofs, block_size, sig_inbytes);
278
279         free(buf);
280         return buf2;
281 }
282
283
284 static rs_result rsig_readfn_ofs(void *opaque, off_t pos,
285                                  size_t *len, void **buf)
286 {
287         int ret;
288
289         ret = sig_readfn_ofs(opaque, *buf, *len, pos);
290         
291         if (ret == -1) {
292                 return RS_IO_ERROR;
293         }
294
295         *len = ret;
296         return RS_DONE;
297 }
298
299 rs_result rsig_writefn(rs_job_t *job, rs_buffers_t *buf, void *opaque)
300 {
301         struct file_buf *fbuf = (struct file_buf *)opaque;
302         int present;
303
304         if (buf->next_out == NULL) {
305                 buf->next_out = fbuf->buf;
306                 buf->avail_out = sizeof(fbuf->buf);
307                 return RS_DONE;
308         }
309
310         present = buf->next_out - fbuf->buf;
311
312         if (present > 0) {
313                 int ret = sig_writefn(fbuf, fbuf->buf, present);
314         }
315
316         buf->next_out = fbuf->buf;
317         buf->avail_out = sizeof(fbuf->buf);
318
319         return RS_DONE;
320 }
321
322 rs_result rsig_zwritefn(rs_job_t *job, rs_buffers_t *buf, void *opaque)
323 {
324         struct file_buf *fbuf = (struct file_buf *)opaque;
325         int present;
326
327         if (buf->next_out == NULL) {
328                 buf->next_out = fbuf->buf;
329                 buf->avail_out = sizeof(fbuf->buf);
330                 return RS_DONE;
331         }
332
333         present = buf->next_out - fbuf->buf;
334
335         if (present > 0) {
336                 int ret = sig_zwritefn(fbuf, fbuf->buf, present);
337         }
338
339         buf->next_out = fbuf->buf;
340         buf->avail_out = sizeof(fbuf->buf);
341
342         return RS_DONE;
343 }
344
345 /* decode a rsync-encoded file stream, putting the decoded data to
346    f_out and f_cache. The file used to generate the signature is 
347    available in f_orig */
348 void sig_decode(FILE *f_in, FILE *f_out, FILE *f_orig, FILE *f_cache, 
349                 ssize_t content_length)
350 {
351         rs_buffers_t rbuf;
352         struct file_buf fbuf_orig, fbuf_out, fbuf_in;
353         rs_job_t *job;
354         rs_result r;
355
356         fbuf_orig.f = f_orig;
357         fbuf_orig.f_cache = NULL;
358         fbuf_orig.length = -1;
359         fbuf_orig.fn = sig_readfn_ofs;
360
361         fbuf_out.f = f_out;
362         fbuf_out.f_cache = f_cache;
363         fbuf_out.length = -1;
364         fbuf_out.fn = sig_writefn;
365
366         fbuf_in.f = f_in;
367         fbuf_in.f_cache = NULL;
368         fbuf_in.length = content_length;
369         fbuf_in.fn = sig_readfn;
370
371         sig_inbytes = sig_outbytes = 0;
372
373         memset(&rbuf, 0, sizeof(rbuf));
374
375         decomp_init();
376
377         job = rs_patch_begin(rsig_readfn_ofs, &fbuf_orig);
378         r = rs_job_drive(job, &rbuf,
379                          rsig_zreadfn, (void *)&fbuf_in,
380                          rsig_writefn, (void *)&fbuf_out);
381         rs_job_free(job);
382
383         logmsg("librsync_decode->%d (in=%d out=%d)\n", 
384                (int)r, (int)sig_inbytes, (int)sig_outbytes);
385 }
386
387
388 rs_result rsig_readbuf(rs_job_t *job, rs_buffers_t *buf, void *opaque)
389 {
390         struct mem_buf *mbuf = (struct mem_buf *)opaque;
391
392         if (buf->next_in == NULL) {
393                 buf->next_in = mbuf->buf;
394                 buf->avail_in = mbuf->length;
395                 return RS_DONE;
396         }
397
398         if (buf->avail_in == 0) {
399                 buf->eof_in = 1;
400         }
401         
402         return RS_DONE;
403 }
404
405
406
407
408 /* encode a file stream, putting the encoded data to f_out and the
409    unencoded data to f_cache. The signature of the original file is in
410    signature, in base64 form */
411 void sig_encode(FILE *f_in, FILE *f_out, char *signature, FILE *f_cache,
412                 ssize_t content_length)
413 {
414         rs_buffers_t rbuf;
415         struct file_buf fbuf_r, fbuf_w;
416         struct mem_buf mbuf;
417         char *sig2;
418         size_t sig_length;
419         rs_job_t *job;
420         rs_signature_t *sig;
421         rs_result r;
422
423         sig2 = xstrdup(signature);
424         sig_length = base64_decode(sig2);
425
426         fbuf_r.f = f_in;
427         fbuf_r.f_cache = f_cache;
428         fbuf_r.length = content_length;
429
430         logmsg("sig_encode content_length=%d sig_length=%u\n", 
431                content_length, sig_length);
432
433         fbuf_w.f = f_out;
434         fbuf_w.f_cache = NULL;
435         fbuf_w.length = -1;
436
437         mbuf.buf = sig2;
438         mbuf.ofs = 0;
439         mbuf.length = sig_length;
440
441         sig_inbytes = sig_outbytes = 0;
442
443         memset(&rbuf, 0, sizeof(rbuf));
444
445         job = rs_loadsig_begin(&sig);
446         r = rs_job_drive(job, &rbuf,
447                          rsig_readbuf, (void *)&mbuf,
448                          NULL, NULL);
449
450         rs_job_free(job);
451
452         memset(&rbuf, 0, sizeof(rbuf));
453
454         r = rs_build_hash_table(sig);
455
456         comp_init();
457
458         job = rs_delta_begin(sig);
459         r = rs_job_drive(job, &rbuf,
460                          rsig_readfn, (void *)&fbuf_r,
461                          rsig_zwritefn, (void *)&fbuf_w);
462         rs_job_free(job);
463
464         comp_flush(sig_writefn, (void *)&fbuf_w);
465
466         free(sig2);
467         logmsg("librsync_encode->%d (in=%d out=%d)\n", 
468                (int)r, (int)sig_inbytes, (int)sig_outbytes);
469 }