librsync  2.0.2
whole.c
1 /*= -*- c-basic-offset: 4; indent-tabs-mode: nil; -*-
2  *
3  * librsync -- the library for network deltas
4  *
5  * Copyright 2000, 2001, 2014, 2015 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  | Is it possible that software is not
24  | like anything else, that it is meant
25  | to be discarded: that the whole point
26  | is to always see it as a soap bubble?
27  | -- Alan Perlis
28  */
29 
30 #include "config.h"
31 
32 #include <assert.h>
33 #include <stdlib.h>
34 #ifdef HAVE_UNISTD_H
35 # include <unistd.h>
36 #endif
37 #include <stdio.h>
38 #include <string.h>
39 #include <errno.h>
40 
41 #include "librsync.h"
42 
43 #include "trace.h"
44 #include "fileutil.h"
45 #include "sumset.h"
46 #include "job.h"
47 #include "buf.h"
48 #include "whole.h"
49 #include "util.h"
50 
51 /** Whole file IO buffer sizes. */
52 int rs_inbuflen = 0, rs_outbuflen = 0;
53 
54 /** Run a job continuously, with input to/from the two specified files.
55  *
56  * The job should already be set up, and must be freed by the caller after
57  * return. If rs_inbuflen or rs_outbuflen are set, they will override the
58  * inbuflen and outbuflen arguments.
59  *
60  * \param in_file - input file, or NULL if there is no input.
61  *
62  * \param out_file - output file, or NULL if there is no output.
63  *
64  * \param inbuflen - recommended input buffer size to use.
65  *
66  * \param outbuflen - recommended output buffer size to use.
67  *
68  * \return RS_DONE if the job completed, or otherwise an error result. */
69 rs_result rs_whole_run(rs_job_t *job, FILE *in_file, FILE *out_file,
70  int inbuflen, int outbuflen)
71 {
72  rs_buffers_t buf;
73  rs_result result;
74  rs_filebuf_t *in_fb = NULL, *out_fb = NULL;
75 
76  /* Override buffer sizes if rs_inbuflen or rs_outbuflen are set. */
77  inbuflen = rs_inbuflen ? rs_inbuflen : inbuflen;
78  outbuflen = rs_outbuflen ? rs_outbuflen : outbuflen;
79  if (in_file)
80  in_fb = rs_filebuf_new(in_file, inbuflen);
81  if (out_file)
82  out_fb = rs_filebuf_new(out_file, outbuflen);
83  result =
84  rs_job_drive(job, &buf, in_fb ? rs_infilebuf_fill : NULL, in_fb,
85  out_fb ? rs_outfilebuf_drain : NULL, out_fb);
86  if (in_fb)
87  rs_filebuf_free(in_fb);
88  if (out_fb)
89  rs_filebuf_free(out_fb);
90  return result;
91 }
92 
93 rs_result rs_sig_file(FILE *old_file, FILE *sig_file, size_t new_block_len,
94  size_t strong_len, rs_magic_number sig_magic,
95  rs_stats_t *stats)
96 {
97  rs_job_t *job;
98  rs_result r;
99 
100  job = rs_sig_begin(new_block_len, strong_len, sig_magic);
101  /* Size inbuf for 4 blocks, outbuf for header + 4 blocksums. */
102  r = rs_whole_run(job, old_file, sig_file, 4 * new_block_len,
103  12 + 4 * (4 + strong_len));
104  if (stats)
105  memcpy(stats, &job->stats, sizeof *stats);
106  rs_job_free(job);
107 
108  return r;
109 }
110 
111 rs_result rs_loadsig_file(FILE *sig_file, rs_signature_t **sumset,
112  rs_stats_t *stats)
113 {
114  rs_job_t *job;
115  rs_result r;
116 
117  job = rs_loadsig_begin(sumset);
118  /* Estimate a number of signatures by file size */
119  rs_get_filesize(sig_file, &job->sig_fsize);
120  /* Size inbuf for 1024x 16 byte blocksums. */
121  r = rs_whole_run(job, sig_file, NULL, 1024 * 16, 0);
122  if (stats)
123  memcpy(stats, &job->stats, sizeof *stats);
124  rs_job_free(job);
125 
126  return r;
127 }
128 
129 rs_result rs_delta_file(rs_signature_t *sig, FILE *new_file, FILE *delta_file,
130  rs_stats_t *stats)
131 {
132  rs_job_t *job;
133  rs_result r;
134 
135  job = rs_delta_begin(sig);
136  /* Size inbuf for 1 block, outbuf for literal cmd + 4 blocks. */
137  r = rs_whole_run(job, new_file, delta_file, sig->block_len,
138  10 + 4 * sig->block_len);
139  if (stats)
140  memcpy(stats, &job->stats, sizeof *stats);
141  rs_job_free(job);
142  return r;
143 }
144 
145 rs_result rs_patch_file(FILE *basis_file, FILE *delta_file, FILE *new_file,
146  rs_stats_t *stats)
147 {
148  rs_job_t *job;
149  rs_result r;
150 
151  job = rs_patch_begin(rs_file_copy_cb, basis_file);
152  /* Default size inbuf and outbuf 64K. */
153  r = rs_whole_run(job, delta_file, new_file, 64 * 1024, 64 * 1024);
154  if (stats)
155  memcpy(stats, &job->stats, sizeof *stats);
156  rs_job_free(job);
157  return r;
158 }
rs_job_drive
rs_result rs_job_drive(rs_job_t *job, rs_buffers_t *buf, rs_driven_cb in_cb, void *in_opaque, rs_driven_cb out_cb, void *out_opaque)
Actively process a job, by making callbacks to fill and empty the buffers until the job is done.
Definition: job.c:155
rs_result
rs_result
Definition: librsync.h:161
rs_signature::block_len
int block_len
The block length.
Definition: sumset.h:39
rs_sig_begin
rs_job_t * rs_sig_begin(size_t new_block_len, size_t strong_sum_len, rs_magic_number sig_magic)
Start generating a signature.
Definition: mksum.c:117
trace.h
rs_file_copy_cb
rs_result rs_file_copy_cb(void *arg, rs_long_t pos, size_t *len, void **buf)
rs_copy_cb that reads from a stdio file.
Definition: fileutil.c:137
librsync.h
rs_job::sig_fsize
rs_long_t sig_fsize
The size of the signature file if available.
Definition: job.h:48
rs_job
Definition: job.h:26
rs_filebuf
Definition: buf.c:54
rs_inbuflen
int rs_inbuflen
Buffer sizes for file IO.
Definition: whole.c:52
rs_loadsig_begin
rs_job_t * rs_loadsig_begin(rs_signature_t **)
Read a signature from a file into an rs_signature structure in memory.
Definition: readsums.c:140
rs_job::stats
rs_stats_t stats
Encoding statistics.
Definition: job.h:72
rs_patch_begin
rs_job_t * rs_patch_begin(rs_copy_cb *copy_cb, void *copy_arg)
Apply a delta to a basis file to recreate the new file.
Definition: patch.c:256
rs_delta_begin
rs_job_t * rs_delta_begin(rs_signature_t *sig)
Prepare to compute a streaming delta.
Definition: delta.c:404
rs_sig_file
rs_result rs_sig_file(FILE *old_file, FILE *sig_file, size_t block_len, size_t strong_len, rs_magic_number sig_magic, rs_stats_t *stats)
Generate the signature of a basis file, and write it out to another.
Definition: whole.c:93
rs_signature
Signature of a whole file.
Definition: sumset.h:37
rs_delta_file
rs_result rs_delta_file(rs_signature_t *, FILE *new_file, FILE *delta_file, rs_stats_t *)
Generate a delta between a signature and a new file into a delta file.
Definition: whole.c:129
rs_patch_file
rs_result rs_patch_file(FILE *basis_file, FILE *delta_file, FILE *new_file, rs_stats_t *)
Apply a patch, relative to a basis, into a new file.
Definition: whole.c:145
rs_stats
Performance statistics from a librsync encoding or decoding operation.
Definition: librsync.h:191
rs_magic_number
rs_magic_number
A uint32 magic number, emitted in bigendian/network order at the start of librsync files.
Definition: librsync.h:68
rs_loadsig_file
rs_result rs_loadsig_file(FILE *sig_file, rs_signature_t **sumset, rs_stats_t *stats)
Load signatures from a signature file into memory.
Definition: whole.c:111
rs_buffers_s
Description of input and output buffers.
Definition: librsync.h:300
rs_job_free
rs_result rs_job_free(rs_job_t *job)
Deallocate job state.
Definition: job.c:69