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 
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  return pf;
64 }
65 
66 void 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. */
76 rs_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. */
126 rs_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.