summaryrefslogtreecommitdiff
path: root/rsync/buf.c
Unidiff
Diffstat (limited to 'rsync/buf.c') (more/less context) (ignore whitespace changes)
-rw-r--r--rsync/buf.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/rsync/buf.c b/rsync/buf.c
index c978fff..fdd67ee 100644
--- a/rsync/buf.c
+++ b/rsync/buf.c
@@ -1,216 +1,218 @@
1/*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- 1/*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*-
2 * 2 *
3 * librsync -- the library for network deltas 3 * librsync -- the library for network deltas
4 * $Id$ 4 * $Id$
5 * 5 *
6 * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org> 6 * Copyright (C) 2000, 2001 by Martin Pool <mbp@samba.org>
7 * 7 *
8 * This program is free software; you can redistribute it and/or 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 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 10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version. 11 * the License, or (at your option) any later version.
12 * 12 *
13 * This program is distributed in the hope that it will be useful, but 13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details. 16 * Lesser General Public License for more details.
17 * 17 *
18 * You should have received a copy of the GNU Lesser General Public 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 19 * License along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */ 21 */
22 22
23 /* 23 /*
24 | Pick a window, Jimmy, you're leaving. 24 | Pick a window, Jimmy, you're leaving.
25 | -- Martin Schwenke, regularly 25 | -- Martin Schwenke, regularly
26 */ 26 */
27 27
28 28
29/* 29/*
30 * buf.c -- Buffers that map between stdio file streams and librsync 30 * buf.c -- Buffers that map between stdio file streams and librsync
31 * streams. As the stream consumes input and produces output, it is 31 * streams. As the stream consumes input and produces output, it is
32 * refilled from appropriate input and output FILEs. A dynamically 32 * refilled from appropriate input and output FILEs. A dynamically
33 * allocated buffer of configurable size is used as an intermediary. 33 * allocated buffer of configurable size is used as an intermediary.
34 * 34 *
35 * TODO: Perhaps be more efficient by filling the buffer on every call 35 * TODO: Perhaps be more efficient by filling the buffer on every call
36 * even if not yet completely empty. Check that it's really our 36 * even if not yet completely empty. Check that it's really our
37 * buffer, and shuffle remaining data down to the front. 37 * buffer, and shuffle remaining data down to the front.
38 * 38 *
39 * TODO: Perhaps expose a routine for shuffling the buffers. 39 * TODO: Perhaps expose a routine for shuffling the buffers.
40 */ 40 */
41 41
42 42
43#include <config_rsync.h> 43#include <config_rsync.h>
44 44
45#include <assert.h> 45#include <assert.h>
46#include <stdlib.h> 46#include <stdlib.h>
47#include <stdio.h> 47#include <stdio.h>
48#include <errno.h> 48#include <errno.h>
49#include <string.h> 49#include <string.h>
50 50
51#include "rsync.h" 51#include "rsync.h"
52#include "trace.h" 52#include "trace.h"
53#include "buf.h" 53#include "buf.h"
54#include "util.h" 54#include "util.h"
55 55
56/** 56/**
57 * File IO buffer sizes. 57 * File IO buffer sizes.
58 */ 58 */
59int rs_inbuflen = 16000, rs_outbuflen = 16000; 59int rs_inbuflen = 16000, rs_outbuflen = 16000;
60 60
61 61
62struct rs_filebuf { 62struct rs_filebuf {
63 FILE *f; 63 FILE *f;
64 char *buf; 64 char *buf;
65 size_t buf_len; 65 size_t buf_len;
66}; 66};
67 67
68 68
69 69
70rs_filebuf_t *rs_filebuf_new(FILE *f, size_t buf_len) 70rs_filebuf_t *rs_filebuf_new(FILE *f, size_t buf_len)
71{ 71{
72 rs_filebuf_t *pf = rs_alloc_struct(rs_filebuf_t); 72 rs_filebuf_t *pf = rs_alloc_struct(rs_filebuf_t);
73 73
74 pf->buf = rs_alloc(buf_len, "file buffer"); 74 pf->buf = rs_alloc(buf_len, "file buffer");
75 pf->buf_len = buf_len; 75 pf->buf_len = buf_len;
76 pf->f = f; 76 pf->f = f;
77 77
78 return pf; 78 return pf;
79} 79}
80 80
81 81
82void rs_filebuf_free(rs_filebuf_t *fb) 82void rs_filebuf_free(rs_filebuf_t *fb)
83{ 83{
84 if ( fb->buf ) 84 if ( fb->buf )
85 free ( fb->buf ); 85 free ( fb->buf );
86 rs_bzero(fb, sizeof *fb); 86 rs_bzero(fb, sizeof *fb);
87 free(fb); 87 free(fb);
88} 88}
89 89
90 90
91/* 91/*
92 * If the stream has no more data available, read some from F into 92 * If the stream has no more data available, read some from F into
93 * BUF, and let the stream use that. On return, SEEN_EOF is true if 93 * BUF, and let the stream use that. On return, SEEN_EOF is true if
94 * the end of file has passed into the stream. 94 * the end of file has passed into the stream.
95 */ 95 */
96rs_result rs_infilebuf_fill(rs_job_t *job, rs_buffers_t *buf, 96rs_result rs_infilebuf_fill(rs_job_t *job, rs_buffers_t *buf,
97 void *opaque) 97 void *opaque)
98{ 98{
99 job=job;
100 int len; 99 int len;
101 rs_filebuf_t *fb = (rs_filebuf_t *) opaque; 100 rs_filebuf_t *fb = (rs_filebuf_t *) opaque;
102 FILE *f = fb->f; 101 FILE *f = fb->f;
102
103 job=job; // fix unused warning
103 104
104 /* This is only allowed if either the buf has no input buffer 105 /* This is only allowed if either the buf has no input buffer
105 * yet, or that buffer could possibly be BUF. */ 106 * yet, or that buffer could possibly be BUF. */
106 if (buf->next_in != NULL) { 107 if (buf->next_in != NULL) {
107 assert(buf->avail_in <= fb->buf_len); 108 assert(buf->avail_in <= fb->buf_len);
108 assert(buf->next_in >= fb->buf); 109 assert(buf->next_in >= fb->buf);
109 assert(buf->next_in <= fb->buf + fb->buf_len); 110 assert(buf->next_in <= fb->buf + fb->buf_len);
110 } else { 111 } else {
111 assert(buf->avail_in == 0); 112 assert(buf->avail_in == 0);
112 } 113 }
113 114
114 if (buf->eof_in || (buf->eof_in = feof(f))) { 115 if (buf->eof_in || (buf->eof_in = feof(f))) {
115 rs_trace("seen end of file on input"); 116 rs_trace("seen end of file on input");
116 buf->eof_in = 1; 117 buf->eof_in = 1;
117 return RS_DONE; 118 return RS_DONE;
118 } 119 }
119 120
120 if (buf->avail_in) 121 if (buf->avail_in)
121 /* Still some data remaining. Perhaps we should read 122 /* Still some data remaining. Perhaps we should read
122 anyhow? */ 123 anyhow? */
123 return RS_DONE; 124 return RS_DONE;
124 125
125 len = fread(fb->buf, 1, fb->buf_len, f); 126 len = fread(fb->buf, 1, fb->buf_len, f);
126 if (len < 0) { 127 if (len < 0) {
127 if (ferror(f)) { 128 if (ferror(f)) {
128 rs_error("error filling buf from file: %s", 129 rs_error("error filling buf from file: %s",
129 strerror(errno)); 130 strerror(errno));
130 return RS_IO_ERROR; 131 return RS_IO_ERROR;
131 } else { 132 } else {
132 rs_error("no error bit, but got %d return when trying to read", 133 rs_error("no error bit, but got %d return when trying to read",
133 len); 134 len);
134 return RS_IO_ERROR; 135 return RS_IO_ERROR;
135 } 136 }
136 } 137 }
137 buf->avail_in = len; 138 buf->avail_in = len;
138 buf->next_in = fb->buf; 139 buf->next_in = fb->buf;
139 140
140 return RS_DONE; 141 return RS_DONE;
141} 142}
142 143
143 144
144/* 145/*
145 * The buf is already using BUF for an output buffer, and probably 146 * The buf is already using BUF for an output buffer, and probably
146 * contains some buffered output now. Write this out to F, and reset 147 * contains some buffered output now. Write this out to F, and reset
147 * the buffer cursor. 148 * the buffer cursor.
148 */ 149 */
149rs_result rs_outfilebuf_drain(rs_job_t *job, rs_buffers_t *buf, void *opaque) 150rs_result rs_outfilebuf_drain(rs_job_t *job, rs_buffers_t *buf, void *opaque)
150{ 151{
151 job=job;
152 int present; 152 int present;
153 rs_filebuf_t *fb = (rs_filebuf_t *) opaque; 153 rs_filebuf_t *fb = (rs_filebuf_t *) opaque;
154 FILE *f = fb->f; 154 FILE *f = fb->f;
155 155
156 job=job; // fix unused warning
157
156 /* This is only allowed if either the buf has no output buffer 158 /* This is only allowed if either the buf has no output buffer
157 * yet, or that buffer could possibly be BUF. */ 159 * yet, or that buffer could possibly be BUF. */
158 if (buf->next_out == NULL) { 160 if (buf->next_out == NULL) {
159 assert(buf->avail_out == 0); 161 assert(buf->avail_out == 0);
160 162
161 buf->next_out = fb->buf; 163 buf->next_out = fb->buf;
162 buf->avail_out = fb->buf_len; 164 buf->avail_out = fb->buf_len;
163 165
164 return RS_DONE; 166 return RS_DONE;
165 } 167 }
166 168
167 assert(buf->avail_out <= fb->buf_len); 169 assert(buf->avail_out <= fb->buf_len);
168 assert(buf->next_out >= fb->buf); 170 assert(buf->next_out >= fb->buf);
169 assert(buf->next_out <= fb->buf + fb->buf_len); 171 assert(buf->next_out <= fb->buf + fb->buf_len);
170 172
171 present = buf->next_out - fb->buf; 173 present = buf->next_out - fb->buf;
172 if (present > 0) { 174 if (present > 0) {
173 int result; 175 int result;
174 176
175 assert(present > 0); 177 assert(present > 0);
176 178
177 result = fwrite(fb->buf, 1, present, f); 179 result = fwrite(fb->buf, 1, present, f);
178 if (present != result) { 180 if (present != result) {
179 rs_error("error draining buf to file: %s", 181 rs_error("error draining buf to file: %s",
180 strerror(errno)); 182 strerror(errno));
181 return RS_IO_ERROR; 183 return RS_IO_ERROR;
182 } 184 }
183 185
184 buf->next_out = fb->buf; 186 buf->next_out = fb->buf;
185 buf->avail_out = fb->buf_len; 187 buf->avail_out = fb->buf_len;
186 } 188 }
187 189
188 return RS_DONE; 190 return RS_DONE;
189} 191}
190 192
191 193
192/** 194/**
193 * Default copy implementation that retrieves a part of a stdio file. 195 * Default copy implementation that retrieves a part of a stdio file.
194 */ 196 */
195rs_result rs_file_copy_cb(void *arg, off_t pos, size_t *len, void **buf) 197rs_result rs_file_copy_cb(void *arg, off_t pos, size_t *len, void **buf)
196{ 198{
197 int got; 199 int got;
198 FILE *f = (FILE *) arg; 200 FILE *f = (FILE *) arg;
199 201
200 if (fseek(f, pos, SEEK_SET)) { 202 if (fseek(f, pos, SEEK_SET)) {
201 rs_log(RS_LOG_ERR, "seek failed: %s", strerror(errno)); 203 rs_log(RS_LOG_ERR, "seek failed: %s", strerror(errno));
202 return RS_IO_ERROR; 204 return RS_IO_ERROR;
203 } 205 }
204 206
205 got = fread(*buf, 1, *len, f); 207 got = fread(*buf, 1, *len, f);
206 if (got == -1) { 208 if (got == -1) {
207 rs_error(strerror(errno)); 209 rs_error(strerror(errno));
208 return RS_IO_ERROR; 210 return RS_IO_ERROR;
209 } else if (got == 0) { 211 } else if (got == 0) {
210 rs_error("unexpected eof on fd%d", fileno(f)); 212 rs_error("unexpected eof on fd%d", fileno(f));
211 return RS_INPUT_ENDED; 213 return RS_INPUT_ENDED;
212 } else { 214 } else {
213 *len = got; 215 *len = got;
214 return RS_DONE; 216 return RS_DONE;
215 } 217 }
216} 218}