librsync  2.3.2
buf.c
Go to the documentation of this file.
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/** \file buf.c
27 * Buffers that map between stdio file streams and librsync streams.
28 *
29 * As the stream consumes input and produces output, it is refilled from
30 * appropriate input and output FILEs. A dynamically allocated buffer of
31 * configurable size is used as an intermediary.
32 *
33 * \todo Perhaps be more efficient by filling the buffer on every call even if
34 * not yet completely empty. Check that it's really our buffer, and shuffle
35 * remaining data down to the front.
36 *
37 * \todo Perhaps expose a routine for shuffling the buffers. */
38
39#include "config.h"
40#include <assert.h>
41#include <stdlib.h>
42#include <errno.h>
43#include <string.h>
44#include "librsync.h"
45#include "buf.h"
46#include "job.h"
47#include "trace.h"
48#include "util.h"
49
50struct rs_filebuf {
51 FILE *f;
52 char *buf;
53 size_t buf_len;
54};
55
56rs_filebuf_t *rs_filebuf_new(FILE *f, size_t buf_len)
57{
58 rs_filebuf_t *pf = rs_alloc_struct(rs_filebuf_t);
59
60 pf->buf = rs_alloc(buf_len, "file buffer");
61 pf->buf_len = buf_len;
62 pf->f = f;
63 return pf;
64}
65
66void rs_filebuf_free(rs_filebuf_t *fb)
67{
68 free(fb->buf);
69 rs_bzero(fb, sizeof *fb);
70 free(fb);
71}
72
73/* If the stream has no more data available, read some from F into BUF, and let
74 the stream use that. On return, SEEN_EOF is true if the end of file has
75 passed into the stream. */
76rs_result rs_infilebuf_fill(rs_job_t *job, rs_buffers_t *buf, void *opaque)
77{
78 size_t len;
79 rs_filebuf_t *fb = (rs_filebuf_t *)opaque;
80 FILE *f = fb->f;
81
82 /* This is only allowed if either the buf has no input buffer yet, or that
83 buffer could possibly be BUF. */
84 if (buf->next_in != NULL) {
85 assert(buf->avail_in <= fb->buf_len);
86 assert(buf->next_in >= fb->buf);
87 assert(buf->next_in <= fb->buf + fb->buf_len);
88 } else {
89 assert(buf->avail_in == 0);
90 }
91
92 if (buf->eof_in || (buf->eof_in = feof(f))) {
93 rs_trace("seen end of file on input");
94 return RS_DONE;
95 }
96
97 if (buf->avail_in)
98 /* Still some data remaining. Perhaps we should read anyhow? */
99 return RS_DONE;
100
101 len = fread(fb->buf, 1, fb->buf_len, f);
102 if (len == 0) {
103 /* This will happen if file size is a multiple of input block len */
104 if (feof(f)) {
105 rs_trace("seen end of file on input");
106 buf->eof_in = 1;
107 return RS_DONE;
108 }
109 if (ferror(f)) {
110 rs_error("error filling buf from file: %s", strerror(errno));
111 return RS_IO_ERROR;
112 } else {
113 rs_error("no error bit, but got " FMT_SIZE
114 " return when trying to read", len);
115 return RS_IO_ERROR;
116 }
117 }
118 buf->avail_in = len;
119 buf->next_in = fb->buf;
120 job->stats.in_bytes += len;
121 return RS_DONE;
122}
123
124/* The buf is already using BUF for an output buffer, and probably contains
125 some buffered output now. Write this out to F, and reset the buffer cursor. */
126rs_result rs_outfilebuf_drain(rs_job_t *job, rs_buffers_t *buf, void *opaque)
127{
128 rs_filebuf_t *fb = (rs_filebuf_t *)opaque;
129 FILE *f = fb->f;
130
131 /* This is only allowed if either the buf has no output buffer yet, or that
132 buffer could possibly be BUF. */
133 if (buf->next_out == NULL) {
134 assert(buf->avail_out == 0);
135 buf->next_out = fb->buf;
136 buf->avail_out = fb->buf_len;
137 return RS_DONE;
138 }
139
140 assert(buf->avail_out <= fb->buf_len);
141 assert(buf->next_out >= fb->buf);
142 assert(buf->next_out <= fb->buf + fb->buf_len);
143
144 size_t present = buf->next_out - fb->buf;
145 if (present > 0) {
146 size_t result = fwrite(fb->buf, 1, present, f);
147 if (present != result) {
148 rs_error("error draining buf to file: %s", strerror(errno));
149 return RS_IO_ERROR;
150 }
151 buf->next_out = fb->buf;
152 buf->avail_out = fb->buf_len;
153 job->stats.out_bytes += result;
154 }
155 return RS_DONE;
156}
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:322
char * next_in
Next input byte.
Definition: librsync.h:328
size_t avail_in
Number of bytes available at next_in.
Definition: librsync.h:336
int eof_in
True if there is no more data after this.
Definition: librsync.h:339
size_t avail_out
Remaining free space at next_out.
Definition: librsync.h:351
char * next_out
Next output byte should be put there.
Definition: librsync.h:345
Definition: buf.c:50
The contents of this structure are private.
Definition: job.h:26
rs_stats_t stats
Encoding statistics.
Definition: job.h:72
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.