librsync  2.3.3
buf.c
1/*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*-
2 *
3 * librsync -- the library for network deltas
4 *
5 * Copyright (C) 2000, 2001 by Martin Pool <mbp@sourcefrog.net>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 /*=
23 | Pick a window, Jimmy, you're leaving.
24 */
25
26#include <assert.h>
27#include <stdlib.h>
28#include <errno.h>
29#include <string.h>
30#include "librsync.h"
31#include "buf.h"
32#include "job.h"
33#include "trace.h"
34#include "util.h"
35
36struct rs_filebuf {
37 FILE *f;
38 char *buf;
39 size_t buf_len;
40};
41
42rs_filebuf_t *rs_filebuf_new(FILE *f, size_t buf_len)
43{
45
46 pf->buf = rs_alloc(buf_len, "file buffer");
47 pf->buf_len = buf_len;
48 pf->f = f;
49 return pf;
50}
51
52void rs_filebuf_free(rs_filebuf_t *fb)
53{
54 free(fb->buf);
55 rs_bzero(fb, sizeof *fb);
56 free(fb);
57}
58
59/* If the stream has no more data available, read some from F into BUF, and let
60 the stream use that. On return, SEEN_EOF is true if the end of file has
61 passed into the stream. */
62rs_result rs_infilebuf_fill(rs_job_t *job, rs_buffers_t *buf, void *opaque)
63{
64 size_t len;
65 rs_filebuf_t *fb = (rs_filebuf_t *)opaque;
66 FILE *f = fb->f;
67
68 /* If buf has data, it must be in the buffer. */
69 if (buf->avail_in) {
70 assert(buf->next_in >= fb->buf);
71 assert(buf->next_in + buf->avail_in <= fb->buf + fb->buf_len);
72 }
73 if (buf->eof_in) {
74 return RS_DONE;
75 } else if (buf->avail_in > fb->buf_len / 2) {
76 /* Buf is already full enough, do nothing. */
77 return RS_DONE;
78 } else if (buf->avail_in) {
79 /* Some leftover tail data, move it to the front of the buffer. */
80 rs_trace("moving buffer " FMT_SIZE " bytes to reuse " FMT_SIZE " bytes",
81 buf->avail_in, (size_t)(buf->next_in - fb->buf));
82 memmove(fb->buf, buf->next_in, buf->avail_in);
83 }
84 buf->next_in = fb->buf;
85 len = fread(fb->buf + buf->avail_in, 1, fb->buf_len - buf->avail_in, f);
86 if (len == 0) {
87 if ((buf->eof_in = feof(f))) {
88 rs_trace("seen end of file on input");
89 return RS_DONE;
90 } else {
91 rs_error("error filling buf from file: %s", strerror(errno));
92 return RS_IO_ERROR;
93 }
94 }
95 buf->avail_in += len;
96 job->stats.in_bytes += len;
97 return RS_DONE;
98}
99
100/* The buf is already using BUF for an output buffer, and probably contains
101 some buffered output now. Write this out to F, and reset the buffer cursor. */
102rs_result rs_outfilebuf_drain(rs_job_t *job, rs_buffers_t *buf, void *opaque)
103{
104 rs_filebuf_t *fb = (rs_filebuf_t *)opaque;
105 FILE *f = fb->f;
106
107 /* If next_out is NULL, we haven't pointed it at fb->buf yet. */
108 if (!buf->next_out) {
109 assert(buf->avail_out == 0);
110 buf->next_out = fb->buf;
111 buf->avail_out = fb->buf_len;
112 }
113 /* The buf output buffer must be at the end of fb->buf. */
114 assert(buf->next_out >= fb->buf);
115 assert(buf->next_out + buf->avail_out == fb->buf + fb->buf_len);
116
117 size_t present = buf->next_out - fb->buf;
118 if (present > 0) {
119 size_t result = fwrite(fb->buf, 1, present, f);
120 if (present != result) {
121 rs_error("error draining buf to file: %s", strerror(errno));
122 return RS_IO_ERROR;
123 }
124 buf->next_out = fb->buf;
125 buf->avail_out = fb->buf_len;
126 job->stats.out_bytes += result;
127 }
128 return RS_DONE;
129}
Buffers that map between stdio file streams and librsync streams.
Generic state-machine interface.
Public header for librsync.
rs_result
Return codes from nonblocking rsync operations.
Definition: librsync.h:180
@ RS_DONE
Completed successfully.
Definition: librsync.h:181
@ RS_IO_ERROR
Error in file or network IO.
Definition: librsync.h:187
Description of input and output buffers.
Definition: librsync.h:328
char * next_in
Next input byte.
Definition: librsync.h:334
size_t avail_in
Number of bytes available at next_in.
Definition: librsync.h:342
int eof_in
True if there is no more data after this.
Definition: librsync.h:345
size_t avail_out
Remaining free space at next_out.
Definition: librsync.h:357
char * next_out
Next output byte should be put there.
Definition: librsync.h:351
Definition: buf.c:36
The contents of this structure are private.
Definition: job.h:47
rs_stats_t stats
Encoding statistics.
Definition: job.h:93
rs_long_t out_bytes
Total bytes written to output.
Definition: librsync.h:228
rs_long_t in_bytes
Total bytes read from input.
Definition: librsync.h:227
logging functions.
Misc utility functions used by librsync.
#define rs_alloc_struct(type)
Allocate and zero-fill an instance of TYPE.
Definition: util.h:41