librsync  2.3.1
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 
50 struct rs_filebuf {
51  FILE *f;
52  char *buf;
53  size_t buf_len;
54 };
55 
56 rs_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 
64  return pf;
65 }
66 
67 void rs_filebuf_free(rs_filebuf_t *fb)
68 {
69  free(fb->buf);
70  rs_bzero(fb, sizeof *fb);
71  free(fb);
72 }
73 
74 /* If the stream has no more data available, read some from F into BUF, and let
75  the stream use that. On return, SEEN_EOF is true if the end of file has
76  passed into the stream. */
77 rs_result rs_infilebuf_fill(rs_job_t *job, rs_buffers_t *buf, void *opaque)
78 {
79  size_t len;
80  rs_filebuf_t *fb = (rs_filebuf_t *)opaque;
81  FILE *f = fb->f;
82 
83  /* This is only allowed if either the buf has no input buffer yet, or that
84  buffer could possibly be BUF. */
85  if (buf->next_in != NULL) {
86  assert(buf->avail_in <= fb->buf_len);
87  assert(buf->next_in >= fb->buf);
88  assert(buf->next_in <= fb->buf + fb->buf_len);
89  } else {
90  assert(buf->avail_in == 0);
91  }
92 
93  if (buf->eof_in || (buf->eof_in = feof(f))) {
94  rs_trace("seen end of file on input");
95  buf->eof_in = 1;
96  return RS_DONE;
97  }
98 
99  if (buf->avail_in)
100  /* Still some data remaining. Perhaps we should read anyhow? */
101  return RS_DONE;
102 
103  len = fread(fb->buf, 1, fb->buf_len, f);
104  if (len == 0) {
105  /* This will happen if file size is a multiple of input block len */
106  if (feof(f)) {
107  rs_trace("seen end of file on input");
108  buf->eof_in = 1;
109  return RS_DONE;
110  }
111  if (ferror(f)) {
112  rs_error("error filling buf from file: %s", strerror(errno));
113  return RS_IO_ERROR;
114  } else {
115  rs_error("no error bit, but got " FMT_SIZE
116  " return when trying to read", len);
117  return RS_IO_ERROR;
118  }
119  }
120  buf->avail_in = len;
121  buf->next_in = fb->buf;
122 
123  job->stats.in_bytes += len;
124 
125  return RS_DONE;
126 }
127 
128 /* The buf is already using BUF for an output buffer, and probably contains
129  some buffered output now. Write this out to F, and reset the buffer cursor. */
130 rs_result rs_outfilebuf_drain(rs_job_t *job, rs_buffers_t *buf, void *opaque)
131 {
132  int present;
133  rs_filebuf_t *fb = (rs_filebuf_t *)opaque;
134  FILE *f = fb->f;
135 
136  /* This is only allowed if either the buf has no output buffer yet, or that
137  buffer could possibly be BUF. */
138  if (buf->next_out == NULL) {
139  assert(buf->avail_out == 0);
140 
141  buf->next_out = fb->buf;
142  buf->avail_out = fb->buf_len;
143 
144  return RS_DONE;
145  }
146 
147  assert(buf->avail_out <= fb->buf_len);
148  assert(buf->next_out >= fb->buf);
149  assert(buf->next_out <= fb->buf + fb->buf_len);
150 
151  present = buf->next_out - fb->buf;
152  if (present > 0) {
153  int result;
154 
155  assert(present > 0);
156 
157  result = fwrite(fb->buf, 1, present, f);
158  if (present != result) {
159  rs_error("error draining buf to file: %s", strerror(errno));
160  return RS_IO_ERROR;
161  }
162 
163  buf->next_out = fb->buf;
164  buf->avail_out = fb->buf_len;
165 
166  job->stats.out_bytes += result;
167  }
168 
169  return RS_DONE;
170 }
rs_buffers_s::avail_in
size_t avail_in
Number of bytes available at next_in.
Definition: librsync.h:336
rs_result
rs_result
Return codes from nonblocking rsync operations.
Definition: librsync.h:180
trace.h
RS_DONE
@ RS_DONE
Completed successfully.
Definition: librsync.h:181
rs_stats::in_bytes
rs_long_t in_bytes
Total bytes read from input.
Definition: librsync.h:227
librsync.h
rs_job
The contents of this structure are private.
Definition: job.h:26
rs_buffers_s::next_in
char * next_in
Next input byte.
Definition: librsync.h:328
rs_stats::out_bytes
rs_long_t out_bytes
Total bytes written to output.
Definition: librsync.h:228
rs_filebuf
Definition: buf.c:50
rs_job::stats
rs_stats_t stats
Encoding statistics.
Definition: job.h:72
rs_buffers_s::eof_in
int eof_in
True if there is no more data after this.
Definition: librsync.h:339
RS_IO_ERROR
@ RS_IO_ERROR
Error in file or network IO.
Definition: librsync.h:187
rs_buffers_s::next_out
char * next_out
Next output byte should be put there.
Definition: librsync.h:345
rs_buffers_s::avail_out
size_t avail_out
Remaining free space at next_out.
Definition: librsync.h:351
rs_buffers_s
Description of input and output buffers.
Definition: librsync.h:322