68 #define PROGRAM "rdiff"
71 static size_t strong_len = 0;
73 static int show_stats = 0;
75 static int bzip2_level = 0;
76 static int gzip_level = 0;
77 static int file_force = 0;
80 OPT_GZIP = 1069, OPT_BZIP2
83 extern int rs_roll_paranoia;
86 const struct poptOption opts[] = {
87 {
"verbose",
'v', POPT_ARG_NONE, 0,
'v'},
88 {
"version",
'V', POPT_ARG_NONE, 0,
'V'},
90 {
"output-size",
'O', POPT_ARG_INT, &rs_outbuflen},
91 {
"hash",
'H', POPT_ARG_STRING, &rs_hash_name},
92 {
"help",
'?', POPT_ARG_NONE, 0,
'h'},
93 {0,
'h', POPT_ARG_NONE, 0,
'h'},
94 {
"block-size",
'b', POPT_ARG_INT, &block_len},
95 {
"sum-size",
'S', POPT_ARG_INT, &strong_len},
96 {
"statistics",
's', POPT_ARG_NONE, &show_stats},
97 {
"stats", 0, POPT_ARG_NONE, &show_stats},
98 {
"gzip",
'z', POPT_ARG_NONE, 0, OPT_GZIP},
99 {
"bzip2",
'i', POPT_ARG_NONE, 0, OPT_BZIP2},
100 {
"force",
'f', POPT_ARG_NONE, &file_force},
101 {
"paranoia", 0, POPT_ARG_NONE, &rs_roll_paranoia},
105 static void rdiff_usage(
const char *error)
107 fprintf(stderr,
"%s\n" "Try `%s --help' for more information.\n", error,
111 static void rdiff_no_more_args(poptContext opcon)
113 if (poptGetArg(opcon)) {
114 rdiff_usage(
"rdiff: too many arguments");
119 static void bad_option(poptContext opcon,
int error)
121 fprintf(stderr,
"%s: %s: %s", PROGRAM, poptStrerror(error),
122 poptBadOption(opcon, 0));
126 static void help(
void)
128 printf(
"Usage: rdiff [OPTIONS] signature [BASIS [SIGNATURE]]\n"
129 " [OPTIONS] delta SIGNATURE [NEWFILE [DELTA]]\n"
130 " [OPTIONS] patch BASIS [DELTA [NEWFILE]]\n" "\n"
132 " -v, --verbose Trace internal processing\n"
133 " -V, --version Show program version\n"
134 " -?, --help Show this help message\n"
135 " -s, --statistics Show performance statistics\n"
136 " -f, --force Force overwriting existing files\n"
137 "Signature generation options:\n"
138 " -H, --hash=ALG Hash algorithm: blake2 (default), md4\n"
139 "Delta-encoding options:\n"
140 " -b, --block-size=BYTES Signature block size\n"
141 " -S, --sum-size=BYTES Set signature strength\n"
142 " --paranoia Verify all rolling checksums\n"
143 "IO options:\n" " -I, --input-size=BYTES Input buffer size\n"
144 " -O, --output-size=BYTES Output buffer size\n"
145 " -z, --gzip[=LEVEL] gzip-compress deltas\n"
146 " -i, --bzip2[=LEVEL] bzip2-compress deltas\n");
149 static void rdiff_show_version(
void)
151 char const *bzlib =
"", *zlib =
"", *trace =
"";
165 trace =
", trace disabled";
168 printf(
"rdiff (%s)\n"
169 "Copyright (C) 1997-2016 by Martin Pool, Andrew Tridgell and others.\n"
170 "http://librsync.sourcefrog.net/\n"
171 "Capabilities: %ld bit files%s%s%s\n" "\n"
172 "librsync comes with NO WARRANTY, to the extent permitted by law.\n"
173 "You may redistribute copies of librsync under the terms of the GNU\n"
174 "Lesser General Public License. For more information about these\n"
176 (
long)(8 *
sizeof(rs_long_t)), zlib, bzlib, trace);
179 static void rdiff_options(poptContext opcon)
184 while ((c = poptGetNextOpt(opcon)) != -1) {
190 rdiff_show_version();
194 rs_error(
"library does not support trace");
201 if ((a = poptGetOptArg(opcon))) {
213 rs_error(
"sorry, compression is not really implemented yet");
217 bad_option(opcon, c);
225 FILE *basis_file, *sig_file;
230 basis_file = rs_file_open(poptGetArg(opcon),
"rb", file_force);
231 sig_file = rs_file_open(poptGetArg(opcon),
"wb", file_force);
233 rdiff_no_more_args(opcon);
235 if (!rs_hash_name || !strcmp(rs_hash_name,
"blake2")) {
237 }
else if (!strcmp(rs_hash_name,
"md4")) {
245 rs_error(
"unknown hash algorithm %s", rs_hash_name);
250 rs_sig_file(basis_file, sig_file, block_len, strong_len, sig_magic,
253 rs_file_close(sig_file);
254 rs_file_close(basis_file);
264 static rs_result rdiff_delta(poptContext opcon)
266 FILE *sig_file, *new_file, *delta_file;
267 char const *sig_name;
272 if (!(sig_name = poptGetArg(opcon))) {
273 rdiff_usage(
"Usage for delta: "
274 "rdiff [OPTIONS] delta SIGNATURE [NEWFILE [DELTA]]");
278 sig_file = rs_file_open(sig_name,
"rb", file_force);
279 new_file = rs_file_open(poptGetArg(opcon),
"rb", file_force);
280 delta_file = rs_file_open(poptGetArg(opcon),
"wb", file_force);
282 rdiff_no_more_args(opcon);
294 result =
rs_delta_file(sumset, new_file, delta_file, &stats);
296 rs_file_close(delta_file);
297 rs_file_close(new_file);
298 rs_file_close(sig_file);
301 rs_signature_log_stats(sumset);
310 static rs_result rdiff_patch(poptContext opcon)
313 FILE *basis_file, *delta_file, *new_file;
314 char const *basis_name;
318 if (!(basis_name = poptGetArg(opcon))) {
319 rdiff_usage(
"Usage for patch: "
320 "rdiff [OPTIONS] patch BASIS [DELTA [NEW]]");
324 basis_file = rs_file_open(basis_name,
"rb", file_force);
325 delta_file = rs_file_open(poptGetArg(opcon),
"rb", file_force);
326 new_file = rs_file_open(poptGetArg(opcon),
"wb", file_force);
328 rdiff_no_more_args(opcon);
330 result =
rs_patch_file(basis_file, delta_file, new_file, &stats);
332 rs_file_close(new_file);
333 rs_file_close(delta_file);
334 rs_file_close(basis_file);
342 static rs_result rdiff_action(poptContext opcon)
346 action = poptGetArg(opcon);
348 else if (isprefix(action,
"signature"))
350 else if (isprefix(action,
"delta"))
351 return rdiff_delta(opcon);
352 else if (isprefix(action,
"patch"))
353 return rdiff_patch(opcon);
356 (
"rdiff: You must specify an action: `signature', `delta', or `patch'.");
360 int main(
const int argc,
const char *argv[])
365 opcon = poptGetContext(PROGRAM, argc, argv, opts, 0);
366 rdiff_options(opcon);
367 result = rdiff_action(opcon);
372 poptFreeContext(opcon);
Command line syntax error.
rs_result rs_build_hash_table(rs_signature_t *sums)
Call this after loading a signature to index it.
A signature file using the BLAKE2 hash.
Bad value passed in to library, probably an application bug.
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.
int rs_inbuflen
Buffer sizes for file IO.
rs_result rs_loadsig_file(FILE *sig_file, rs_signature_t **sumset, rs_stats_t *stats)
Load signatures from a signature file into memory.
void rs_free_sumset(rs_signature_t *)
Deep deallocation of checksums.
int rs_supports_trace(void)
Check whether the library was compiled with debugging trace.
Don't show function name in message.
A signature file with MD4 signatures.
Public header for librsync.
Signature of a whole 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.
Performance statistics from a librsync encoding or decoding operation.
char const * rs_strerror(rs_result r)
Return an English description of a rs_result value.
rs_result
Return codes from nonblocking rsync operations.
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.
static rs_result rdiff_sig(poptContext opcon)
Generate signature from remaining command line arguments.
#define RS_DEFAULT_BLOCK_LEN
Default block length, if not determined by any other factors.
char const rs_librsync_version[]
Library version string.
void rs_trace_set_level(rs_loglevel level)
Set the least important message severity that will be output.
int rs_log_stats(rs_stats_t const *stats)
Write statistics into the current log as text.