librsync  2.3.4
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 "config.h" /* IWYU pragma: keep */
27 #include <assert.h>
28 #include <stdlib.h>
29 #include <errno.h>
30 #include <string.h>
31 #include "librsync.h"
32 #include "buf.h"
33 #include "job.h"
34 #include "trace.h"
35 #include "util.h"
36 
37 struct rs_filebuf {
38  FILE *f;
39  char *buf;
40  size_t buf_len;
41 };
42 
43 rs_filebuf_t *rs_filebuf_new(FILE *f, size_t buf_len)
44 {
46 
47  pf->buf = rs_alloc(buf_len, "file buffer");
48  pf->buf_len = buf_len;
49  pf->f = f;
50  return pf;
51 }
52 
53 void rs_filebuf_free(rs_filebuf_t *fb)
54 {
55  free(fb->buf);
56  rs_bzero(fb, sizeof *fb);
57  free(fb);
58 }
59 
60 /* If the stream has no more data available, read some from F into BUF, and let
61  the stream use that. On return, SEEN_EOF is true if the end of file has
62  passed into the stream. */
63 rs_result rs_infilebuf_fill(rs_job_t *job, rs_buffers_t *buf, void *opaque)
64 {
65  size_t len;
66  rs_filebuf_t *fb = (rs_filebuf_t *)opaque;
67  FILE *f = fb->f;
68 
69  /* If buf has data, it must be in the buffer. */
70  if (buf->avail_in) {
71  assert(buf->next_in >= fb->buf);
72  assert(buf->next_in + buf->avail_in <= fb->buf + fb->buf_len);
73  }
74  if (buf->eof_in) {
75  return RS_DONE;
76  } else if (buf->avail_in > fb->buf_len / 2) {
77  /* Buf is already full enough, do nothing. */
78  return RS_DONE;
79  } else if (buf->avail_in) {
80  /* Some leftover tail data, move it to the front of the buffer. */
81  rs_trace("moving buffer " FMT_SIZE " bytes to reuse " FMT_SIZE " bytes",
82  buf->avail_in, (size_t)(buf->next_in - fb->buf));
83  memmove(fb->buf, buf->next_in, buf->avail_in);
84  }
85  buf->next_in = fb->buf;
86  len = fread(fb->buf + buf->avail_in, 1, fb->buf_len - buf->avail_in, f);
87  if (len == 0) {
88  if ((buf->eof_in = feof(f))) {
89  rs_trace("seen end of file on input");
90  return RS_DONE;
91  } else {
92  rs_error("error filling buf from file: %s", strerror(errno));
93  return RS_IO_ERROR;
94  }
95  }
96  buf->avail_in += len;
97  job->stats.in_bytes += len;
98  return RS_DONE;
99 }
100 
101 /* The buf is already using BUF for an output buffer, and probably contains
102  some buffered output now. Write this out to F, and reset the buffer cursor. */
103 rs_result rs_outfilebuf_drain(rs_job_t *job, rs_buffers_t *buf, void *opaque)
104 {
105  rs_filebuf_t *fb = (rs_filebuf_t *)opaque;
106  FILE *f = fb->f;
107 
108  /* If next_out is NULL, we haven't pointed it at fb->buf yet. */
109  if (!buf->next_out) {
110  assert(buf->avail_out == 0);
111  buf->next_out = fb->buf;
112  buf->avail_out = fb->buf_len;
113  }
114  /* The buf output buffer must be at the end of fb->buf. */
115  assert(buf->next_out >= fb->buf);
116  assert(buf->next_out + buf->avail_out == fb->buf + fb->buf_len);
117 
118  size_t present = buf->next_out - fb->buf;
119  if (present > 0) {
120  size_t result = fwrite(fb->buf, 1, present, f);
121  if (present != result) {
122  rs_error("error draining buf to file: %s", strerror(errno));
123  return RS_IO_ERROR;
124  }
125  buf->next_out = fb->buf;
126  buf->avail_out = fb->buf_len;
127  job->stats.out_bytes += result;
128  }
129  return RS_DONE;
130 }
Description of input and output buffers.
Definition: librsync.h:328
logging functions.
Definition: buf.c:37
size_t avail_out
Remaining free space at next_out.
Definition: librsync.h:357
#define rs_alloc_struct(type)
Allocate and zero-fill an instance of TYPE.
Definition: util.h:41
char * next_out
Next output byte should be put there.
Definition: librsync.h:351
size_t avail_in
Number of bytes available at next_in.
Definition: librsync.h:342
rs_long_t out_bytes
Total bytes written to output.
Definition: librsync.h:228
Error in file or network IO.
Definition: librsync.h:187
rs_stats_t stats
Encoding statistics.
Definition: job.h:93
rs_long_t in_bytes
Total bytes read from input.
Definition: librsync.h:227
Public header for librsync.
Buffers that map between stdio file streams and librsync streams.
Misc utility functions used by librsync.
char * next_in
Next input byte.
Definition: librsync.h:334
rs_result
Return codes from nonblocking rsync operations.
Definition: librsync.h:180
Generic state-machine interface.
int eof_in
True if there is no more data after this.
Definition: librsync.h:345
Completed successfully.
Definition: librsync.h:181
The contents of this structure are private.
Definition: job.h:47