1 /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*-
2  *
3  * librsync -- the library for network deltas
4  * $Id: buf.c,v 1.22 2003/12/16 00:10:55 abo Exp $
5  *
6  * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License 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                                | Pick a window, Jimmy, you're leaving.
25                                |   -- Martin Schwenke, regularly
26                                */
27 
28 
29 /*
30  * buf.c -- Buffers that map between stdio file streams and librsync
31  * streams.  As the stream consumes input and produces output, it is
32  * refilled from appropriate input and output FILEs.  A dynamically
33  * allocated buffer of configurable size is used as an intermediary.
34  */
35 
36 #include "../burp.h"
37 #include "rs_buf.h"
38 #include "../cmd.h"
39 #include "../alloc.h"
40 #include "../asfd.h"
41 #include "../async.h"
42 #include "../handy.h"
43 #include "../iobuf.h"
44 #include "../log.h"
45 
46 /* use fseeko instead of fseek for long file support if we have it */
47 #ifdef HAVE_FSEEKO
48 #define fseek fseeko
49 #endif
50 
rs_filebuf_new(struct BFILE * bfd,struct fzp * fzp,struct asfd * asfd,size_t buf_len,size_t data_len)51 rs_filebuf_t *rs_filebuf_new(struct BFILE *bfd,
52 	struct fzp *fzp,
53 	struct asfd *asfd,
54 	size_t buf_len,
55 	size_t data_len)
56 {
57 	rs_filebuf_t *pf=NULL;
58 	if(!(pf=(struct rs_filebuf *)calloc_w(1,
59 		sizeof(struct rs_filebuf), __func__))
60 	  || !(pf->buf=(char *)calloc_w(1, buf_len, __func__)))
61 		goto error;
62 	pf->buf_len=buf_len;
63 	pf->fzp=fzp;
64 	pf->bfd=bfd;
65 	pf->bytes=0;
66 	pf->data_len=data_len;
67 	if(data_len>0)
68 		pf->do_known_byte_count=1;
69 	else
70 		pf->do_known_byte_count=0;
71 	if(!MD5_Init(&(pf->md5)))
72 	{
73 		logp("MD5_Init() failed\n");
74 		goto error;
75 	}
76 	pf->asfd=asfd;
77 	return pf;
78 error:
79 	rs_filebuf_free(&pf);
80 	return NULL;
81 }
82 
rs_filebuf_free(rs_filebuf_t ** fb)83 void rs_filebuf_free(rs_filebuf_t **fb)
84 {
85 	if(!fb || !*fb) return;
86 	free_w(&((*fb)->buf));
87         free_v((void **)fb);
88 }
89 
90 /*
91  * If the stream has no more data available, read some from F into
92  * BUF, and let the stream use that.  On return, SEEN_EOF is true if
93  * the end of file has passed into the stream.
94  */
rs_infilebuf_fill(rs_job_t * job,rs_buffers_t * buf,void * opaque)95 rs_result rs_infilebuf_fill(__attribute__ ((unused)) rs_job_t *job,
96 	rs_buffers_t *buf, void *opaque)
97 {
98 	int len=0;
99 	rs_filebuf_t *fb=(rs_filebuf_t *) opaque;
100 
101 	//logp("rs_infilebuf_fill\n");
102 
103 	/* This is only allowed if either the buf has no input buffer
104 	 * yet, or that buffer could possibly be BUF. */
105 	if(buf->next_in)
106 	{
107 		//logp("infilebuf avail_in %d buf_len %d\n",
108 		//	buf->avail_in, fb->buf_len);
109 		if(buf->avail_in > fb->buf_len)
110 		{
111 			logp("buf->avail_in > fb->buf_len (%lu > %lu) in %s\n",
112 				(unsigned long)buf->avail_in,
113 				(unsigned long)fb->buf_len, __func__);
114 			return RS_IO_ERROR;
115 		}
116 		if(buf->next_in < fb->buf)
117 		{
118 			logp("buf->next_in < fb->buf in %s\n", __func__);
119 			return RS_IO_ERROR;
120 		}
121 		if(buf->next_in > fb->buf + fb->buf_len)
122 		{
123 			logp("buf->next_in > fb->buf + fb->buf_len in %s\n",
124 				__func__);
125 			return RS_IO_ERROR;
126 		}
127 	}
128 	else
129 	{
130 		if(buf->avail_in)
131 		{
132 			logp("buf->avail_in is %lu in %s\n",
133 				(unsigned long)buf->avail_in, __func__);
134 			return RS_IO_ERROR;
135 		}
136 	}
137 
138 	if(buf->eof_in)
139 		return RS_DONE;
140 
141 	if(buf->avail_in)
142 		/* Still some data remaining.  Perhaps we should read
143 		   anyhow? */
144 		return RS_DONE;
145 
146 	if(fb->asfd)
147 	{
148 		static struct iobuf *rbuf=NULL;
149 		rbuf=fb->asfd->rbuf;
150 
151 		switch(rbuf->cmd)
152 		{
153 			case CMD_APPEND:
154 				memcpy(fb->buf, rbuf->buf, rbuf->len);
155 				len=rbuf->len;
156 				break;
157 			case CMD_END_FILE:
158 				buf->eof_in=1;
159 				return RS_DONE;
160 			default:
161 				iobuf_log_unexpected(rbuf, __func__);
162 				return RS_IO_ERROR;
163 		}
164 	}
165 	else if(fb->bfd)
166 	{
167 		if(fb->do_known_byte_count)
168 		{
169 			if(fb->data_len>0)
170 			{
171 				len=fb->bfd->read(fb->bfd, fb->buf,
172 					min(fb->buf_len, fb->data_len));
173 				fb->data_len-=len;
174 			}
175 			else
176 			{
177 				// We have already read as much data as the VSS
178 				// header told us to, so set len=0 in order to
179 				// finish up.
180 				len=0;
181 			}
182 		}
183 		else
184 			len=fb->bfd->read(fb->bfd, fb->buf, fb->buf_len);
185 		if(len==0)
186 		{
187 			//logp("bread: eof\n");
188 			buf->eof_in=1;
189 			return RS_DONE;
190 		}
191 		else if(len<0)
192 		{
193 			logp("rs_infilebuf_fill: error in bread: %s\n",
194 				strerror(errno));
195 			return RS_IO_ERROR;
196 		}
197 		//logp("bread: ok: %d\n", len);
198 		fb->bytes+=len;
199 		if(!MD5_Update(&(fb->md5), fb->buf, len))
200 		{
201 			logp("rs_infilebuf_fill: MD5_Update() failed\n");
202 			return RS_IO_ERROR;
203 		}
204 	}
205 	else if(fb->fzp)
206 	{
207 		if((len=fzp_read(fb->fzp, fb->buf, fb->buf_len))<=0)
208 		{
209 			// This will happen if file size is a multiple of
210 			// input block len.
211 			if(fzp_eof(fb->fzp))
212 			{
213 				buf->eof_in=1;
214 				return RS_DONE;
215 			}
216 			else
217 			{
218 				logp("rs_infilebuf_fill: got return %d when trying to read\n", len);
219 				return RS_IO_ERROR;
220 			}
221 		}
222 		fb->bytes+=len;
223 		if(!MD5_Update(&(fb->md5), fb->buf, len))
224 		{
225 			logp("rs_infilebuf_fill: MD5_Update() failed\n");
226 			return RS_IO_ERROR;
227 		}
228 	}
229 
230 	buf->avail_in = len;
231 	buf->next_in = fb->buf;
232 
233 	return RS_DONE;
234 }
235 
236 /*
237  * The buf is already using BUF for an output buffer, and probably
238  * contains some buffered output now.  Write this out to F, and reset
239  * the buffer cursor.
240  */
rs_outfilebuf_drain(rs_job_t * job,rs_buffers_t * buf,void * opaque)241 rs_result rs_outfilebuf_drain(__attribute__ ((unused)) rs_job_t *job,
242 	rs_buffers_t *buf, void *opaque)
243 {
244 	rs_filebuf_t *fb=(rs_filebuf_t *)opaque;
245 	size_t wlen;
246 
247 	//logp("in rs_outfilebuf_drain\n");
248 
249 	/* This is only allowed if either the buf has no output buffer
250 	 * yet, or that buffer could possibly be BUF. */
251 	if(!buf->next_out)
252 	{
253 		if(buf->avail_out)
254 		{
255 			logp("buf->avail_out is %lu in %s\n",
256 				(unsigned long)buf->avail_out, __func__);
257 			return RS_IO_ERROR;
258 		}
259 		buf->next_out = fb->buf;
260 		buf->avail_out = fb->buf_len;
261 		return RS_DONE;
262 	}
263 
264 	if(buf->avail_out > fb->buf_len)
265 	{
266 		logp("buf->avail_out > fb->buf_len (%lu > %lu) in %s\n",
267 			(unsigned long)buf->avail_out,
268 			(unsigned long)fb->buf_len, __func__);
269 		return RS_IO_ERROR;
270 	}
271 	if(buf->next_out < fb->buf)
272 	{
273 		logp("buf->next_out < fb->buf (%p < %p) in %s\n",
274 			buf->next_out, fb->buf, __func__);
275 		return RS_IO_ERROR;
276 	}
277 	if(buf->next_out > fb->buf + fb->buf_len)
278 	{
279 		logp("buf->next_out > fb->buf + fb->buf_len in %s\n",
280 			__func__);
281 		return RS_IO_ERROR;
282 	}
283 
284 	if((wlen=buf->next_out-fb->buf)>0)
285 	{
286 		//logp("wlen: %d\n", wlen);
287 		if(fb->asfd)
288 		{
289 			size_t w=wlen;
290 			struct iobuf wbuf;
291 			iobuf_set(&wbuf, CMD_APPEND, fb->buf, wlen);
292 			switch(fb->asfd->append_all_to_write_buffer(
293 				fb->asfd, &wbuf))
294 			{
295 				case APPEND_OK: break;
296 				case APPEND_BLOCKED: return RS_BLOCKED;
297 				case APPEND_ERROR:
298 				default: return RS_IO_ERROR;
299 			}
300 			fb->bytes+=w;
301 		}
302 		else
303 		{
304 			size_t result=0;
305 			result=fzp_write(fb->fzp, fb->buf, wlen);
306 			if(wlen!=result)
307 			{
308 				logp("error draining buf to file: %s",
309 						strerror(errno));
310 				return RS_IO_ERROR;
311 			}
312 		}
313 	}
314 
315 	buf->next_out = fb->buf;
316 	buf->avail_out = fb->buf_len;
317 
318 	return RS_DONE;
319 }
320 
rs_async_drive(rs_job_t * job,rs_buffers_t * rsbuf,rs_driven_cb in_cb,void * in_opaque,rs_driven_cb out_cb,void * out_opaque)321 static rs_result rs_async_drive(rs_job_t *job, rs_buffers_t *rsbuf,
322 	rs_driven_cb in_cb, void *in_opaque,
323 	rs_driven_cb out_cb, void *out_opaque)
324 {
325 	rs_result result;
326 	rs_result iores;
327 
328 	if(!rsbuf->eof_in && in_cb)
329 	{
330 		iores=in_cb(job, rsbuf, in_opaque);
331 		if(iores!=RS_DONE) return iores;
332 	}
333 
334 	result=rs_job_iter(job, rsbuf);
335 	if(result!=RS_DONE && result!=RS_BLOCKED)
336 		return result;
337 
338 	if(out_cb)
339 	{
340 		iores=(out_cb)(job, rsbuf, out_opaque);
341 		if(iores!=RS_DONE) return iores;
342 	}
343 
344 	return result;
345 }
346 
rs_async(rs_job_t * job,rs_buffers_t * rsbuf,rs_filebuf_t * infb,rs_filebuf_t * outfb)347 rs_result rs_async(rs_job_t *job, rs_buffers_t *rsbuf,
348 	rs_filebuf_t *infb, rs_filebuf_t *outfb)
349 {
350 	return rs_async_drive(job, rsbuf,
351 		infb ? rs_infilebuf_fill : NULL, infb,
352 		outfb ? rs_outfilebuf_drain : NULL, outfb);
353 }
354 
rs_whole_gzrun(rs_job_t * job,struct fzp * in_file,struct fzp * out_file)355 static rs_result rs_whole_gzrun(
356 	rs_job_t *job, struct fzp *in_file, struct fzp *out_file)
357 {
358 	rs_buffers_t buf;
359 	rs_result result;
360 	rs_filebuf_t *in_fb=NULL;
361 	rs_filebuf_t *out_fb=NULL;
362 
363 	if(in_file)
364 		in_fb=rs_filebuf_new(NULL,
365 			in_file, NULL, ASYNC_BUF_LEN, -1);
366 	if(out_file)
367 		out_fb=rs_filebuf_new(NULL,
368 			out_file, NULL, ASYNC_BUF_LEN, -1);
369 
370 	result=rs_job_drive(job, &buf,
371 		in_fb ? rs_infilebuf_fill : NULL, in_fb,
372 		out_fb ? rs_outfilebuf_drain : NULL, out_fb);
373 
374 	rs_filebuf_free(&in_fb);
375 	rs_filebuf_free(&out_fb);
376 	return result;
377 }
378 
rs_patch_gzfile(struct fzp * basis_file,struct fzp * delta_file,struct fzp * new_file)379 rs_result rs_patch_gzfile(struct fzp *basis_file,
380 	struct fzp *delta_file, struct fzp *new_file)
381 {
382 	rs_job_t *job;
383 	rs_result r;
384 
385 	// FIX THIS: Seems wrong to just pick out basis_file->fp.
386 	// Should probably pass a fp into rs_patch_gzfile.
387 	// Or, much better would be to investigate whether basis_file always
388 	// needs to be a FILE *. If I copy rs_file_copy_cb from librsync, and
389 	// rewrite it to use a struct fzp, maybe the callers to rs_patch_gzfile
390 	// do not need to mess around inflating files when they do not have
391 	// to.
392 	job=rs_patch_begin(rs_file_copy_cb, basis_file->fp);
393 	r=rs_whole_gzrun(job, delta_file, new_file);
394 	rs_job_free(job);
395 
396 	return r;
397 }
398 
rs_sig_gzfile(struct fzp * old_file,struct fzp * sig_file,size_t new_block_len,size_t strong_len,struct conf ** confs)399 rs_result rs_sig_gzfile(struct fzp *old_file, struct fzp *sig_file,
400 	size_t new_block_len, size_t strong_len,
401 	struct conf **confs)
402 {
403 	rs_job_t *job;
404 	rs_result r;
405 	job=
406 		rs_sig_begin(new_block_len, strong_len
407 #ifndef RS_DEFAULT_STRONG_LEN
408                   	, rshash_to_magic_number(
409 				get_e_rshash(confs[OPT_RSHASH]))
410 #endif
411 		);
412 
413 	r=rs_whole_gzrun(job, old_file, sig_file);
414 	rs_job_free(job);
415 
416 	return r;
417 }
418 
rs_delta_gzfile(rs_signature_t * sig,struct fzp * new_file,struct fzp * delta_file)419 rs_result rs_delta_gzfile(rs_signature_t *sig, struct fzp *new_file,
420 	struct fzp *delta_file)
421 {
422 	rs_job_t *job;
423 	rs_result r;
424 
425 	job=rs_delta_begin(sig);
426 	r=rs_whole_gzrun(job, new_file, delta_file);
427 	rs_job_free(job);
428 
429 	return r;
430 }
431 
432 #ifndef RS_DEFAULT_STRONG_LEN
rshash_to_magic_number(enum rshash r)433 rs_magic_number rshash_to_magic_number(enum rshash r)
434 {
435 	switch(r)
436 	{
437 		case RSHASH_BLAKE2:
438 			return RS_BLAKE2_SIG_MAGIC;
439 		default:
440 			return RS_MD4_SIG_MAGIC;
441 	}
442 }
443 #endif
444 
rs_loadsig_fzp(struct fzp * fzp,rs_signature_t ** sig)445 rs_result rs_loadsig_fzp(struct fzp *fzp, rs_signature_t **sig)
446 {
447 	rs_result r;
448 	rs_job_t *job;
449 
450 	job=rs_loadsig_begin(sig);
451 	r=rs_whole_gzrun(job, fzp, NULL);
452 	rs_job_free(job);
453 
454 	return r;
455 }
456