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
37struct rs_filebuf {
38 FILE *f;
39 char *buf;
40 size_t buf_len;
41};
42
43rs_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
53void 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. */
63rs_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. */
103rs_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}
Buffers that map between stdio file streams and librsync streams.
Generic state-machine interface.
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:328
char * next_in
Next input byte.
Definition: librsync.h:334
size_t avail_in
Number of bytes available at next_in.
Definition: librsync.h:342
int eof_in
True if there is no more data after this.
Definition: librsync.h:345
size_t avail_out
Remaining free space at next_out.
Definition: librsync.h:357
char * next_out
Next output byte should be put there.
Definition: librsync.h:351
Definition: buf.c:37
The contents of this structure are private.
Definition: job.h:47
rs_stats_t stats
Encoding statistics.
Definition: job.h:93
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.
Misc utility functions used by librsync.
#define rs_alloc_struct(type)
Allocate and zero-fill an instance of TYPE.
Definition: util.h:41