diff options
author | Martin Pool <mbp@sourcefrog.net> | 2001-02-07 23:24:41 +0000 |
---|---|---|
committer | Martin Pool <mbp@sourcefrog.net> | 2001-02-07 23:24:41 +0000 |
commit | 51114f4d0169297d540373705f6f3d014bc4b2a3 (patch) | |
tree | ef423d9c280f7e77cf6a3e46b35598674d0842b6 | |
parent | 819e089b8437e909f5362230057914ecbc672c6d (diff) | |
download | librsync-51114f4d0169297d540373705f6f3d014bc4b2a3.tar.gz |
Change to a generic hs_job_t class so we can share the iterator code.
Drop HSFILE interface; not very useful at the moment. Therefore we
could drop streamfile and other over-complex code as well.
Doc.
Generate strong checksums as well as weak; update the test case to reflect this.
Drop leading underscores on function names; they're not proving very useful.
rdiff/rsum are currently broken, but I wanted to commit the new
library interface anyhow.
Started changing towards libpopt.
-rw-r--r-- | Makefile.am | 28 | ||||
-rw-r--r-- | TODO | 3 | ||||
-rw-r--r-- | acconfig.h | 2 | ||||
-rwxr-xr-x | autogen.sh | 6 | ||||
-rw-r--r-- | base64.c | 2 | ||||
-rw-r--r-- | buf.c | 176 | ||||
-rw-r--r-- | buf.h | 31 | ||||
-rw-r--r-- | checksum.c | 11 | ||||
-rw-r--r-- | checksum.h | 4 | ||||
-rw-r--r-- | codeheader.c | 2 | ||||
-rw-r--r-- | command.c | 8 | ||||
-rw-r--r-- | command.h | 2 | ||||
-rw-r--r-- | config.h | 15 | ||||
-rw-r--r-- | configure.in | 20 | ||||
-rw-r--r-- | copyq.c | 12 | ||||
-rw-r--r-- | delta.c | 85 | ||||
-rw-r--r-- | emit.c | 16 | ||||
-rw-r--r-- | emit.h | 4 | ||||
-rw-r--r-- | file.c | 258 | ||||
-rw-r--r-- | file.h | 1 | ||||
-rw-r--r-- | fileutil.c | 14 | ||||
-rw-r--r-- | fileutil.h | 6 | ||||
-rw-r--r-- | hex.c | 4 | ||||
-rw-r--r-- | hsync.h | 71 | ||||
-rw-r--r-- | hsyncfile.h | 6 | ||||
-rw-r--r-- | job.c | 95 | ||||
-rw-r--r-- | job.h | 49 | ||||
-rw-r--r-- | mdfour.c | 24 | ||||
-rwxr-xr-x | mkprototab.sh | 2 | ||||
-rw-r--r-- | mksum.c | 117 | ||||
-rw-r--r-- | mksum.h | 2 | ||||
-rw-r--r-- | mksum.input/COPYING.sig | bin | 56 -> 160 bytes | |||
-rw-r--r-- | netint.c | 42 | ||||
-rw-r--r-- | netint.h | 18 | ||||
-rw-r--r-- | patch.c | 162 | ||||
-rw-r--r-- | prototab.h | 2 | ||||
-rw-r--r-- | rdiff.c | 184 | ||||
-rw-r--r-- | readsums.c | 126 | ||||
-rw-r--r-- | rollsum.c | 10 | ||||
-rw-r--r-- | rollsum.h | 6 | ||||
-rw-r--r-- | rsum.c | 138 | ||||
-rw-r--r-- | scoop.c | 48 | ||||
-rw-r--r-- | search.c | 14 | ||||
-rw-r--r-- | search.h | 2 | ||||
-rw-r--r-- | snprintf.c | 2 | ||||
-rw-r--r-- | stats.c | 2 | ||||
-rw-r--r-- | stream.c | 45 | ||||
-rw-r--r-- | stream.h | 34 | ||||
-rw-r--r-- | streamfile.c | 113 | ||||
-rw-r--r-- | sumset.c | 142 | ||||
-rw-r--r-- | sumset.h | 28 | ||||
-rw-r--r-- | trace.c | 42 | ||||
-rw-r--r-- | trace.h | 34 | ||||
-rw-r--r-- | tube.c | 28 | ||||
-rw-r--r-- | util.c | 16 | ||||
-rw-r--r-- | util.h | 12 | ||||
-rw-r--r-- | version.c | 43 | ||||
-rw-r--r-- | whole.c | 187 | ||||
-rw-r--r-- | whole.h (renamed from streamfile.h) | 7 |
59 files changed, 1323 insertions, 1240 deletions
diff --git a/Makefile.am b/Makefile.am index ec8c571..e83ac22 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to produce Makefile.in -# Copyright (C) 2000 by Martin Pool <mbp@linuxcare.com.au> +# Copyright (C) 2000, 2001 by Martin Pool <mbp@linuxcare.com.au> # $Id$ # This program is free software; you can redistribute it and/or @@ -28,31 +28,31 @@ lib_LTLIBRARIES = libhsync.la libhsync_la_SOURCES = \ base64.c \ + buf.c buf.h \ checksum.c checksum.h \ command.c command.h \ - delta.c delta.h \ + delta.c \ emit.c emit.h \ - file.c \ fileutil.c fileutil.h \ hex.c \ hsync.h \ hsyncfile.h \ + job.c job.h \ mdfour.c \ mksum.c \ msg.c \ netint.c netint.h \ patch.c \ - private.h \ protocol.h \ prototab.c prototab.h \ scoop.c \ stream.c stream.h \ - streamfile.c streamfile.h \ + sumset.c \ trace.c trace.h \ - tube.c tube.h \ + tube.c \ util.c util.h \ version.c \ - whole.c + whole.c whole.h # TODO: If we ever care enough, build a second library containing only # the code necessary to be a client, and not stuff for encoding. At @@ -68,7 +68,8 @@ libhsync_la_SOURCES = \ # TODO: driver.sh requires bash. Therefore we should either test for # it and use it rather than $SHELL, or we should rewrite it to work in -# plain Bourne shell. +# plain Bourne shell. Or perhaps we should use bash enforcing POSIX +# compliance, so that we can detect and avoid such dependencies. TESTS_ENVIRONMENT = bash $(srcdir)/driver.sh @@ -93,7 +94,7 @@ noinst_SCRIPTS = \ test_data= -# TODO: Delete the test-*.d directories when cleaning up. Yeah! +# TODO: Delete the test-*.d directories when cleaning up. CLEANFILES = tmp-test-*.d/* tmp-try-*.d/* # Autogenerated by a script @@ -113,10 +114,13 @@ LDADD = libhsync.la $(LIBOBJS) # end users wanting to run them. So for the time being they are not # installed. -bin_PROGRAMS = rdiff +# bin_PROGRAMS = rsum +# rdiff -rdiff_SOURCES = rdiff.c \ - isprefix.c isprefix.h +# rsum_SOURCES = rsum.c + +# rdiff_SOURCES = rdiff.c \ +# isprefix.c isprefix.h check_PROGRAMS = isprefix.driver @@ -177,7 +177,8 @@ $Id$ sufficient. * SCO and similar things on 32-bit platforms may be more - difficult. + difficult. Some SCO systems have no 64-bit types at all, so + there we will have to do without. * On larger Unix platforms we hope that large file support will be the default. @@ -20,7 +20,7 @@ #undef _LARGEFILE_SOURCE #undef _LARGEFILE64_SOURCE -/* How many bits in an off_t? */ +/* How many bits would you like to have in an off_t? */ #undef _FILE_OFFSET_BITS /* Define to include GNU C library extensions. */ @@ -34,6 +34,12 @@ FILE=hsync.h DIE=0 +cache="$srcdir/config.cache" +[ -f "$cache" ] && { + echo "Deleting $cache" + rm "$cache" +} + (autoconf --version) < /dev/null > /dev/null 2>&1 || { echo echo "You must have autoconf installed to compile $PROJECT." @@ -20,7 +20,7 @@ */ -#include "config.h" +#include <config.h> #include <string.h> #include <stdio.h> @@ -0,0 +1,176 @@ +/*= -*- c-file-style: "linux" -*- + * + * libhsync -- the library for network deltas + * $Id$ + * + * Copyright (C) 2000, 2001 by Martin Pool <mbp@linuxcare.com.au> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + /* + * Pick a window, Jimmy, you're leaving. + * -- Martin Schwenke, regularly + */ + + + +#include <config.h> + +#include <assert.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> + +#include "hsync.h" +#include "hsyncfile.h" +#include "trace.h" +#include "buf.h" +#include "util.h" + + +int hs_inbuflen = 1000, hs_outbuflen = 1000; + + +struct hs_filebuf { + FILE *f; + hs_stream_t *stream; + char *buf; + size_t buf_len; +}; + + + +hs_filebuf_t *hs_filebuf_new(FILE *f, hs_stream_t *stream, size_t buf_len) +{ + hs_filebuf_t *pf = hs_alloc_struct(hs_filebuf_t); + + pf->buf = hs_alloc(buf_len, "file buffer"); + pf->buf_len = buf_len; + pf->f = f; + pf->stream = stream; + + return pf; +} + + +void hs_filebuf_free(hs_filebuf_t *fb) +{ + hs_bzero(fb, sizeof *fb); + free(fb); +} + + +/* + * If the stream has no more data available, read some from F into BUF, + * and let the stream use that. + */ +hs_result hs_infilebuf_fill(hs_filebuf_t *fb) +{ + hs_stream_t * const stream = fb->stream; + FILE *f = fb->f; + + /* This is only allowed if either the stream has no input buffer + * yet, or that buffer could possibly be BUF. */ + if (stream->next_in != NULL) { + assert(stream->avail_in <= fb->buf_len); + assert(stream->next_in >= fb->buf); + assert(stream->next_in <= fb->buf + fb->buf_len); + } else { + assert(stream->avail_in == 0); + } + + if (stream->avail_in == 0 && !feof(fb->f)) { + int len = fread(fb->buf, 1, fb->buf_len, f); + if (len < 0) { + hs_error("error filling stream from file: %s", + strerror(errno)); + return HS_IO_ERROR; + } + stream->avail_in = len; + stream->next_in = fb->buf; + } + + return HS_OK; +} + + +/* + * The stream is already using BUF for an output buffer, and probably + * contains some buffered output now. Write this out to F, and reset + * the buffer cursor. + */ +hs_result hs_outfilebuf_drain(hs_filebuf_t *fb) +{ + int present; + hs_stream_t * const stream = fb->stream; + FILE *f = fb->f; + + /* This is only allowed if either the stream has no output buffer + * yet, or that buffer could possibly be BUF. */ + if (stream->next_out == NULL) { + assert(stream->avail_out == 0); + + stream->next_out = fb->buf; + stream->avail_out = fb->buf_len; + + return HS_OK; + } + + assert(stream->avail_out <= fb->buf_len); + assert(stream->next_out >= fb->buf); + assert(stream->next_out <= fb->buf + fb->buf_len); + + present = stream->next_out - fb->buf; + if (present > 0) { + int result; + + assert(present > 0); + + result = fwrite(fb->buf, 1, present, f); + if (present != result) { + hs_error("error draining stream to file: %s", + strerror(errno)); + return HS_IO_ERROR; + } + + stream->next_out = fb->buf; + stream->avail_out = fb->buf_len; + } + + return HS_OK; +} + + +/* + * Default copy implementation that retrieves a part of a stdio file. + */ +hs_result hs_file_copy_cb(void *arg, size_t *len, void **buf) +{ + int got; + + got = fread(*buf, 1, *len, (FILE *) arg); + if (got == -1) { + hs_error(strerror(errno)); + return HS_IO_ERROR; + } else if (got == 0) { + hs_error("unexpected eof"); + return HS_SHORT_STREAM; + } else { + *len = got; + return HS_OK; + } +} @@ -0,0 +1,31 @@ +/*= -*- c-file-style: "linux" -*- + * + * libhsync -- the library for network deltas + * $Id$ + * + * Copyright (C) 2000, 2001 by Martin Pool <mbp@linuxcare.com.au> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +typedef struct hs_filebuf hs_filebuf_t; + +hs_filebuf_t *hs_filebuf_new(FILE *f, hs_stream_t *stream, size_t buf_len); + +void hs_filebuf_free(hs_filebuf_t *fb); + +hs_result hs_infilebuf_fill(hs_filebuf_t *fb); + +hs_result hs_outfilebuf_drain(hs_filebuf_t *); @@ -2,7 +2,7 @@ * * $Id$ * - * Copyright (C) 1999, 2000 by Martin Pool <mbp@linuxcare.com.au> + * Copyright (C) 1999, 2000, 2001 by Martin Pool <mbp@linuxcare.com.au> * Copyright (C) 1996 by Andrew Tridgell * Copyright (C) 1996 by Paul Mackerras * @@ -21,7 +21,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" +#include <config.h> #include <assert.h> #include <stdlib.h> @@ -45,7 +45,7 @@ int checksum_seed = 0; * A simple 32 bit checksum that can be updated from either end * (inspired by Mark Adler's Adler-32 checksum) */ -uint32_t _hs_calc_weak_sum(void const *p, int len) +uint32_t hs_calc_weak_sum(void const *p, int len) { int i; uint32_t s1, s2; @@ -79,7 +79,7 @@ uint32_t _hs_calc_weak_sum(void const *p, int len) * Since we can't retry a web transaction I'm not sure if it's very * useful in rproxy. */ -void _hs_calc_strong_sum(void const *buf, +void hs_calc_strong_sum(void const *buf, size_t len, uint8_t *sum, size_t sum_len) @@ -93,3 +93,6 @@ void _hs_calc_strong_sum(void const *buf, memcpy(sum, tsum, sum_len); } + + + @@ -19,7 +19,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -uint32_t _hs_calc_weak_sum(void const *buf1, int len); +uint32_t hs_calc_weak_sum(void const *buf1, int len); -void _hs_calc_strong_sum(void const *buf, size_t buf_len, +void hs_calc_strong_sum(void const *buf, size_t buf_len, uint8_t *sum, size_t sum_len); diff --git a/codeheader.c b/codeheader.c index dab3ce6..ce05487 100644 --- a/codeheader.c +++ b/codeheader.c @@ -3,7 +3,7 @@ * libhsync -- the library for network deltas * $Id$ * - * Copyright (C) 2000 by Martin Pool <mbp@linuxcare.com.au> + * Copyright (C) 2001 by Martin Pool <mbp@linuxcare.com.au> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -21,7 +21,7 @@ */ -#include "config.h" +#include <config.h> #include <assert.h> #include <stdlib.h> @@ -31,7 +31,7 @@ #include "command.h" /* For debugging purposes, here are some human-readable forms. */ -struct hs_op_kind_name const _hs_op_kind_names[] = { +struct hs_op_kind_name const hs_op_kind_names[] = { {"EOF", HS_KIND_EOF }, {"COPY", HS_KIND_COPY }, {"LITERAL", HS_KIND_LITERAL }, @@ -45,11 +45,11 @@ struct hs_op_kind_name const _hs_op_kind_names[] = { /* * Return a human-readable name for KIND. */ -char const * _hs_op_kind_name(enum hs_op_kind kind) +char const * hs_op_kind_name(enum hs_op_kind kind) { const struct hs_op_kind_name *k; - for (k = _hs_op_kind_names; k->kind; k++) { + for (k = hs_op_kind_names; k->kind; k++) { if (k->kind == kind) { return k->name; } @@ -53,6 +53,6 @@ typedef struct hs_op_kind_name { enum hs_op_kind const kind; } hs_op_kind_name_t; -char const * _hs_op_kind_name(enum hs_op_kind); +char const * hs_op_kind_name(enum hs_op_kind); @@ -1,9 +1,18 @@ /* config.h. Generated automatically by configure. */ /* config.h.in. Generated automatically from configure.in by autoheader. */ +/* Define to empty if the keyword does not work. */ +/* #undef const */ + +/* Define to `long' if <sys/types.h> doesn't define. */ +/* #undef off_t */ + /* Define if you need to in order for stat and other things to work. */ /* #undef _POSIX_SOURCE */ +/* Define to `unsigned' if <sys/types.h> doesn't define. */ +/* #undef size_t */ + /* Define if you have the ANSI C header files. */ #define STDC_HEADERS 1 @@ -16,6 +25,9 @@ /* Define this if your sockaddr structure contains sin_len */ /* #undef HAVE_SOCK_SIN_LEN */ +/* How many bits would you like to have in an off_t? */ +#define _FILE_OFFSET_BITS 64 + /* Define to include GNU C library extensions. */ #define _GNU_SOURCE 1 @@ -25,9 +37,6 @@ /* Canonical GNU hostname */ #define HS_CANONICAL_HOST "i686-pc-linux-gnu" -/* The number of bytes in a off_t. */ -#define SIZEOF_OFF_T 4 - /* The number of bytes in a unsigned char. */ #define SIZEOF_UNSIGNED_CHAR 1 diff --git a/configure.in b/configure.in index f88c0be..3fda1a3 100644 --- a/configure.in +++ b/configure.in @@ -1,8 +1,11 @@ -# -*- shell-script -*- dnl Process this file with autoconf to produce a configure script. - AC_REVISION($Id$) +# -*- shell-script -*- + +# Copyright (C) 1999, 2000, 2001 by Martin Pool <mbp@linuxcare.com.au> + AC_INIT(trace.c) + my_version=0.6.0dev my_package=libhsync my_url=http://linuxcare.com.au/rproxy/ @@ -14,10 +17,8 @@ AM_PROG_LIBTOOL AM_CONFIG_HEADER(config.h) -dnl Set up to get as many features as we can manage -dnl trying to do large file support is not so simple -dnl we will turn it off for the moment -dnl AC_DEFINE(_FILE_OFFSET_BITS, 64) +# Set up to get as many features as we can manage +AC_DEFINE(_FILE_OFFSET_BITS, 64) AC_DEFINE(_GNU_SOURCE) AC_CANONICAL_HOST @@ -29,6 +30,11 @@ AC_PROG_CPP AC_PROG_INSTALL AC_PROG_RANLIB +AC_TYPE_SIZE_T +AC_TYPE_OFF_T + +AC_C_CONST + # See if the compiler has the nice GNU feature of # putting argv[0] into a global AC_MSG_CHECKING([for program_invocation_short_name]) @@ -94,8 +100,6 @@ then AC_MSG_WARN(unsigned char seems to be $ac_cv_sizeof_unsigned_char bytes. Expect trouble.) fi -AC_CHECK_SIZEOF(off_t, 4) - dnl Checks for header files. AC_CHECK_HEADERS(sys/endian.h) AC_HEADER_STDC @@ -27,8 +27,8 @@ /* If possible, append this copy command to the end of the previous * one. If not, flush the existing command and begin a new one. */ int -_hs_queue_copy(hs_write_fn_t write_fn, void *write_priv, - _hs_copyq_t * copyq, +hs_queue_copy(hs_write_fn_t write_fn, void *write_priv, + hs_copyq_t * copyq, off_t start, size_t len, hs_stats_t * stats) { int ret; @@ -45,7 +45,7 @@ _hs_queue_copy(hs_write_fn_t write_fn, void *write_priv, } else { /* Of course, COPY commands don't *have* to follow each other. If we get two non-contiguous ones, then we flush and start again. */ - ret = _hs_copyq_push(write_fn, write_priv, copyq, stats); + ret = hs_copyq_push(write_fn, write_priv, copyq, stats); copyq->start = start; copyq->len = len; return ret; @@ -58,8 +58,8 @@ _hs_queue_copy(hs_write_fn_t write_fn, void *write_priv, * them out. */ int -_hs_copyq_push(hs_write_fn_t write_fn, void *write_priv, - _hs_copyq_t * copyq, hs_stats_t * stats) +hs_copyq_push(hs_write_fn_t write_fn, void *write_priv, + hs_copyq_t * copyq, hs_stats_t * stats) { int ret; @@ -67,7 +67,7 @@ _hs_copyq_push(hs_write_fn_t write_fn, void *write_priv, return 0; assert(copyq->len > 0); - ret = _hs_emit_copy(write_fn, write_priv, + ret = hs_emit_copy(write_fn, write_priv, copyq->start, copyq->len, stats); copyq->len = 0; @@ -3,7 +3,7 @@ * libhsync -- library for network deltas * $Id$ * - * Copyright (C) 2000 by Martin Pool <mbp@linuxcare.com.au> + * Copyright (C) 2000, 2001 by Martin Pool <mbp@linuxcare.com.au> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -34,26 +34,17 @@ /* * Eventually, the delta algorithm has to maintain one block of - * readahead or readbehind to check the strong checksum. Normally we - * don't have to actually do anything with this data, just keep it. - * - * Probably a reasonable way to implement this is with a double-long - * buffer and data scrolling through that. When a weak match is found, - * we check the strong checksum against the readbehind buffer. + * readahead or readbehind to check the strong checksum. * * On each entry to the iterator, we first need to try to flush any * outstanding output from either the tube or a copy instruction. */ -#include "config.h" +#include <config.h> #include <assert.h> -#ifdef HAVE_STDINT_H -#include <stdint.h> -#endif - #include <sys/types.h> #include <limits.h> #include <inttypes.h> @@ -64,68 +55,46 @@ #include "emit.h" #include "stream.h" #include "util.h" +#include "job.h" -enum hs_delta_state { - hs_s_header, - hs_body -}; - -struct hs_delta_job { - hs_stream_t *stream; -}; - - -/* - * Prepare to compute a delta on a stream. - */ -hs_delta_job_t *hs_delta_begin(hs_stream_t *stream) +static hs_result hs_delta_s_fake(hs_job_t *job) { - hs_delta_job_t *job; + hs_stream_t * const stream = job->stream; + size_t avail = stream->avail_in; + + hs_emit_literal_cmd(stream, avail); + hs_blow_copy(stream, avail); - job = _hs_alloc_struct(hs_delta_job_t); - job->stream = stream; - - _hs_emit_delta_header(stream); - - return job; + if (hs_stream_is_empty(stream)) + return HS_OK; + else + return HS_BLOCKED; } -/* - * Consume and produce data to generate a delta. - */ -int hs_delta_iter(hs_delta_job_t *job, int ending) +static hs_result hs_delta_s_header(hs_job_t *job) { - int avail; - hs_stream_t * const stream = job->stream; - - /* Find out how much input is available. Write it out as one big - * command, and remove it from the input stream. */ - if (!_hs_tube_catchup(stream)) - return HS_OK; + hs_emit_delta_header(job->stream); - avail = stream->avail_in; - _hs_emit_literal_cmd(stream, avail); - _hs_blow_copy(stream, avail); + job->statefn = hs_delta_s_fake; - if (_hs_stream_is_empty(stream)) - return HS_OK; - else - return HS_BLOCKED; + return HS_OK; } - /* - * Close of processing of a delta. This doesn't terminate the stream, - * it just frees up any memory that was allocated. + * Prepare to compute a delta on a stream. */ -int hs_delta_finish(hs_delta_job_t *job) +hs_job_t *hs_delta_begin(hs_stream_t *stream) { - _hs_bzero(job, sizeof *job); + hs_job_t *job; - free(job); + job = hs_job_new(stream); - return HS_OK; + job->statefn = hs_delta_s_header; + + return job; } + + @@ -28,7 +28,7 @@ */ -#include "config.h" +#include <config.h> #include <assert.h> @@ -55,19 +55,19 @@ * Write the magic for the start of a delta. */ void -_hs_emit_delta_header(hs_stream_t *stream) +hs_emit_delta_header(hs_stream_t *stream) { - _hs_trace("emit DELTA"); - _hs_squirt_n32(stream, HS_DELTA_MAGIC); + hs_trace("emit DELTA"); + hs_squirt_n32(stream, HS_DELTA_MAGIC); } /* Write a LITERAL command. */ void -_hs_emit_literal_cmd(hs_stream_t *stream, int len) +hs_emit_literal_cmd(hs_stream_t *stream, int len) { - _hs_trace("emit LITERAL(%d)", len); - _hs_squirt_n8(stream, HS_OP_LITERAL_N32); - _hs_squirt_n32(stream, len); + hs_trace("emit LITERAL(%d)", len); + hs_squirt_n8(stream, HS_OP_LITERAL_N32); + hs_squirt_n32(stream, len); } @@ -26,5 +26,5 @@ */ -void _hs_emit_delta_header(hs_stream_t *stream); -void _hs_emit_literal_cmd(hs_stream_t *stream, int len); +void hs_emit_delta_header(hs_stream_t *stream); +void hs_emit_literal_cmd(hs_stream_t *stream, int len); @@ -1,258 +0,0 @@ -/*= -*- c-file-style: "linux" -*- - * - * libhsync -- dynamic caching and delta update in HTTP - * $Id$ - * - * Copyright (C) 2000 by Martin Pool <mbp@linuxcare.com.au> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * file.c -- This looks after the high-level, stdio-flavoured - * interface. - */ - - - /* - * "You know, it'd be much cheaper if - * you flew on the 25th of December." - */ - - -#include "config.h" - -#include <assert.h> -#include <stdlib.h> -#include <stdio.h> -#include <stdint.h> -#include <limits.h> -#include <errno.h> -#include <string.h> - -#include "hsync.h" -#include "util.h" -#include "stream.h" -#include "trace.h" -#include "streamfile.h" -#include "sumset.h" -#include "hsyncfile.h" - - -int hs_inbuflen = 500, hs_outbuflen = 600; - -static const int HS_PATCH_FILE_TAG = 201214, - HS_MKSUM_FILE_TAG = 201215; - -typedef struct hs_file { - int tag; - FILE *basis_file, *in_file, *out_file; - - char *buf; - size_t buf_len; - - hs_stream_t *stream; - - /* one of the following: */ - hs_patch_job_t *patch_job; - hs_mksum_job_t *mksum_job; -} hs_file_t; - - -/* - * Extract from a void pointer, and check the dogtag. - */ -static hs_file_t *_hs_file_check(void *p, int tag) { - hs_file_t *pf = (hs_file_t *) p; - assert(pf->tag == tag); - return pf; -} - - -static hs_file_t *_hs_file_new(size_t buf_len) { - hs_file_t *pf = _hs_alloc_struct(hs_file_t); - pf->stream = _hs_alloc_struct(hs_stream_t); - hs_stream_init(pf->stream); - - pf->buf = _hs_alloc(buf_len, "file buffer"); - pf->buf_len = buf_len; - - return pf; -} - - -/* - * Open a new hsync file which will apply a patch. As you read from - * the file using hs_read(), you'll receive parts of the new file. - */ -HSFILE *hs_patch_open(FILE *basis_file, FILE *delta_file) -{ - hs_file_t *pf; - - pf = _hs_file_new(hs_inbuflen); - - pf->tag = HS_PATCH_FILE_TAG; - pf->basis_file = basis_file; - pf->in_file = delta_file; - - pf->patch_job = hs_patch_begin(pf->stream, hs_file_copy_cb, basis_file); - - return pf; -} - - - -/* - * Open a file to write out the signature of caller-supplied data. - */ -HSFILE *hs_mksum_open(FILE *sig_file, int block_len, int strong_sum_len) -{ - hs_file_t *pf = _hs_file_new(hs_outbuflen); - - pf->tag = HS_MKSUM_FILE_TAG; - pf->out_file = sig_file; - pf->mksum_job = hs_mksum_begin(pf->stream, block_len, strong_sum_len); - - return pf; -} - - - -/* - * Read up to *LEN bytes from PF. At end of file, return HS_OK; if - * the patch is not yet complete returns HS_BLOCKED; if an error - * occurred returns an appropriate code. Adjusts LEN to show how much - * was actually read. - */ -enum hs_result hs_patch_read(HSFILE *f, void *buf, size_t *len) -{ - hs_file_t *pf = _hs_file_check(f, HS_PATCH_FILE_TAG); - enum hs_result result; - - pf->stream->next_out = buf; - pf->stream->avail_out = *len; - - do { - _hs_fill_from_file(pf->stream, pf->buf, pf->buf_len, - pf->in_file); - - result = hs_patch_iter(pf->patch_job); - - if (result == HS_BLOCKED && feof(pf->in_file) && - !pf->stream->avail_in) { - /* The library wants more input, but it has - * none in its internal buffer and we're at - * the end of the file. Therefore the delta - * must have been truncated. */ - result = HS_SHORT_STREAM; - } - } while (result == HS_BLOCKED); - - /* Return the amount of output actually available. */ - assert(pf->stream->next_out >= (char *) buf); - *len = pf->stream->next_out - (char *) buf; - _hs_trace("returns %d bytes: %s", *len, hs_strerror(result)); - - return result; -} - - - -enum hs_result hs_mksum_write(HSFILE *f, void *buf, size_t len) -{ - hs_file_t *pf = _hs_file_check(f, HS_MKSUM_FILE_TAG); - enum hs_result result, io_result; - - pf->stream->next_in = buf; - pf->stream->avail_in = len; - - do { - result = hs_mksum_iter(pf->mksum_job, 0); - - io_result = _hs_drain_to_file(pf->stream, pf->buf, pf->buf_len, - pf->out_file); - - if (io_result != HS_OK) - return result; - } while (result == HS_BLOCKED && pf->stream->avail_in > 0); - - _hs_trace("returns %s(%d)", hs_strerror(result), result); - - return result; -} - - -/* - * Close off a patch file. If the patch has not finished, then the - * rest of the data is just lost. The files used are not closed. - */ -enum hs_result hs_patch_close(HSFILE *f) -{ - hs_file_t *pf = _hs_file_check(f, HS_PATCH_FILE_TAG); - if (pf->buf) - free(pf->buf); - hs_patch_finish(pf->patch_job); - return HS_OK; -} - - - -enum hs_result hs_mksum_close(HSFILE *f) -{ - hs_file_t *pf = _hs_file_check(f, HS_MKSUM_FILE_TAG); - enum hs_result result, io_result; - - pf->stream->next_in = 0; - pf->stream->avail_in = 0; - - /* Continue to run until all stream data has drained; then - * deallocate and leave. */ - do { - result = hs_mksum_iter(pf->mksum_job, 1); - - io_result = _hs_drain_to_file(pf->stream, pf->buf, pf->buf_len, - pf->out_file); - - if (io_result != HS_OK) - return result; - } while (result == HS_BLOCKED); - - if (pf->buf) - free(pf->buf); - hs_mksum_finish(pf->mksum_job); - return HS_OK; -} - - - -/* - * Default copy implementation that retrieves a part of a stdio file. - */ -enum hs_result hs_file_copy_cb(void *arg, size_t *len, void **buf) -{ - int got; - - got = fread(*buf, 1, *len, (FILE *) arg); - if (got == -1) { - _hs_error(strerror(errno)); - return HS_IO_ERROR; - } else if (got == 0) { - _hs_error("unexpected eof"); - return HS_SHORT_STREAM; - } else { - *len = got; - return HS_OK; - } -} @@ -1 +0,0 @@ -#error unused @@ -21,7 +21,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" +#include <config.h> #ifdef HAVE_STDINT_H # include <stdint.h> @@ -42,13 +42,13 @@ void -_hs_file_close(int fd) +hs_file_close(int fd) { if (fd == -1) - _hs_error("warning: close called with fd of -1"); + hs_error("warning: close called with fd of -1"); if (close(fd) == -1) { - _hs_error("error closing fd %d: %s", + hs_error("error closing fd %d: %s", fd, strerror(errno)); } } @@ -58,7 +58,7 @@ _hs_file_close(int fd) * Open a file, with special handling for `-' on input and output. */ FILE * -_hs_file_open(char const *filename, int mode) +hs_file_open(char const *filename, int mode) { int fd; FILE *f; @@ -80,7 +80,7 @@ _hs_file_open(char const *filename, int mode) fd = open(filename, mode, 0666); if (fd == -1) { - _hs_error("Error opening \"%s\" for %s: %s", filename, + hs_error("Error opening \"%s\" for %s: %s", filename, (mode & O_WRONLY) ? "write" : "read", strerror(errno)); exit(1); @@ -88,7 +88,7 @@ _hs_file_open(char const *filename, int mode) f = fdopen(fd, is_write ? "w" : "r"); if (!f) { - _hs_error("Error opening stream on fd%d: %s", fd, + hs_error("Error opening stream on fd%d: %s", fd, strerror(errno)); exit(1); } @@ -20,7 +20,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -int _hs_file_copy_all(int from_fd, int to_fd); +int hs_file_copy_all(int from_fd, int to_fd); -FILE * _hs_file_open(char const *filename, int mode); -void _hs_file_close(int fd); +FILE * hs_file_open(char const *filename, int mode); +void hs_file_close(int fd); @@ -2,7 +2,7 @@ * rproxy -- dynamic caching and delta update in HTTP * $Id$ * - * Copyright (C) 2000 by Martin Pool <mbp@linuxcare.com.au> + * Copyright (C) 2000, 2001 by Martin Pool <mbp@linuxcare.com.au> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -19,7 +19,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" +#include <config.h> #include <assert.h> @@ -3,7 +3,7 @@ * libhsync -- library for network deltas * $Id$ * - * Copyright (C) 2000 by Martin Pool <mbp@linuxcare.com.au> + * Copyright (C) 2000, 2001 by Martin Pool <mbp@linuxcare.com.au> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -20,28 +20,20 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -/* - * hsync.h: public interface to libhsync. - */ - -extern char const *const hs_libhsync_version; -extern int const hs_libhsync_file_offset_bits; + /* + * You should never wear your best + * trousers when you go out to fight for + * freedom and liberty. + * -- Henrik Ibsen + */ -void hs_show_version(FILE *out, char const *program); -void hs_show_licence(FILE *out); - /* - * For the moment, we always work in the C library's off_t. - * - * Supporting large files on 32-bit Linux is *NOT* just a matter of - * setting these: people will typically need a different libc and - * possibly an LFS-supported kernel too. :-( - * - * Anyhow, will anyone really have single HTTP requests >=2GB? + * hsync.h: public interface to libhsync. */ +extern char const hs_libhsync_version[]; +extern char const hs_licence_string[]; /*********************************************************************** @@ -79,15 +71,15 @@ void hs_base64(unsigned char const *buf, int n, char *out); /* Return codes */ -enum hs_result { +typedef enum hs_result { HS_OK = 0, /* completed successfully */ HS_BLOCKED = 1, /* OK, but more remains to be done */ - HS_RUN_OK = 2, /* not finished or blocked */ + HS_RUN_OK = 2, /* not yet finished or blocked */ HS_IO_ERROR = (-1), /* error in file or network IO */ HS_MEM_ERROR = (-2), /* out of memory */ HS_SHORT_STREAM = (-3), /* unexpected eof */ HS_BAD_MAGIC = (-4) /* illegal value on stream */ -}; +} hs_result; /*********************************************************************** @@ -127,7 +119,15 @@ void hs_mdfour_result(hs_mdfour_t * md, unsigned char *out); char *hs_format_stats(hs_stats_t const *, char *, size_t); int hs_log_stats(hs_stats_t const *stats); -char const *hs_strerror(enum hs_result r); +char const *hs_strerror(hs_result r); + + + +typedef struct hs_sumset hs_sumset_t; + +void hs_free_sumset(hs_sumset_t *); +void hs_sumset_dump(hs_sumset_t const *); + /*********************************************************************** * All encoding routines follow a calling protocol similar to that of @@ -163,25 +163,22 @@ void hs_stream_init(hs_stream_t *); #define HS_DEFAULT_BLOCK_LEN 2048 -typedef struct hs_mksum_job hs_mksum_job_t; -hs_mksum_job_t *hs_mksum_begin(hs_stream_t *stream, - size_t new_block_len, size_t strong_sum_len); -int hs_mksum_iter(hs_mksum_job_t * job, int ending); -int hs_mksum_finish(hs_mksum_job_t * job); +typedef struct hs_job hs_job_t; -typedef struct hs_delta_job hs_delta_job_t; -hs_delta_job_t *hs_delta_begin(hs_stream_t *stream); -int hs_delta_iter(hs_delta_job_t *, int ending); -int hs_delta_finish(hs_delta_job_t *); +hs_job_t *hs_accum_begin(hs_stream_t *); +hs_result hs_job_iter(hs_job_t *, int ending); +hs_result hs_job_free(hs_job_t *); -/* Callback used to retrieve parts of the basis file. */ -typedef enum hs_result (hs_copy_cb)(void *opaque, size_t *len, void **result); +int hs_accum_value(hs_job_t *, char *sum, size_t sum_len); + +hs_job_t *hs_mksum_begin(hs_stream_t *stream, + size_t new_block_len, size_t strong_sum_len); -typedef struct hs_patch_job hs_patch_job_t; -hs_patch_job_t *hs_patch_begin(hs_stream_t *stream, hs_copy_cb *, void *copy_arg); -int hs_patch_iter(hs_patch_job_t *); -int hs_patch_finish(hs_patch_job_t *); +hs_job_t *hs_delta_begin(hs_stream_t *stream); +/* Callback used to retrieve parts of the basis file. */ +typedef hs_result (hs_copy_cb)(void *opaque, size_t *len, void **result); +hs_job_t *hs_patch_begin(hs_stream_t *, hs_copy_cb *, void *copy_arg); diff --git a/hsyncfile.h b/hsyncfile.h index 0e03c05..acff985 100644 --- a/hsyncfile.h +++ b/hsyncfile.h @@ -3,7 +3,7 @@ * libhsync -- the library for network deltas * $Id$ * - * Copyright (C) 2000 by Martin Pool <mbp@linuxcare.com.au> + * Copyright (C) 2000, 2001 by Martin Pool <mbp@linuxcare.com.au> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -76,4 +76,6 @@ void hs_mdfour_file(FILE *in_file, char *result); enum hs_result hs_rdiff_signature(int argc, char *argv[]); enum hs_result hs_rdiff_delta(int argc, char *argv[]); enum hs_result hs_rdiff_patch(int argc, char *argv[]); -enum hs_result hs_rdiff_md4(int argc, char *argv[]); +enum hs_result hs_rdiff_sum(int argc, char *argv[]); + +hs_result hs_whole_signature(FILE *old_file, FILE *sig_file, size_t, size_t); @@ -0,0 +1,95 @@ +/*= -*- c-file-style: "linux" -*- + * + * libhsync -- the library for network deltas + * $Id$ + * + * Copyright (C) 2000, 2001 by Martin Pool <mbp@linuxcare.com.au> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + + /* + * The hard, lifeless I covered up the + * warm, pulsing It; protecting and + * sheltering. + */ + + +/* + * Generic state-machine "job" mechanism. + */ + + +#include <config.h> + +#include <stdlib.h> +#include <assert.h> + +#include "hsync.h" +#include "stream.h" +#include "util.h" +#include "job.h" +#include "trace.h" + + +hs_job_t * hs_job_new(hs_stream_t *stream) +{ + hs_job_t *job; + + job = hs_alloc_struct(hs_job_t); + + hs_stream_check(stream); + job->stream = stream; + + return job; +} + + +hs_result hs_job_free(hs_job_t *job) +{ + hs_bzero(job, sizeof *job); + free(job); + + return HS_OK; +} + + + +/* + * Nonblocking iteration interface for making up a file sum. + * + * ENDING should be true if there is no more data after what's in the + * input buffer. The final block checksum will run across whatever's + * in there, without trying to accumulate anything else. + */ +hs_result hs_job_iter(hs_job_t *job, int ending) +{ + enum hs_result result; + + if (ending) + job->near_end = 1; + + while (1) { + result = hs_tube_catchup(job->stream); + if (result != HS_OK) + return result; + + result = job->statefn(job); + if (result != HS_RUN_OK) + return result; + } +} + @@ -0,0 +1,49 @@ +/*= -*- c-file-style: "linux" -*- + * + * libhsync -- the library for network deltas + * $Id$ + * + * Copyright (C) 2000, 2001 by Martin Pool <mbp@linuxcare.com.au> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +/* Generic 'job' state machine. */ + +struct hs_job { + hs_stream_t *stream; + + /* Callback for each processing step. */ + enum hs_result (*statefn)(hs_job_t *); + + /* Generic storage fields. */ + size_t block_len; + size_t strong_sum_len; + int near_end; + + hs_copy_cb *copy_cb; + void *copy_arg; + + /* Command byte currently being processed, if any, and lengths + * of expected parameters. */ + int op, param1, param2; + struct hs_prototab_ent const *cmd; + hs_mdfour_t output_md4; +}; + + +hs_job_t * hs_job_new(hs_stream_t *stream); + @@ -1,8 +1,9 @@ /* -*- c-file-style: "linux" -*- - * libhsync -- dynamic caching and delta update in HTTP + * + * libhsync -- the library for network deltas * $Id$ * - * Copyright (C) 2000 by Martin Pool <mbp@linuxcare.com.au> + * Copyright (C) 2000, 2001 by Martin Pool <mbp@linuxcare.com.au> * Copyright (C) 1997-1999 by Andrew Tridgell * * This program is free software; you can redistribute it and/or modify @@ -21,14 +22,17 @@ */ /* NOTE: This code makes no attempt to be fast! - - It assumes that a int is at least 32 bits long - - TODO: Recode to be fast, and to use system integer types. Perhaps if we - can find an mdfour implementation already on the system (e.g. in OpenSSL) - then we should use it instead of our own? */ - -#include "config.h" + * + * It assumes that a int is at least 32 bits long + * + * TODO: Recode to be fast, and to use system integer types. Perhaps + * if we can find an mdfour implementation already on the system + * (e.g. in OpenSSL) then we should use it instead of our own? + * + * TODO: Apparently rsync 2.4 now has a fast MD4 routine. So we + * should copy that into here. */ + +#include <config.h> #include <stdlib.h> diff --git a/mkprototab.sh b/mkprototab.sh index 4d3f217..c42f7e3 100755 --- a/mkprototab.sh +++ b/mkprototab.sh @@ -67,6 +67,8 @@ emit_cmd() { emit_cmd EOF 0 0 0 +# FIXME: seq(1) may not be available on BSD systems. + for i in `seq 1 120` do emit_cmd LITERAL $i 0 0 @@ -3,7 +3,7 @@ * libhsync -- library for network deltas * $Id$ * - * Copyright (C) 1999, 2000 by Martin Pool <mbp@linuxcare.com.au> + * Copyright (C) 1999, 2000, 2001 by Martin Pool <mbp@linuxcare.com.au> * Copyright (C) 1999 by Andrew Tridgell <tridge@samba.org> * * This program is free software; you can redistribute it and/or modify @@ -24,9 +24,14 @@ /* * mksum: Generate and write out checksums using the stream interface. + * + * Generating checksums is pretty easy, since we can always just + * process whatever data is available. When a whole block has + * arrived, or we've reached the end of the file, we write the + * checksum out. */ -#include "config.h" +#include <config.h> #include <stdlib.h> #include <stdio.h> @@ -36,51 +41,49 @@ #include "hsync.h" #include "stream.h" #include "util.h" +#include "job.h" #include "protocol.h" #include "netint.h" #include "trace.h" #include "checksum.h" -const int HS_MKSUM_TAG = 123124; - -struct hs_mksum_job { - int dogtag; - hs_stream_t *stream; - enum hs_result (*statefn)(hs_mksum_job_t *); - size_t block_len; - size_t strong_sum_len; - int near_end; -}; - /* Possible state functions for signature generation. */ -static enum hs_result _hs_mksum_s_header(hs_mksum_job_t *); -static enum hs_result _hs_mksum_s_complete(hs_mksum_job_t *); -static enum hs_result _hs_mksum_s_generate(hs_mksum_job_t *); +static enum hs_result hs_mksum_s_header(hs_job_t *); +static enum hs_result hs_mksum_s_complete(hs_job_t *); +static enum hs_result hs_mksum_s_generate(hs_job_t *); /* * State of trying to send the signature header. */ -static enum hs_result _hs_mksum_s_header(hs_mksum_job_t *job) +static enum hs_result hs_mksum_s_header(hs_job_t *job) { - _hs_squirt_n32(job->stream, HS_SIG_MAGIC); - job->statefn = _hs_mksum_s_generate; + hs_squirt_n32(job->stream, HS_SIG_MAGIC); + job->statefn = hs_mksum_s_generate; return HS_RUN_OK; } static enum hs_result -_hs_mksum_do_block(hs_mksum_job_t *job, const void *block, size_t len) +hs_mksum_do_block(hs_job_t *job, const void *block, size_t len) { uint32_t weak_sum; + uint8_t strong_sum[HS_MD4_LENGTH]; + char strong_sum_hex[HS_MD4_LENGTH * 2 + 1]; - weak_sum = _hs_calc_weak_sum(block, len); - _hs_trace("got weak sum 0x%08x", weak_sum); + weak_sum = hs_calc_weak_sum(block, len); - _hs_squirt_n32(job->stream, weak_sum); + hs_calc_strong_sum(block, len, strong_sum, job->strong_sum_len); + hs_hexify(strong_sum_hex, strong_sum, job->strong_sum_len); + + hs_squirt_n32(job->stream, weak_sum); + hs_blow_literal(job->stream, strong_sum, job->strong_sum_len); + + hs_trace("sent weak sum 0x%08x and strong sum %s", weak_sum, + strong_sum_hex); return HS_RUN_OK; } @@ -89,7 +92,7 @@ _hs_mksum_do_block(hs_mksum_job_t *job, const void *block, size_t len) /* * State of reading a block and trying to generate its sum. */ -static enum hs_result _hs_mksum_s_generate(hs_mksum_job_t *job) +static enum hs_result hs_mksum_s_generate(hs_job_t *job) { enum hs_result result; int len; @@ -97,90 +100,48 @@ static enum hs_result _hs_mksum_s_generate(hs_mksum_job_t *job) /* must get a whole block, otherwise try again */ len = job->block_len; - result = _hs_scoop_read(job->stream, len, &block); + result = hs_scoop_read(job->stream, len, &block); /* unless we're near eof, in which case we'll accept * whatever's in there */ if (result == HS_BLOCKED && job->near_end) { - result = _hs_scoop_read_rest(job->stream, &len, &block); - job->statefn = _hs_mksum_s_complete; + result = hs_scoop_read_rest(job->stream, &len, &block); + job->statefn = hs_mksum_s_complete; } else if (result != HS_OK) { - _hs_trace("generate stopped: %s", hs_strerror(result)); + hs_trace("generate stopped: %s", hs_strerror(result)); return result; } - _hs_trace("got %d byte block", len); - fwrite(block, 1, len, stdout); + hs_trace("got %d byte block", len); - return _hs_mksum_do_block(job, block, len); + return hs_mksum_do_block(job, block, len); } -static enum hs_result _hs_mksum_s_complete(hs_mksum_job_t *UNUSED(job)) +static hs_result hs_mksum_s_complete(hs_job_t *UNUSED(job)) { - _hs_trace("signature generation has already finished"); + hs_trace("signature generation has already finished"); return HS_OK; } /* Set up a new encoding job. */ -hs_mksum_job_t * hs_mksum_begin(hs_stream_t *stream, +hs_job_t * hs_mksum_begin(hs_stream_t *stream, size_t new_block_len, size_t strong_sum_len) { - hs_mksum_job_t *job; + hs_job_t *job; - job = _hs_alloc_struct(hs_mksum_job_t); + job = hs_job_new(stream); - _hs_stream_check(stream); - job->stream = stream; job->block_len = new_block_len; - job->dogtag = HS_MKSUM_TAG; assert(strong_sum_len > 0 && strong_sum_len <= HS_MD4_LENGTH); job->strong_sum_len = strong_sum_len; - job->statefn = _hs_mksum_s_header; + job->statefn = hs_mksum_s_header; return job; } - -int hs_mksum_finish(hs_mksum_job_t * job) -{ - assert(job->dogtag == HS_MKSUM_TAG); - _hs_bzero(job, sizeof *job); - free(job); - - return HS_OK; -} - - - -/* - * Nonblocking iteration interface for making up a file sum. - * - * ENDING should be true if there is no more data after what's in the - * input buffer. The final block checksum will run across whatever's - * in there, without trying to accumulate anything else. - */ -int hs_mksum_iter(hs_mksum_job_t *job, int ending) -{ - enum hs_result result; - - assert(job->dogtag == HS_MKSUM_TAG); - - if (ending) - job->near_end = 1; - - while (1) { - result = _hs_tube_catchup(job->stream); - if (result != HS_OK) - return result; - - result = job->statefn(job); - if (result != HS_RUN_OK) - return result; - } -} @@ -21,6 +21,6 @@ */ -void _hs_mksum_of_block(byte_t const *p, ssize_t len, +void hs_mksum_of_block(byte_t const *p, ssize_t len, hs_write_fn_t write_fn, void *write_priv, size_t strong_sum_len); diff --git a/mksum.input/COPYING.sig b/mksum.input/COPYING.sig Binary files differindex 328b994..eecd62b 100644 --- a/mksum.input/COPYING.sig +++ b/mksum.input/COPYING.sig @@ -36,7 +36,7 @@ * is not enough input to proceed. */ -#include "config.h" +#include <config.h> #include <assert.h> @@ -64,31 +64,31 @@ #include "stream.h" -void _hs_squirt_n32(hs_stream_t *stream, int d) +void hs_squirt_n32(hs_stream_t *stream, int d) { uint32_t nd = htonl(d); - _hs_blow_literal(stream, &nd, sizeof nd); + hs_blow_literal(stream, &nd, sizeof nd); } void -_hs_squirt_n8(hs_stream_t *stream, int d) +hs_squirt_n8(hs_stream_t *stream, int d) { uint8_t nd = d; - _hs_blow_literal(stream, &nd, sizeof nd); + hs_blow_literal(stream, &nd, sizeof nd); } -enum hs_result _hs_suck_n32(hs_stream_t *stream, int *v) +enum hs_result hs_suck_n32(hs_stream_t *stream, int *v) { void *p; int result; - if ((result = _hs_scoop_read(stream, sizeof (uint32_t), &p))) + if ((result = hs_scoop_read(stream, sizeof (uint32_t), &p))) return result; *v = ntohl(* (uint32_t const *) p); @@ -97,12 +97,12 @@ enum hs_result _hs_suck_n32(hs_stream_t *stream, int *v) } -enum hs_result _hs_suck_n8(hs_stream_t *stream, int *v) +enum hs_result hs_suck_n8(hs_stream_t *stream, int *v) { void *p; int result; - if ((result = _hs_scoop_read(stream, sizeof (uint8_t), &p))) + if ((result = hs_scoop_read(stream, sizeof (uint8_t), &p))) return result; *v = * (uint8_t const *) p; @@ -112,49 +112,49 @@ enum hs_result _hs_suck_n8(hs_stream_t *stream, int *v) -enum hs_result _hs_suck_netint(hs_stream_t *stream, int len, int *v) +enum hs_result hs_suck_netint(hs_stream_t *stream, int len, int *v) { switch (len) { case 1: - return _hs_suck_n8(stream, v); + return hs_suck_n8(stream, v); case 4: - return _hs_suck_n32(stream, v); + return hs_suck_n32(stream, v); default: - _hs_fatal("kaboom! len=%d", len); + hs_fatal("kaboom! len=%d", len); } } -int _hs_fits_in_n8(size_t val) +int hs_fits_in_n8(size_t val) { return val <= UINT8_MAX; } -int _hs_fits_in_n16(size_t val) +int hs_fits_in_n16(size_t val) { return val <= UINT16_MAX; } -int _hs_fits_in_n32(size_t val) +int hs_fits_in_n32(size_t val) { return val <= UINT32_MAX; } -int _hs_int_len(off_t val) +int hs_int_len(off_t val) { - if (_hs_fits_in_n8(val)) + if (hs_fits_in_n8(val)) return 1; - else if (_hs_fits_in_n16(val)) + else if (hs_fits_in_n16(val)) return 2; - else if (_hs_fits_in_n32(val)) + else if (hs_fits_in_n32(val)) return 4; else { - _hs_fatal("can't handle integer this long yet"); + hs_fatal("can't handle integer this long yet"); } } @@ -21,14 +21,14 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -void _hs_squirt_n32(hs_stream_t *stream, int d); -void _hs_squirt_n8(hs_stream_t *stream, int d); +void hs_squirt_n32(hs_stream_t *stream, int d); +void hs_squirt_n8(hs_stream_t *stream, int d); -enum hs_result _hs_suck_n32(hs_stream_t *stream, int *v); -enum hs_result _hs_suck_n8(hs_stream_t *stream, int *v); -enum hs_result _hs_suck_netint(hs_stream_t *stream, int len, int *v); +enum hs_result hs_suck_n32(hs_stream_t *stream, int *v); +enum hs_result hs_suck_n8(hs_stream_t *stream, int *v); +enum hs_result hs_suck_netint(hs_stream_t *stream, int len, int *v); -int _hs_fits_in_n8(size_t val); -int _hs_fits_in_n16(size_t val); -int _hs_fits_in_n32(size_t val); -int _hs_int_len(off_t val); +int hs_fits_in_n8(size_t val); +int hs_fits_in_n16(size_t val); +int hs_fits_in_n32(size_t val); +int hs_int_len(off_t val); @@ -3,7 +3,7 @@ * libhsync -- the library for network deltas * $Id$ * - * Copyright (C) 2000 by Martin Pool <mbp@linuxcare.com.au> + * Copyright (C) 2000, 2001 by Martin Pool <mbp@linuxcare.com.au> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -22,10 +22,12 @@ /* - * This is Tranquility. + * This is Tranquility Base. */ +#include <config.h> + /* * TODO: As output is produced, accumulate the MD4 checksum of the * output. Then if we find a CHECKSUM command we can check it's @@ -35,8 +37,6 @@ */ -#include "config.h" - #include <assert.h> #include <stdlib.h> #include <stdio.h> @@ -49,50 +49,19 @@ #include "command.h" #include "prototab.h" #include "stream.h" +#include "job.h" -const int HS_PATCH_TAG = 201210; - - -enum hs_patch_state { - hs_s_header, - hs_s_run -}; - - -struct hs_patch_job { - int dogtag; - hs_stream_t *stream; - enum hs_result (*statefn)(hs_patch_job_t *); - - hs_copy_cb *copy_cb; - void *copy_arg; - - /* Command byte currently being processed, if any, and lengths - * of expected parameters. */ - int op, param1, param2; - hs_prototab_ent_t const *cmd; - - /* MD4 checksum of all output data to date. */ - hs_mdfour_t output_md4; -}; +const int HS_PATCH_TAG = 201210; /* Local prototypes for state functions. */ -static enum hs_result _hs_patch_s_complete(hs_patch_job_t *); -static enum hs_result _hs_patch_s_cmdbyte(hs_patch_job_t *); -static enum hs_result _hs_patch_s_params(hs_patch_job_t *); -static enum hs_result _hs_patch_s_run(hs_patch_job_t *); -static enum hs_result _hs_patch_s_literal(hs_patch_job_t *); - - - -static void _hs_patch_check(const hs_patch_job_t *job) -{ - assert(job->dogtag == HS_PATCH_TAG); -} - +static enum hs_result hs_patch_s_complete(hs_job_t *); +static enum hs_result hs_patch_s_cmdbyte(hs_job_t *); +static enum hs_result hs_patch_s_params(hs_job_t *); +static enum hs_result hs_patch_s_run(hs_job_t *); +static enum hs_result hs_patch_s_literal(hs_job_t *); @@ -101,23 +70,23 @@ static void _hs_patch_check(const hs_patch_job_t *job) * we've taken that in, we can know how much data to read to get the * arguments. */ -static enum hs_result _hs_patch_s_cmdbyte(hs_patch_job_t *job) +static enum hs_result hs_patch_s_cmdbyte(hs_job_t *job) { enum hs_result result; - if ((result = _hs_suck_n8(job->stream, &job->op)) != HS_OK) + if ((result = hs_suck_n8(job->stream, &job->op)) != HS_OK) return result; assert(job->op >= 0 && job->op <= 0xff); - job->cmd = &_hs_prototab[job->op]; + job->cmd = &hs_prototab[job->op]; - _hs_trace("got command byte 0x%02x (%s)", job->op, - _hs_op_kind_name(job->cmd->kind)); + hs_trace("got command byte 0x%02x (%s)", job->op, + hs_op_kind_name(job->cmd->kind)); if (job->cmd->len_1) - job->statefn = _hs_patch_s_params; + job->statefn = hs_patch_s_params; else - job->statefn = _hs_patch_s_run; + job->statefn = hs_patch_s_run; return HS_RUN_OK; } @@ -127,7 +96,7 @@ static enum hs_result _hs_patch_s_cmdbyte(hs_patch_job_t *job) * Called after reading a command byte to pull in its parameters and * then setup to execute the command. */ -static enum hs_result _hs_patch_s_params(hs_patch_job_t *job) +static enum hs_result hs_patch_s_params(hs_job_t *job) { enum hs_result result; int len = job->cmd->len_1 + job->cmd->len_2; @@ -135,22 +104,22 @@ static enum hs_result _hs_patch_s_params(hs_patch_job_t *job) assert(len); - result = _hs_scoop_readahead(job->stream, len, &p); + result = hs_scoop_readahead(job->stream, len, &p); if (result != HS_OK) return result; /* we now must have LEN bytes buffered */ - result = _hs_suck_netint(job->stream, job->cmd->len_1, &job->param1); + result = hs_suck_netint(job->stream, job->cmd->len_1, &job->param1); /* shouldn't fail, since we already checked */ assert(result == HS_OK); if (job->cmd->len_2) { - result = _hs_suck_netint(job->stream, job->cmd->len_2, - &job->param2); + result = hs_suck_netint(job->stream, job->cmd->len_2, + &job->param2); assert(result == HS_OK); } - job->statefn = _hs_patch_s_run; + job->statefn = hs_patch_s_run; return HS_RUN_OK; } @@ -160,20 +129,20 @@ static enum hs_result _hs_patch_s_params(hs_patch_job_t *job) /* * Called when we've read in the whole command and we need to execute it. */ -static enum hs_result _hs_patch_s_run(hs_patch_job_t *job) +static enum hs_result hs_patch_s_run(hs_job_t *job) { - _hs_trace("running command 0x%x, kind %d", job->op, job->cmd->kind); + hs_trace("running command 0x%x, kind %d", job->op, job->cmd->kind); switch (job->cmd->kind) { case HS_KIND_LITERAL: - job->statefn = _hs_patch_s_literal; + job->statefn = hs_patch_s_literal; return HS_RUN_OK; case HS_KIND_EOF: - job->statefn = _hs_patch_s_complete; + job->statefn = hs_patch_s_complete; return HS_OK; /* so we exit here; trying to continue causes an error */ default: - _hs_error("bogus command 0x%02x", job->op); + hs_error("bogus command 0x%02x", job->op); return HS_BAD_MAGIC; } } @@ -182,7 +151,7 @@ static enum hs_result _hs_patch_s_run(hs_patch_job_t *job) /* * Called when trying to copy through literal data. */ -static enum hs_result _hs_patch_s_literal(hs_patch_job_t *job) +static enum hs_result hs_patch_s_literal(hs_job_t *job) { int len; if (job->cmd->len_1) @@ -190,11 +159,11 @@ static enum hs_result _hs_patch_s_literal(hs_patch_job_t *job) else len = job->cmd->immediate; - _hs_trace("copying %d bytes of literal data", len); + hs_trace("copying %d bytes of literal data", len); - _hs_blow_copy(job->stream, len); + hs_blow_copy(job->stream, len); - job->statefn = _hs_patch_s_cmdbyte; + job->statefn = hs_patch_s_cmdbyte; return HS_RUN_OK; } @@ -202,29 +171,29 @@ static enum hs_result _hs_patch_s_literal(hs_patch_job_t *job) /* * Called after encountering EOF on the patch. */ -static enum hs_result _hs_patch_s_complete(hs_patch_job_t *UNUSED(job)) +static enum hs_result hs_patch_s_complete(hs_job_t *UNUSED(job)) { - _hs_fatal("the patch has already finished"); + hs_fatal("the patch has already finished"); } /* * Called while we're trying to read the header of the patch. */ -static enum hs_result _hs_patch_s_header(hs_patch_job_t *job) +static enum hs_result hs_patch_s_header(hs_job_t *job) { int v; int result; - if ((result =_hs_suck_n32(job->stream, &v)) != HS_OK) + if ((result =hs_suck_n32(job->stream, &v)) != HS_OK) return result; if (v != HS_DELTA_MAGIC) return HS_BAD_MAGIC; - _hs_trace("got patch magic %#10x", v); + hs_trace("got patch magic %#10x", v); - job->statefn = _hs_patch_s_cmdbyte; + job->statefn = hs_patch_s_cmdbyte; return HS_RUN_OK; } @@ -237,13 +206,12 @@ static enum hs_result _hs_patch_s_header(hs_patch_job_t *job) * the stream pointers. When finished, call hs_patch_finish to * dispose of it. */ -hs_patch_job_t *hs_patch_begin(hs_stream_t *stream, hs_copy_cb *copy_cb, - void *copy_arg) +hs_job_t *hs_patch_begin(hs_stream_t *stream, hs_copy_cb *copy_cb, + void *copy_arg) { - hs_patch_job_t *job = _hs_alloc_struct(hs_patch_job_t); + hs_job_t *job = hs_job_new(stream); - job->statefn = _hs_patch_s_header; - job->dogtag = HS_PATCH_TAG; + job->statefn = hs_patch_s_header; job->stream = stream; job->copy_cb = copy_cb; @@ -254,47 +222,3 @@ hs_patch_job_t *hs_patch_begin(hs_stream_t *stream, hs_copy_cb *copy_cb, return job; } - -/* - * Patch iterator, called by the client as more input data or output space - * becomes available. - * - * Calls whatever code is appropriate to the current state. - * - * When the state function is called, it knows the tube is empty, and so - * it can go ahead and blow output as required. It might have to return - * early if not enough input data is available. - */ -int hs_patch_iter(hs_patch_job_t *job) -{ - int result; - - _hs_patch_check(job); - - while (1) { - result = _hs_tube_catchup(job->stream); - if (result != HS_OK) - return result; - - result = job->statefn(job); - if (result != HS_RUN_OK) - return result; - } - - return result; -} - - -/* - * Free memory used by applying a patch. This doesn't finish the work. - * It just drops it wherever it was. - */ -enum hs_result hs_patch_finish(hs_patch_job_t *job) -{ - _hs_patch_check(job); - - _hs_bzero(job, sizeof *job); - free(job); - - return HS_OK; -} @@ -46,7 +46,7 @@ typedef struct hs_prototab_ent { size_t len_1, len_2, total_size; } hs_prototab_ent_t; -extern const hs_prototab_ent_t _hs_prototab[]; +extern const hs_prototab_ent_t hs_prototab[]; /* FIXME: Really these should be autogenerated by the same code in @@ -3,7 +3,7 @@ * rdiff -- generate and apply rsync signatures and deltas * $Id$ * - * Copyright (C) 1999, 2000 by Martin Pool <mbp@linuxcare.com.au> + * Copyright (C) 1999, 2000, 2001 by Martin Pool <mbp@linuxcare.com.au> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,7 @@ * to the dead. * -- Harold Bloom */ -#include "config.h" +#include <config.h> #include <assert.h> #include <sys/types.h> @@ -79,7 +79,7 @@ static void show_usage(void) printf("Usage: %s [OPTIONS] signature OLDFILE SIGNATURE\n" " or: %s [OPTIONS] delta SIGNATURE NEWFILE DELTA\n" " or: %s [OPTIONS] patch OLDFILE DELTA NEWFILE\n" - " or: %s [OPTIONS] md4 INPUT\n" + " or: %s [OPTIONS] sum INPUT\n" "\n" "Compute rsync checksums or deltas, or apply a delta.\n" "\n" @@ -112,20 +112,20 @@ static void process_args(int argc, char **argv) show_usage(); exit(0); case 'I': - _hs_readintarg(argv[optind], optarg, &hs_inbuflen); + hs_readintarg(argv[optind], optarg, &hs_inbuflen); break; case 'O': - _hs_readintarg(argv[optind], optarg, &hs_outbuflen); + hs_readintarg(argv[optind], optarg, &hs_outbuflen); break; case 'V': - hs_show_version(stdout, PROGRAM); - exit(0); + printf("%s (%s)\n", PROGRAM, hs_libhsync_version); + exit(0); case 'L': - hs_show_licence(stdout); + puts(hs_licence_string); exit(0); case 'v': if (!hs_supports_trace()) { - _hs_error("library does not support trace"); + hs_error("library does not support trace"); } hs_trace_set_level(LOG_DEBUG); break; @@ -137,25 +137,157 @@ static void process_args(int argc, char **argv) int main(int argc, char **argv) { - process_args(argc, argv); + process_args(argc, argv); - argc -= optind; - argv += optind; + argc -= optind; + argv += optind; + + if (argc <= 0) { + ; + } else if (strisprefix(argv[0], "signature")) { + return hs_rdiff_signature(argc, argv); + } else if (strisprefix(argv[0], "delta")) { + return hs_rdiff_delta(argc, argv); + } else if (strisprefix(argv[0], "patch")) { + return hs_rdiff_patch(argc, argv); + } else if (strisprefix(argv[0], "sum")) { + return hs_rdiff_sum(argc, argv); + } - if (argc <= 0) { - ; - } else if (strisprefix(argv[0], "signature")) { - return hs_rdiff_signature(argc, argv); - } else if (strisprefix(argv[0], "delta")) { - return hs_rdiff_delta(argc, argv); - } else if (strisprefix(argv[0], "patch")) { - return hs_rdiff_patch(argc, argv); - } else if (strisprefix(argv[0], "md4")) { - return hs_rdiff_md4(argc, argv); + hs_error("You must specify one of the signature, delta, " + "patch or sum operations" + ", or try --help."); + return 1; +} + + + +/* This should probably be a parameter to all functions instead, but + * I'm not sure I want to keep it. */ +extern int output_mode; + +enum hs_result hs_rdiff_sum(int argc, char **argv) +{ +#if 0 + unsigned char result[HS_MD4_LENGTH]; + char result_str[HS_MD4_LENGTH * 3]; + FILE *in_file; + + if (argc != 2) { + hs_error("Sum operation needs one filename"); + return 1; } - _hs_error("You must specify one of the signature, delta, " - "patch or sum operations" - ", or try --help."); - return 1; + in_file = hs_file_open(argv[1], O_RDONLY); + + hs_mdfour_file(in_file, result); + hs_hexify(result_str, result, HS_MD4_LENGTH); + + printf("%s\n", result_str); + + return 0; +#else + hs_fatal("not implemented at the moment, back soon"); +#endif +} + + + +hs_result +hs_rdiff_delta(int argc, char **argv) +{ +#if 0 + FILE *new_file, *sig_file, *delta_file; + hs_job_t *job; + hs_stream_t *stream; + char *inbuf, *outbuf; + hs_result result; + + if (argc != 4) { + hs_error("Delta operation needs three filenames: " + "SIGNATURE NEWFILE DELTA"); + return 1; + } + + sig_file = hs_file_open(argv[1], O_RDONLY); + new_file = hs_file_open(argv[2], O_RDONLY); + delta_file = hs_file_open(argv[3], output_mode); + + job = hs_delta_begin(stream); + + /* TODO: read signatures; then close signature file. */ + return result; +#else + hs_fatal("not implemented at the moment, back soon"); +#endif +} + + + +enum hs_result +hs_rdiff_patch(int argc, char *argv[]) +{ +#if 0 + FILE *old_file, *delta_file, *new_file; + char *outbuf; + HSFILE *patch; + enum hs_result result; + size_t len; + + if (argc != 4) { + hs_error("Patch operation needs three filenames: " + "OLDFILE DELTA NEWFILE"); + return 1; + } + + old_file = hs_file_open(argv[1], O_RDONLY); + delta_file = hs_file_open(argv[2], O_RDONLY); + new_file = hs_file_open(argv[3], output_mode); + + outbuf = malloc(hs_outbuflen); + assert(outbuf); + patch = hs_patch_open(old_file, delta_file); + + do { + len = hs_outbuflen; + result = hs_patch_read(patch, outbuf, &len); + fwrite(outbuf, len, 1, new_file); + } while (result == HS_BLOCKED); + + if (result != HS_OK) + goto failed; + + return 0; + + failed: + hs_error("patch failed: %s", hs_strerror(result)); + + return 1; +#else + hs_fatal("not implemented at the moment, back soon"); +#endif +} + + + + +hs_result hs_rdiff_signature(int argc, char *argv[]) +{ + FILE *old_file, *sig_file; + hs_result result; + + if (argc != 3) { + hs_error("Signature operation needs two filenames"); + return 1; + } + + old_file = hs_file_open(argv[1], O_RDONLY); + sig_file = hs_file_open(argv[2], output_mode); + + result = hs_whole_signature(old_file, sig_file); + + if (result != HS_OK) + hs_error("signature failed: %s", hs_strerror(result)); + + return result; } diff --git a/readsums.c b/readsums.c new file mode 100644 index 0000000..2eeb7a9 --- /dev/null +++ b/readsums.c @@ -0,0 +1,126 @@ +/*= -*- c-file-style: "linux" -*- + * + * libhsync -- the library for network deltas + * $Id$ + * + * Copyright (C) 2001 by Martin Pool <mbp@linuxcare.com.au> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + + +#include <config.h> + +#include <assert.h> + +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif + +#include <sys/types.h> +#include <limits.h> +#include <inttypes.h> +#include <stdlib.h> + +#include "hsync.h" +#include "sumset.h" + +$if 0 +/* + * Read and remember all the signatures from last time. Return null * + * if there are no signatures. + */ +hs_sumset_t * +hs_read_sumset(hs_read_fn_t sigread_fn, void *sigread_priv) +{ + int ret = 0; + int block_len; + hs_sum_buf_t *asignature; + int n = 0; + int checksum1; + hs_sumset_t *sumbuf; + uint32_t tmp32; + + + ret = hs_check_sig_version(sigread_fn, sigread_priv); + if (ret <= 0) + return NULL; + + if (hs_read_blocksize(sigread_fn, sigread_priv, &block_len) < 0) + return NULL; + + sumbuf = hs_alloc_struct(hs_sumset_t); + + sumbuf->block_len = block_len; + + sumbuf->block_sums = NULL; + /* XXX: It's perhaps a bit inefficient to realloc each time. We could + prealloc, but for now we'll give realloc the benefit of the doubt. */ + + while (1) { + ret = hs_read_netint(sigread_fn, sigread_priv, &tmp32); + checksum1 = tmp32; + + if (ret == 0) + break; + if (ret < 0) { + hs_error("IO error while reading in signatures"); + goto fail; + } + assert(ret == 4); + + sumbuf->block_sums = realloc(sumbuf->block_sums, (n + 1) * sizeof(hs_sum_buf_t)); + if (sumbuf->block_sums == NULL) { + errno = ENOMEM; + ret = -1; + break; + } + asignature = &(sumbuf->block_sums[n]); + + asignature->weak_sum = checksum1; + asignature->i = ++n; + + /* read in the long sum */ + ret = hs_must_read(sigread_fn, sigread_priv, + asignature->strong_sum, DEFAULT_SUM_LENGTH); + if (ret != DEFAULT_SUM_LENGTH) { + hs_error("IO error while reading strong signature %d", n); + break; + } + } + if (ret < 0) { + hs_error("error reading checksums"); + goto fail; + } + + sumbuf->count = n; + hs_trace("Read %d sigs", n); + + if (hs_build_hash_table(sumbuf) < 0) { + hs_error("error building checksum hashtable"); + goto fail; + } + + return sumbuf; + + fail: + if (sumbuf) + free(sumbuf); + return NULL; +} + + +#endif @@ -27,22 +27,22 @@ void -_hs_roll_reset(hs_rollsum_t * rollsum) +hs_roll_reset(hs_rollsum_t * rollsum) { hs_bzero(rollsum, sizeof *rollsum); } int -_hs_stretch_sums(byte_t const *bytep, size_t full_block, +hs_stretch_sums(byte_t const *bytep, size_t full_block, size_t short_block, hs_rollsum_t * rollsum) { /* Checksum calculations are signed */ int8_t const *p = (int8_t const *) bytep; if (!rollsum->havesum) { - rollsum->weak_sum = _hs_calc_weak_sum(p, short_block); - _hs_trace("recalculate checksum: weak=%#x", rollsum->weak_sum); + rollsum->weak_sum = hs_calc_weak_sum(p, short_block); + hs_trace("recalculate checksum: weak=%#x", rollsum->weak_sum); rollsum->s1 = rollsum->weak_sum & 0xFFFF; rollsum->s2 = rollsum->weak_sum >> 16; } else { @@ -68,7 +68,7 @@ _hs_stretch_sums(byte_t const *bytep, size_t full_block, /* One byte rolls off the checksum. */ int -_hs_trim_sums(byte_t const *bytep, hs_rollsum_t * rollsum, size_t short_block) +hs_trim_sums(byte_t const *bytep, hs_rollsum_t * rollsum, size_t short_block) { /* Checksum calculations are signed */ int8_t const *p = (int8_t const *) bytep; @@ -38,10 +38,10 @@ struct hs_rollsum { #define HS_PAINFUL_HONESTY -int _hs_trim_sums(byte_t const *p, hs_rollsum_t * rollsum, +int hs_trim_sums(byte_t const *p, hs_rollsum_t * rollsum, size_t short_block); -int _hs_stretch_sums(byte_t const *p, size_t full_block, +int hs_stretch_sums(byte_t const *p, size_t full_block, size_t short_block, hs_rollsum_t * rollsum); -void _hs_roll_reset(hs_rollsum_t * rollsum); +void hs_roll_reset(hs_rollsum_t * rollsum); @@ -0,0 +1,138 @@ +/*= -*- c-file-style: "linux" -*- + * + * libhsync -- the library for network deltas + * $Id$ + * + * Copyright (C) 2001 by Martin Pool <mbp@linuxcare.com.au> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +/* + * rsum.c -- Command line tool to generate rsync signatures for a file. + */ + +#include <config.h> + +#include <stdlib.h> +#include <stdio.h> +#include <getopt.h> +#include <syslog.h> +#include <fcntl.h> +#include <popt.h> + +#include "hsync.h" +#include "hsyncfile.h" +#include "fileutil.h" +#include "util.h" +#include "trace.h" + + +#define PROGRAM "rsum" + + +/* Overwrite existing files. */ +int force = 0; +size_t block_len, sum_len; + + +const struct poptOption opts[] = { + POPT_AUTOHELP + { "version", 'V', POPT_ARG_NONE, 0, 'V', "show program version" }, + { NULL, '\0', 0, 0 } +}; + + + +static void show_usage(void) +{ + printf("Usage: %s [OPTIONS] OLDFILE SIGNATURE\n" + "\n" + "Compute rsync file signature.\n" + "\n" + " -v, --verbose trace internal processing\n" + " -I, --input-buffer=BYTES input buffer size\n" + " -O, --output-buffer=BYTES output buffer size\n" + " --help display this help and exit\n" + " --version output version information and exit\n" + " --licence show summary copying terms and exit\n" + , + PROGRAM); +} + + +static void process_args(int argc, char **argv) +{ + int c, longind; + + while ((c = getopt_long(argc, argv, "vfI:O:", longopts, &longind)) != -1) { + switch (c) { + case '?': + case ':': + exit(1); + case 'h': + show_usage(); + exit(0); + case 'I': + hs_readintarg(argv[optind], optarg, &hs_inbuflen); + break; + case 'O': + hs_readintarg(argv[optind], optarg, &hs_outbuflen); + break; + case 'V': + printf("%s (%s)\n", PROGRAM, hs_libhsync_version); + exit(0); + case 'L': + puts(hs_licence_string); + exit(0); + case 'b': + + case 'v': + if (!hs_supports_trace()) { + hs_error("library does not support trace"); + } + hs_trace_set_level(LOG_DEBUG); + break; + } + } +} + + +int main(int argc, char *argv[]) +{ + FILE *old_file, *sig_file; + hs_result result; + + process_args(argc, argv); + + argc -= optind; + argv += optind; + + if (argc != 3) { + hs_error("Signature operation needs two filenames"); + return 1; + } + + old_file = hs_file_open(argv[1], O_RDONLY); + sig_file = hs_file_open(argv[2], O_WRONLY|O_CREAT|O_TRUNC); + + result = hs_whole_signature(old_file, sig_file); + + if (result != HS_OK) + hs_error("signature failed: %s", hs_strerror(result)); + + return result; +} @@ -59,7 +59,7 @@ | -- Shihad, `The General Electric'. */ -#include "config.h" +#include <config.h> #include <assert.h> #include <stdlib.h> @@ -75,7 +75,7 @@ /* * Try to accept from the input buffer to get LEN bytes in the scoop. */ -static void _hs_scoop_input(hs_stream_t *stream, size_t len) +static void hs_scoop_input(hs_stream_t *stream, size_t len) { hs_simpl_t *impl = stream->impl; size_t tocopy; @@ -86,14 +86,14 @@ static void _hs_scoop_input(hs_stream_t *stream, size_t len) /* need to allocate a new buffer, too */ char *newbuf; int newsize = 2 * len; - newbuf = _hs_alloc(newsize, "scoop buffer"); + newbuf = hs_alloc(newsize, "scoop buffer"); if (impl->scoop_avail) memcpy(newbuf, impl->scoop_next, impl->scoop_avail); if (impl->scoop_buf) free(impl->scoop_buf); impl->scoop_buf = impl->scoop_next = newbuf; impl->scoop_alloc = newsize; - _hs_trace("resized scoop buffer to %d bytes", + hs_trace("resized scoop buffer to %d bytes", impl->scoop_alloc); } else { /* this buffer size is fine, but move the existing @@ -110,7 +110,7 @@ static void _hs_scoop_input(hs_stream_t *stream, size_t len) assert(tocopy + impl->scoop_avail <= impl->scoop_alloc); memcpy(impl->scoop_next + impl->scoop_avail, stream->next_in, tocopy); - _hs_trace("accepted %d bytes from input to scoop", tocopy); + hs_trace("accepted %d bytes from input to scoop", tocopy); impl->scoop_avail += tocopy; stream->next_in += tocopy; stream->avail_in -= tocopy; @@ -126,18 +126,18 @@ static void _hs_scoop_input(hs_stream_t *stream, size_t len) * after examining that block, we might decide to advance over all of * it (if there is a match), or just one byte (if not). */ -void _hs_scoop_advance(hs_stream_t *stream, size_t len) +void hs_scoop_advance(hs_stream_t *stream, size_t len) { hs_simpl_t *impl = stream->impl; if (impl->scoop_avail) { /* reading from the scoop buffer */ - _hs_trace("advance over %d bytes from scoop", len); + hs_trace("advance over %d bytes from scoop", len); assert(len <= impl->scoop_avail); impl->scoop_avail -= len; impl->scoop_next += len; } else { - _hs_trace("advance over %d bytes from input buffer", len); + hs_trace("advance over %d bytes from input buffer", len); assert(len <= stream->avail_in); stream->avail_in -= len; stream->next_in += len; @@ -155,47 +155,47 @@ void _hs_scoop_advance(hs_stream_t *stream, size_t len) * * The data is not actually removed from the input, so this function * lets you do readahead. If you want to keep any of the data, you - * should also call _hs_scoop_advance to skip over it. + * should also call hs_scoop_advance to skip over it. */ -enum hs_result _hs_scoop_readahead(hs_stream_t *stream, size_t len, void **ptr) +enum hs_result hs_scoop_readahead(hs_stream_t *stream, size_t len, void **ptr) { hs_simpl_t *impl = stream->impl; - _hs_stream_check(stream); + hs_stream_check(stream); if (impl->scoop_avail >= len) { /* We have enough data queued to satisfy the request, * so go straight from the scoop buffer. */ - _hs_trace("got %d bytes direct from scoop", len); + hs_trace("got %d bytes direct from scoop", len); *ptr = impl->scoop_next; return HS_OK; } else if (impl->scoop_avail) { /* We have some data in the scoop, but not enough to * satisfy the request. */ - _hs_trace("data is present in the scoop and must be used"); - _hs_scoop_input(stream, len); + hs_trace("data is present in the scoop and must be used"); + hs_scoop_input(stream, len); if (impl->scoop_avail < len) { - _hs_trace("still only have %d bytes in scoop, not enough", + hs_trace("still only have %d bytes in scoop, not enough", impl->scoop_avail); return HS_BLOCKED; } else { - _hs_trace("scoop now has %d bytes, this is enough", + hs_trace("scoop now has %d bytes, this is enough", impl->scoop_avail); *ptr = impl->scoop_next; return HS_OK; } } else if (stream->avail_in >= len) { /* There's enough data in the stream's input */ - _hs_trace("got %d bytes direct from input", len); + hs_trace("got %d bytes direct from input", len); *ptr = stream->next_in; return HS_OK; } else { /* Nothing was queued before, but we don't have enough * data to satisfy the request. So queue what little * we have, and try again next time. */ - _hs_trace("not enough data to satisfy request, scooping %d bytes", + hs_trace("not enough data to satisfy request, scooping %d bytes", impl->scoop_avail); - _hs_scoop_input(stream, len); + hs_scoop_input(stream, len); return HS_BLOCKED; } } @@ -206,13 +206,13 @@ enum hs_result _hs_scoop_readahead(hs_stream_t *stream, size_t len, void **ptr) * Read LEN bytes if possible, and remove them from the input scoop. * If there's not enough data yet, return HS_BLOCKED. */ -enum hs_result _hs_scoop_read(hs_stream_t *stream, size_t len, void **ptr) +enum hs_result hs_scoop_read(hs_stream_t *stream, size_t len, void **ptr) { enum hs_result result; - result = _hs_scoop_readahead(stream, len, ptr); + result = hs_scoop_readahead(stream, len, ptr); if (result == HS_OK) - _hs_scoop_advance(stream, len); + hs_scoop_advance(stream, len); return result; } @@ -223,11 +223,11 @@ enum hs_result _hs_scoop_read(hs_stream_t *stream, size_t len, void **ptr) * Read whatever remains in the input stream, assuming that it runs up * to the end of the file. Set LEN appropriately. */ -enum hs_result _hs_scoop_read_rest(hs_stream_t *stream, size_t *len, void **ptr) +enum hs_result hs_scoop_read_rest(hs_stream_t *stream, size_t *len, void **ptr) { hs_simpl_t *impl = stream->impl; *len = impl->scoop_avail + stream->avail_in; - return _hs_scoop_read(stream, *len, ptr); + return hs_scoop_read(stream, *len, ptr); } @@ -45,14 +45,14 @@ #define gettag(sum) gettag2((sum)&0xFFFF,(sum)>>16) static int -_hs_compare_targets(struct target const *t1, struct target const *t2) +hs_compare_targets(struct target const *t1, struct target const *t2) { return ((int) t1->t - (int) t2->t); } int -_hs_build_hash_table(hs_sumset_t * sums) +hs_build_hash_table(hs_sumset_t * sums) { int i; @@ -70,7 +70,7 @@ _hs_build_hash_table(hs_sumset_t * sums) * care? */ qsort(sums->targets, sums->count, sizeof(sums->targets[0]), - (int (*)(const void *, const void *)) _hs_compare_targets); + (int (*)(const void *, const void *)) hs_compare_targets); } for (i = 0; i < TABLESIZE; i++) @@ -95,7 +95,7 @@ _hs_build_hash_table(hs_sumset_t * sums) * anything. */ int -_hs_search_for_block(hs_weak_sum_t weak_sum, +hs_search_for_block(hs_weak_sum_t weak_sum, byte_t const *inbuf, size_t block_len, hs_sumset_t const *sums, hs_stats_t * stats, off_t * match_where) @@ -128,10 +128,10 @@ _hs_search_for_block(hs_weak_sum_t weak_sum, token = sums->block_sums[i].i; - _hs_trace("found weak match for %08x in token %d", weak_sum, token); + hs_trace("found weak match for %08x in token %d", weak_sum, token); if (!got_strong) { - _hs_calc_strong_sum(inbuf, block_len, strong_sum, + hs_calc_strong_sum(inbuf, block_len, strong_sum, DEFAULT_SUM_LENGTH); got_strong = 1; } @@ -144,7 +144,7 @@ _hs_search_for_block(hs_weak_sum_t weak_sum, *match_where = (token - 1) * sums->block_len; return 1; } else { - _hs_trace("this was a false positive, the strong sums " + hs_trace("this was a false positive, the strong sums " "don't match"); stats->false_matches++; } @@ -21,7 +21,7 @@ */ int -_hs_search_for_block(hs_weak_sum_t weak_sum, +hs_search_for_block(hs_weak_sum_t weak_sum, byte_t const *inbuf, size_t block_len, hs_sumset_t const *sums, hs_stats_t * stats, off_t * match_where); @@ -53,7 +53,7 @@ * **************************************************************/ -#include "config.h" +#include <config.h> #include <string.h> # include <ctype.h> @@ -34,7 +34,7 @@ hs_log_stats(hs_stats_t const *stats) char buf[1000]; hs_format_stats(stats, buf, sizeof buf - 1); - _hs_log(LOG_INFO, "%s", buf); + hs_log(LOG_INFO, "%s", buf); return 0; } @@ -3,7 +3,7 @@ * libhsync -- dynamic caching and delta update in HTTP * $Id$ * - * Copyright (C) 2000 by Martin Pool <mbp@linuxcare.com.au> + * Copyright (C) 2000, 2001 by Martin Pool <mbp@linuxcare.com.au> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -20,9 +20,13 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - /* - * Pick a window, Jimmy, you're leaving. - */ + /* + * Programming languages should be designed not + * by piling feature on top of feature, but by + * removing the weaknesses and restrictions that + * make additional features appear necessary. + * -- Revised^5 Report on Scheme + */ /* @@ -44,8 +48,8 @@ * buffer. Instead it knows that we can send either literal data, or * data copied through from the input of the stream. * - * In streamfile.c you will find functions that then map buffers onto - * stdio files. + * In buf.c you will find functions that then map buffers onto stdio + * files. * * So on return from an encoding function, either the input or the * output or possibly both will have no more bytes available. @@ -80,7 +84,7 @@ /* TODO: Return errors rather than aborting if something goes wrong. */ -#include "config.h" +#include <config.h> #include <assert.h> @@ -107,10 +111,10 @@ void hs_stream_init(hs_stream_t *stream) hs_simpl_t *impl; assert(stream); - _hs_bzero(stream, sizeof *stream); + hs_bzero(stream, sizeof *stream); stream->dogtag = HS_STREAM_DOGTAG; - impl = stream->impl = _hs_alloc_struct(hs_simpl_t); + impl = stream->impl = hs_alloc_struct(hs_simpl_t); /* because scoop_alloc == 0, the scoop buffer will be * allocated when required. */ @@ -121,7 +125,7 @@ void hs_stream_init(hs_stream_t *stream) * Make sure everything is basically OK with STREAM. */ void -_hs_stream_check(hs_stream_t *stream) +hs_stream_check(hs_stream_t *stream) { assert(stream); assert(stream->dogtag == HS_STREAM_DOGTAG); @@ -134,29 +138,30 @@ _hs_stream_check(hs_stream_t *stream) * there is not enough space in one or the other stream. * * This always does the copy immediately. Most functions should call - * _hs_blow_copy to cause the copy to happen gradually as space + * hs_blow_copy to cause the copy to happen gradually as space * becomes available. */ -int _hs_stream_copy(hs_stream_t *stream, int max_len) +int hs_stream_copy(hs_stream_t *stream, int max_len) { int len = max_len; - _hs_stream_check(stream); + hs_stream_check(stream); assert(len > 0); if ((unsigned) len > stream->avail_in) { - _hs_trace("copy limited to %d available input bytes", + hs_trace("copy limited to %d available input bytes", stream->avail_in); len = stream->avail_in; } + if ((unsigned) len > stream->avail_out) { - _hs_trace("copy limited to %d available output bytes", + hs_trace("copy limited to %d available output bytes", stream->avail_out); len = stream->avail_out; } - _hs_trace("stream copied chunk of %d bytes", len); + hs_trace("stream copied chunk of %d bytes", len); memcpy(stream->next_out, stream->next_in, len); @@ -177,12 +182,12 @@ int _hs_stream_copy(hs_stream_t *stream, int max_len) * means you're done. */ int -_hs_stream_is_empty(hs_stream_t *stream) +hs_stream_is_empty(hs_stream_t *stream) { - int ret = stream->avail_in == 0 && _hs_tube_is_idle(stream); + int ret = stream->avail_in == 0 && hs_tube_is_idle(stream); if (ret) - _hs_trace("stream now has no input and no tube output"); + hs_trace("stream now has no input and no tube output"); return ret; } @@ -194,7 +199,7 @@ _hs_stream_is_empty(hs_stream_t *stream) * because it has either consumed all the input or has filled the * output buffer. This function checks that simple postcondition. */ -void _hs_stream_check_exit(hs_stream_t const *stream) +void hs_stream_check_exit(hs_stream_t const *stream) { assert(stream->avail_in == 0 || stream->avail_out == 0); } @@ -3,7 +3,7 @@ * libhsync -- library for network deltas * $Id$ * - * Copyright (C) 2000 by Martin Pool <mbp@linuxcare.com.au> + * Copyright (C) 2000, 2001 by Martin Pool <mbp@linuxcare.com.au> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -20,6 +20,12 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + /* Two wars in a lifetime bear hard on the little places. + * In winter when storms come rushing out of the dark, + * And the bay boils like a cauldron of sharks, + * The old remember the trenches at Paschendale + * And sons who died on the Burma Railway. */ + /* * Stream private data @@ -46,21 +52,21 @@ typedef struct hs_simpl { -int _hs_stream_is_empty(hs_stream_t *stream); -int _hs_stream_copy(hs_stream_t *stream, int len); -void _hs_stream_check(hs_stream_t *stream); -void _hs_stream_check_exit(hs_stream_t const *stream); +int hs_stream_is_empty(hs_stream_t *stream); +int hs_stream_copy(hs_stream_t *stream, int len); +void hs_stream_check(hs_stream_t *stream); +void hs_stream_check_exit(hs_stream_t const *stream); -int _hs_tube_catchup(hs_stream_t *); -void _hs_blow_literal(hs_stream_t *, void const *buf, size_t len); +int hs_tube_catchup(hs_stream_t *); +void hs_blow_literal(hs_stream_t *, void const *buf, size_t len); -void _hs_blow_copy(hs_stream_t *, int len); +void hs_blow_copy(hs_stream_t *, int len); -int _hs_tube_is_idle(hs_stream_t const *); -void _hs_check_tube(hs_stream_t *); +int hs_tube_is_idle(hs_stream_t const *); +void hs_check_tube(hs_stream_t *); -void _hs_scoop_advance(hs_stream_t *stream, size_t len); -enum hs_result _hs_scoop_readahead(hs_stream_t *stream, size_t len, void **ptr); -enum hs_result _hs_scoop_read(hs_stream_t *stream, size_t len, void **ptr); -enum hs_result _hs_scoop_read_rest(hs_stream_t *stream, size_t *len, void **ptr); +void hs_scoop_advance(hs_stream_t *stream, size_t len); +enum hs_result hs_scoop_readahead(hs_stream_t *stream, size_t len, void **ptr); +enum hs_result hs_scoop_read(hs_stream_t *stream, size_t len, void **ptr); +enum hs_result hs_scoop_read_rest(hs_stream_t *stream, size_t *len, void **ptr); diff --git a/streamfile.c b/streamfile.c deleted file mode 100644 index 958d7aa..0000000 --- a/streamfile.c +++ /dev/null @@ -1,113 +0,0 @@ -/*= -*- c-file-style: "linux" -*- - * - * libhsync -- the library for network deltas - * $Id$ - * - * Copyright (C) 2000 by Martin Pool <mbp@linuxcare.com.au> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - - -#include "config.h" - -#include <assert.h> -#include <stdlib.h> -#include <stdio.h> -#include <errno.h> -#include <string.h> - -#include "hsync.h" -#include "trace.h" -#include "streamfile.h" - - - -/* - * If the stream has no more data available, read some from F into BUF, - * and let the stream use that. - */ -int _hs_fill_from_file(hs_stream_t *stream, char *buf, size_t buf_len, FILE *f) -{ - /* This is only allowed if either the stream has no input buffer - * yet, or that buffer could possibly be BUF. */ - if (stream->next_in != NULL) { - assert(stream->avail_in <= buf_len); - assert(stream->next_in >= buf); - assert(stream->next_in <= buf + buf_len); - } else { - assert(stream->avail_in == 0); - } - - if (stream->avail_in == 0 && !feof(f)) { - int len = fread(buf, 1, buf_len, f); - if (len < 0) { - _hs_error("error filling stream from file: %s", - strerror(errno)); - return HS_IO_ERROR; - } - stream->avail_in = len; - stream->next_in = buf; - } - - return HS_OK; -} - - -/* - * The stream is already using BUF for an output buffer, and probably - * contains some buffered output now. Write this out to F, and reset - * the buffer cursor. - */ -enum hs_result _hs_drain_to_file(hs_stream_t *stream, - char *buf, size_t buf_len, - FILE *f) -{ - int present; - - /* This is only allowed if either the stream has no output buffer - * yet, or that buffer could possibly be BUF. */ - if (stream->next_out == NULL) { - assert(stream->avail_out == 0); - - stream->next_out = buf; - stream->avail_out = buf_len; - - return HS_OK; - } - - assert(stream->avail_out <= buf_len); - assert(stream->next_out >= buf); - assert(stream->next_out <= buf + buf_len); - - present = stream->next_out - buf; - if (present > 0) { - int result; - - assert(present > 0); - - result = fwrite(buf, 1, present, f); - if (present != result) { - _hs_error("error draining stream to file: %s", - strerror(errno)); - return HS_IO_ERROR; - } - - stream->next_out = buf; - stream->avail_out = buf_len; - } - - return HS_OK; -} @@ -3,7 +3,7 @@ * libhsync -- library for network deltas * $Id$ * - * Copyright (C) 1999, 2000 by Martin Pool <mbp@linuxcare.com.au> + * Copyright (C) 1999, 2000, 2001 by Martin Pool <mbp@linuxcare.com.au> * Copyright (C) 1999 by Andrew Tridgell * * This program is free software; you can redistribute it and/or modify @@ -21,7 +21,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" +#include <config.h> #include <assert.h> @@ -33,109 +33,27 @@ #include <limits.h> #include <inttypes.h> #include <stdlib.h> +#include <syslog.h> #include "hsync.h" - -#include "sum_p.h" - -/* - * Read and remember all the signatures from last time. Return null * - * if there are no signatures. - */ -hs_sumset_t * -hs_read_sumset(hs_read_fn_t sigread_fn, void *sigread_priv) -{ - int ret = 0; - int block_len; - hs_sum_buf_t *asignature; - int n = 0; - int checksum1; - hs_sumset_t *sumbuf; - uint32_t tmp32; - - - ret = _hs_check_sig_version(sigread_fn, sigread_priv); - if (ret <= 0) - return NULL; - - if (_hs_read_blocksize(sigread_fn, sigread_priv, &block_len) < 0) - return NULL; - - sumbuf = _hs_alloc_struct(hs_sumset_t); - - sumbuf->block_len = block_len; - - sumbuf->block_sums = NULL; - /* XXX: It's perhaps a bit inefficient to realloc each time. We could - prealloc, but for now we'll give realloc the benefit of the doubt. */ - - while (1) { - ret = _hs_read_netint(sigread_fn, sigread_priv, &tmp32); - checksum1 = tmp32; - - if (ret == 0) - break; - if (ret < 0) { - _hs_error("IO error while reading in signatures"); - goto fail; - } - assert(ret == 4); - - sumbuf->block_sums = realloc(sumbuf->block_sums, (n + 1) * sizeof(hs_sum_buf_t)); - if (sumbuf->block_sums == NULL) { - errno = ENOMEM; - ret = -1; - break; - } - asignature = &(sumbuf->block_sums[n]); - - asignature->weak_sum = checksum1; - asignature->i = ++n; - - /* read in the long sum */ - ret = _hs_must_read(sigread_fn, sigread_priv, - asignature->strong_sum, DEFAULT_SUM_LENGTH); - if (ret != DEFAULT_SUM_LENGTH) { - _hs_error("IO error while reading strong signature %d", n); - break; - } - } - if (ret < 0) { - _hs_error("error reading checksums"); - goto fail; - } - - sumbuf->count = n; - _hs_trace("Read %d sigs", n); - - if (_hs_build_hash_table(sumbuf) < 0) { - _hs_error("error building checksum hashtable"); - goto fail; - } - - return sumbuf; - - fail: - if (sumbuf) - free(sumbuf); - return NULL; -} - +#include "sumset.h" +#include "util.h" +#include "trace.h" void hs_free_sumset(hs_sumset_t * psums) { - if (psums->block_sums) - free(psums->block_sums); + if (psums->block_sums) + free(psums->block_sums); - assert(psums->tag_table); - free(psums->tag_table); + assert(psums->tag_table); + free(psums->tag_table); - if (psums->targets) - free(psums->targets); + if (psums->targets) + free(psums->targets); - hs_bzero(psums, sizeof *psums); - free(psums); + hs_bzero(psums, sizeof *psums); + free(psums); } @@ -143,23 +61,23 @@ hs_free_sumset(hs_sumset_t * psums) void hs_sumset_dump(hs_sumset_t const *sums) { - int i; - char strong_hex[MD4_LENGTH * 3]; + int i; + char strong_hex[HS_MD4_LENGTH * 3]; - _hs_log(LOG_INFO, - "sumset info: block_len=%d, file length=%lu, " - "number of chunks=%d, remainder=%d", - sums->block_len, - (unsigned long) sums->flength, sums->count, - sums->remainder); - - for (i = 0; i < sums->count; i++) { - hs_hexify_buf(strong_hex, sums->block_sums[i].strong_sum, - DEFAULT_SUM_LENGTH); - _hs_log(LOG_INFO, - "sum %6d: weak=%08x, strong=%s", - i, sums->block_sums[i].weak_sum, strong_hex); - } + hs_log(LOG_INFO, + "sumset info: block_len=%d, file length=%lu, " + "number of chunks=%d, remainder=%d", + sums->block_len, + (unsigned long) sums->flength, sums->count, + sums->remainder); + + for (i = 0; i < sums->count; i++) { + hs_hexify(strong_hex, sums->block_sums[i].strong_sum, + sums->strong_sum_len); + hs_log(LOG_INFO, + "sum %6d: weak=%08x, strong=%s", + i, sums->block_sums[i].weak_sum, strong_hex); + } } @@ -1,8 +1,9 @@ /*= -*- c-file-style: "linux" -*- - * rproxy -- dynamic caching and delta update in HTTP + * + * libhsync -- the library for network deltas * $Id$ * - * Copyright (C) 1999, 2000 by Martin Pool <mbp@linuxcare.com.au> + * Copyright (C) 1999, 2000, 2001 by Martin Pool <mbp@linuxcare.com.au> * Copyright (C) 1999 by Andrew Tridgell <tridge@linuxcare.com.au> * * This program is free software; you can redistribute it and/or @@ -26,14 +27,10 @@ typedef unsigned char hs_strong_sum_t[HS_MD4_LENGTH]; typedef struct hs_rollsum hs_rollsum_t; -struct hs_target { +typedef struct hs_target { short t; int i; -}; - - -/* TODO: Include length of strong checksums in case it varies between - * files. */ +} hs_target_t; typedef struct hs_sum_buf hs_sum_buf_t; @@ -43,13 +40,14 @@ typedef struct hs_sum_buf hs_sum_buf_t; * search. */ struct hs_sumset { - off_t flength; /* total file length */ - int count; /* how many chunks */ - int remainder; /* flength % block_length */ - int block_len; /* block_length */ - hs_sum_buf_t *block_sums; /* points to info for each chunk */ - int *tag_table; - struct target *targets; + off_t flength; /* total file length */ + int count; /* how many chunks */ + int remainder; /* flength % block_length */ + int block_len; /* block_length */ + int strong_sum_len; + hs_sum_buf_t *block_sums; /* points to info for each chunk */ + int *tag_table; + hs_target_t *targets; }; @@ -3,7 +3,7 @@ * libhsync -- library for network deltas * $Id$ * - * Copyright (C) 2000 by Martin Pool <mbp@linuxcare.com.au> + * Copyright (C) 2000, 2001 by Martin Pool <mbp@linuxcare.com.au> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -27,7 +27,7 @@ | There are lumps in it. */ -#include "config.h" +#include <config.h> #include <unistd.h> #include <stdio.h> @@ -45,11 +45,9 @@ #include "trace.h" -int const hs_libhsync_file_offset_bits = SIZEOF_OFF_T * 8; +hs_trace_fn_t *hs_trace_impl = hs_trace_stderr; -hs_trace_fn_t *_hs_trace_impl = hs_trace_stderr; - -static int _hs_trace_level = LOG_INFO; +static int hs_trace_level = LOG_INFO; #ifdef HAVE_PROGRAM_INVOCATION_NAME # define MY_NAME program_invocation_short_name @@ -57,13 +55,13 @@ static int _hs_trace_level = LOG_INFO; # define MY_NAME "libhsync" #endif -static void _hs_log_va(int level, char const *fn, char const *fmt, va_list va); +static void hs_log_va(int level, char const *fn, char const *fmt, va_list va); /* Called by the application to set the destination of trace * information. */ void hs_trace_to(hs_trace_fn_t * new_impl) { - _hs_trace_impl = new_impl; + hs_trace_impl = new_impl; } @@ -71,14 +69,14 @@ hs_trace_to(hs_trace_fn_t * new_impl) void hs_trace_set_level(int level) { - _hs_trace_level = level; + hs_trace_level = level; } static void -_hs_log_va(int level, char const *fn, char const *fmt, va_list va) +hs_log_va(int level, char const *fn, char const *fmt, va_list va) { - if (_hs_trace_impl && level <= _hs_trace_level) { + if (hs_trace_impl && level <= hs_trace_level) { char buf[1000]; char full_buf[1000]; @@ -87,7 +85,7 @@ _hs_log_va(int level, char const *fn, char const *fmt, va_list va) snprintf(full_buf, sizeof full_buf - 1, "%s: %s: %s\n", MY_NAME, fn, buf); - _hs_trace_impl(level, full_buf); + hs_trace_impl(level, full_buf); } } @@ -96,12 +94,12 @@ _hs_log_va(int level, char const *fn, char const *fmt, va_list va) /* This function is called by a macro that prepends the calling function * name, etc. */ void -_hs_log0(int level, char const *fn, char const *fmt, ...) +hs_log0(int level, char const *fn, char const *fmt, ...) { va_list va; va_start(va, fmt); - _hs_log_va(level, fn, fmt, va); + hs_log_va(level, fn, fmt, va); va_end(va); } @@ -117,12 +115,12 @@ hs_trace_stderr(int UNUSED(level), char const *msg) /* This is called directly if the machine doesn't allow varargs * macros. */ void -_hs_fatal0(char const *s, ...) +hs_fatal0(char const *s, ...) { va_list va; va_start(va, s); - _hs_log_va(LOG_CRIT, PACKAGE, s, va); + hs_log_va(LOG_CRIT, PACKAGE, s, va); va_end(va); } @@ -130,12 +128,12 @@ _hs_fatal0(char const *s, ...) /* This is called directly if the machine doesn't allow varargs * macros. */ void -_hs_error0(char const *s, ...) +hs_error0(char const *s, ...) { va_list va; va_start(va, s); - _hs_log_va(LOG_ERR, PACKAGE, s, va); + hs_log_va(LOG_ERR, PACKAGE, s, va); va_end(va); } @@ -143,12 +141,12 @@ _hs_error0(char const *s, ...) /* This is called directly if the machine doesn't allow varargs * macros. */ void -_hs_trace0(char const *s, ...) +hs_trace0(char const *s, ...) { va_list va; va_start(va, s); - _hs_log_va(LOG_DEBUG, PACKAGE, s, va); + hs_log_va(LOG_DEBUG, PACKAGE, s, va); va_end(va); } @@ -161,9 +159,9 @@ _hs_trace0(char const *s, ...) int hs_supports_trace(void) { -#ifdef DO_HS_TRACE +#ifdef DOHS_TRACE return 1; #else return 0; -#endif /* !DO_HS_TRACE */ +#endif /* !DOHS_TRACE */ } @@ -36,21 +36,21 @@ * fatal terminates the whole process */ -void _hs_fatal0(char const *s, ...); -void _hs_error0(char const *s, ...); -void _hs_trace0(char const *s, ...); +void hs_fatal0(char const *s, ...); +void hs_error0(char const *s, ...); +void hs_trace0(char const *s, ...); #ifdef __GNUC__ -void _hs_log0(int level, char const *fn, char const *fmt, ...) +void hs_log0(int level, char const *fn, char const *fmt, ...) __attribute__ ((format(printf, 3, 4))); #ifdef DO_HS_TRACE -# define _hs_trace(fmt, arg...) \ - do { _hs_log0(LOG_DEBUG, __FUNCTION__, fmt , ##arg); \ +# define hs_trace(fmt, arg...) \ + do { hs_log0(LOG_DEBUG, __FUNCTION__, fmt , ##arg); \ } while (0) #else -# define _hs_trace(s, str...) +# define hs_trace(s, str...) #endif /* !DO_HS_TRACE */ /* @@ -62,18 +62,18 @@ void _hs_log0(int level, char const *fn, char const *fmt, ...) * whatever it's called. */ -#define _hs_log(l, s, str...) do { \ - _hs_log0(l, __FUNCTION__, (s) , ##str); \ +#define hs_log(l, s, str...) do { \ + hs_log0(l, __FUNCTION__, (s) , ##str); \ } while (0) -#define _hs_error(s, str...) do { \ - _hs_log0(LOG_ERR, __FUNCTION__, (s) , ##str); \ +#define hs_error(s, str...) do { \ + hs_log0(LOG_ERR, __FUNCTION__, (s) , ##str); \ } while (0) -#define _hs_fatal(s, str...) do { \ - _hs_log0(LOG_CRIT, __FUNCTION__, \ +#define hs_fatal(s, str...) do { \ + hs_log0(LOG_CRIT, __FUNCTION__, \ (s) , ##str); \ abort(); \ } while (0) @@ -81,12 +81,12 @@ void _hs_log0(int level, char const *fn, char const *fmt, ...) #else /************************* ! __GNUC__ */ -# define _hs_fatal _hs_fatal0 -# define _hs_error _hs_error0 +# define hs_fatal hs_fatal0 +# define hs_error hs_error0 # ifdef DO_HS_TRACE -# define _hs_trace _hs_trace0 -void _hs_log0(int, char const *, ...); +# define hs_trace hs_trace0 +void hs_log0(int, char const *, ...); # endif /* DO_HS_TRACE */ #endif /* ! __GNUC__ */ @@ -50,7 +50,7 @@ * possible. But for simplicity don't do that yet. */ -#include "config.h" +#include <config.h> #include <assert.h> #include <stdlib.h> @@ -66,7 +66,7 @@ const int HS_TUBE_TAG = 892138; -static void _hs_tube_catchup_literal(hs_stream_t *stream) +static void hs_tube_catchup_literal(hs_stream_t *stream) { int len, remain; hs_simpl_t *tube = stream->impl; @@ -79,7 +79,7 @@ static void _hs_tube_catchup_literal(hs_stream_t *stream) len = stream->avail_out; if (!stream->avail_out) { - _hs_trace("no output space available"); + hs_trace("no output space available"); return; } @@ -88,7 +88,7 @@ static void _hs_tube_catchup_literal(hs_stream_t *stream) stream->avail_out -= len; remain = tube->lit_len - len; - _hs_trace("transmitted %d literal bytes from tube, %d remain", + hs_trace("transmitted %d literal bytes from tube, %d remain", len, remain); if (remain > 0) { @@ -102,7 +102,7 @@ static void _hs_tube_catchup_literal(hs_stream_t *stream) } -static void _hs_tube_catchup_copy(hs_stream_t *stream) +static void hs_tube_catchup_copy(hs_stream_t *stream) { int copied; hs_simpl_t *tube = stream->impl; @@ -110,11 +110,11 @@ static void _hs_tube_catchup_copy(hs_stream_t *stream) assert(tube->lit_len == 0); assert(tube->copy_len > 0); - copied = _hs_stream_copy(stream, tube->copy_len); + copied = hs_stream_copy(stream, tube->copy_len); tube->copy_len -= copied; - _hs_trace("transmitted %d copy bytes from tube, %d remain", + hs_trace("transmitted %d copy bytes from tube, %d remain", copied, tube->copy_len); } @@ -124,11 +124,11 @@ static void _hs_tube_catchup_copy(hs_stream_t *stream) * Return HS_OK if the tube is now empty and ready to accept another * command, HS_BLOCKED if there is still stuff waiting to go out. */ -int _hs_tube_catchup(hs_stream_t *stream) +int hs_tube_catchup(hs_stream_t *stream) { hs_simpl_t *tube = stream->impl; if (tube->lit_len) - _hs_tube_catchup_literal(stream); + hs_tube_catchup_literal(stream); if (tube->lit_len) { /* there is still literal data queued, so we can't send @@ -137,7 +137,7 @@ int _hs_tube_catchup(hs_stream_t *stream) } if (tube->copy_len) - _hs_tube_catchup_copy(stream); + hs_tube_catchup_copy(stream); if (tube->copy_len) return HS_BLOCKED; @@ -149,7 +149,7 @@ int _hs_tube_catchup(hs_stream_t *stream) /* Check whether there is data in the tube waiting to go out. So if true * this basically means that the previous command has finished doing all its * output. */ -int _hs_tube_is_idle(hs_stream_t const *stream) +int hs_tube_is_idle(hs_stream_t const *stream) { hs_simpl_t *tube = stream->impl; return tube->lit_len == 0 && tube->copy_len == 0; @@ -161,7 +161,7 @@ int _hs_tube_is_idle(hs_stream_t const *stream) * output of the stream. We can only accept this request if there is * no copy command already pending. */ -void _hs_blow_copy(hs_stream_t *stream, int len) +void hs_blow_copy(hs_stream_t *stream, int len) { hs_simpl_t *tube = stream->impl; assert(tube->copy_len == 0); @@ -180,13 +180,13 @@ void _hs_blow_copy(hs_stream_t *stream, int len) * tube, because the literal data comes out first. */ void -_hs_blow_literal(hs_stream_t *stream, const void *buf, size_t len) +hs_blow_literal(hs_stream_t *stream, const void *buf, size_t len) { hs_simpl_t *tube = stream->impl; assert(tube->copy_len == 0); if (len > sizeof(tube->lit_buf) - tube->lit_len) { - _hs_fatal("tube popped when trying to blow %d literal bytes!", + hs_fatal("tube popped when trying to blow %d literal bytes!", len); } @@ -25,7 +25,7 @@ */ -#include "config.h" +#include <config.h> #include <stdlib.h> #include <stdio.h> @@ -34,33 +34,33 @@ #include "trace.h" void -_hs_bzero(void *buf, size_t size) +hs_bzero(void *buf, size_t size) { memset(buf, 0, size); } void * -_hs_alloc_struct0(size_t size, char const *name) +hs_alloc_struct0(size_t size, char const *name) { void *p; if (!(p = malloc(size))) { - _hs_fatal("couldn't allocate instance of %s", name); + hs_fatal("couldn't allocate instance of %s", name); } - _hs_bzero(p, size); + hs_bzero(p, size); return p; } void * -_hs_alloc(size_t size, char const *name) +hs_alloc(size_t size, char const *name) { void *p; if (!(p = malloc(size))) { - _hs_fatal("couldn't allocate instance of %s", name); + hs_fatal("couldn't allocate instance of %s", name); } return p; @@ -69,7 +69,7 @@ _hs_alloc(size_t size, char const *name) void -_hs_readintarg(char const *opt, char const *arg, int *out) +hs_readintarg(char const *opt, char const *arg, int *out) { char *o; @@ -22,20 +22,20 @@ */ -void * _hs_alloc(size_t size, char const *name); -void *_hs_alloc_struct0(size_t size, char const *name); +void * hs_alloc(size_t size, char const *name); +void *hs_alloc_struct0(size_t size, char const *name); -void _hs_bzero(void *buf, size_t size); +void hs_bzero(void *buf, size_t size); /* * Allocate and zero-fill an instance of TYPE. */ -#define _hs_alloc_struct(type) \ - ((type *) _hs_alloc_struct0(sizeof(type), #type)) +#define hs_alloc_struct(type) \ + ((type *) hs_alloc_struct0(sizeof(type), #type)) -void _hs_readintarg(char const *opt, char const *arg, int *out); +void hs_readintarg(char const *opt, char const *arg, int *out); @@ -3,7 +3,7 @@ * libhsync -- dynamic caching and delta update in HTTP * $Id$ * - * Copyright (C) 2000 by Martin Pool <mbp@linuxcare.com.au> + * Copyright (C) 2000, 2001 by Martin Pool <mbp@linuxcare.com.au> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -20,43 +20,26 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" +#include <config.h> #include <stdio.h> #include "hsync.h" -char const * const hs_libhsync_version = PACKAGE " " VERSION; - - -void hs_show_version(FILE *out, char const *program) -{ - fprintf(out, -"%s (%s) %s (%d-bit, trace %s, %s)\n" -"\n" -"Copyright (C) 1997-2000 by Martin Pool, Andrew Tridgell and others.\n" -"This is free software; see the GNU General Public Licence version 2.1\n" -"or later for copying conditions. There is NO warranty of any kind.\n" -, - program, PACKAGE, VERSION, - hs_libhsync_file_offset_bits, - hs_supports_trace() ? "enabled" : "disabled", - HS_CANONICAL_HOST - ); -} +char const hs_libhsync_version[] = (PACKAGE " " VERSION + " [" __DATE__ " " __TIME__ "]"); /* - * This little function is dedicated to Stephen Kapp and Reaper - * Technologies, who (apparently) tried to redistribute a modified - * version of GNU Keyring in violation of the licence and all laws of - * politeness and good taste. + * This little declaration is dedicated to Stephen Kapp and Reaper + * Technologies, who by all appearances redistributed a modified but + * unacknowledged version of GNU Keyring in violation of the licence + * and all laws of politeness and good taste. */ -void hs_show_licence(FILE *out) -{ - fprintf(out, -"Copyright (C) 1997-2000 by Martin Pool, Andrew Tridgell and others.\n" +char const hs_licence_string[] = +"http://rproxy.samba.org/\n" +"Copyright (C) 1997-2001 by Martin Pool, Andrew Tridgell and others.\n" "\n" "This program is free software; you can redistribute it and/or\n" "modify it under the terms of the GNU Lesser General Public License\n" @@ -70,6 +53,4 @@ void hs_show_licence(FILE *out) "\n" "You should have received a copy of the GNU Lesser General Public\n" "License along with this program; if not, write to the Free Software\n" -"Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n" - ); -} +"Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n"; @@ -3,7 +3,7 @@ * libhsync -- the library for network deltas * $Id$ * - * Copyright (C) 2000 by Martin Pool <mbp@linuxcare.com.au> + * Copyright (C) 2000, 2001 by Martin Pool <mbp@linuxcare.com.au> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -20,6 +20,15 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + /* + * Is it possible that software is not + * like anything else, that it is meant + * to be discarded: that the whole point + * is to always see it as a soap bubble? + * -- Alan Perlis + */ + + /* * whole.c -- This module contains routines for processing whole files @@ -28,162 +37,72 @@ * they are. */ -#include "config.h" +#include <config.h> #include <assert.h> #include <sys/types.h> #include <stdlib.h> #include <unistd.h> #include <stdio.h> -#include <sys/file.h> #include <string.h> -#include <syslog.h> + #include <errno.h> #include "trace.h" #include "fileutil.h" #include "hsync.h" #include "hsyncfile.h" +#include "job.h" +#include "buf.h" +#include "whole.h" -/* This should probably be a parameter to all functions instead, but - * I'm not sure I want to keep it. */ -extern int output_mode; - -enum hs_result -hs_rdiff_delta(int argc, char **argv) +/* + * Run a job continuously, with input to/from the two specified files. + * The job should already be set up. + */ +hs_result +hs_whole_run(hs_job_t *job, FILE *in_file, FILE *out_file) { - FILE *new_file, *sig_file, *delta_file; - - if (argc != 4) { - _hs_error("Delta operation needs three filenames: " - "SIGNATURE NEWFILE DELTA"); - return 1; - } - - _hs_fatal("no longer implemented"); -} + hs_stream_t *stream = job->stream; + hs_result result, iores; + hs_filebuf_t *in_fb, *out_fb; + int ending = 0; + in_fb = hs_filebuf_new(in_file, stream, hs_inbuflen); + out_fb = hs_filebuf_new(out_file, stream, hs_outbuflen); -enum hs_result hs_rdiff_md4(int argc, char **argv) -{ - unsigned char result[HS_MD4_LENGTH]; - char result_str[HS_MD4_LENGTH * 3]; - FILE *in_file; - char *inbuf = malloc(hs_inbuflen); - int len; - hs_mdfour_t md4; - - if (argc != 2) { - _hs_error("MD4 operation needs one filename"); - return 1; - } - - in_file = _hs_file_open(argv[1], O_RDONLY); - assert(inbuf); - - hs_mdfour_begin(&md4); - while (!feof(in_file)) { - len = fread(inbuf, hs_inbuflen, 1, in_file); - if (len < 0) { - _hs_fatal("%s: %s", argv[1], strerror(errno)); - return 1; - } - hs_mdfour_update(&md4, inbuf, len); - } - - hs_mdfour_result(&md4, result); - hs_hexify(result_str, result, HS_MD4_LENGTH); - - printf("%s\n", result_str); - - return 0; + do { + iores = hs_infilebuf_fill(in_fb); + if (iores != HS_OK) + return iores; + + result = hs_job_iter(job, ending); + if (result != HS_OK && result != HS_BLOCKED) + return result; + + iores = hs_outfilebuf_drain(out_fb); + if (iores != HS_OK) + return iores; + } while (result != HS_OK); + + return result; } - -enum hs_result hs_rdiff_patch(int argc, char *argv[]) +hs_result +hs_whole_signature(FILE *old_file, FILE *sig_file, size_t new_block_len, + size_t strong_len) { - FILE *old_file, *delta_file, *new_file; - char *outbuf; - HSFILE *patch; - enum hs_result result; - size_t len; - - if (argc != 4) { - _hs_error("Patch operation needs three filenames: " - "OLDFILE DELTA NEWFILE"); - return 1; - } - - old_file = _hs_file_open(argv[1], O_RDONLY); - delta_file = _hs_file_open(argv[2], O_RDONLY); - new_file = _hs_file_open(argv[3], output_mode); - - outbuf = malloc(hs_outbuflen); - assert(outbuf); - patch = hs_patch_open(old_file, delta_file); + hs_result result; + hs_job_t *job; + hs_stream_t stream; - do { - len = hs_outbuflen; - result = hs_patch_read(patch, outbuf, &len); - fwrite(outbuf, len, 1, new_file); - } while (result == HS_BLOCKED); - - if (result != HS_OK) - goto failed; - - return 0; - - failed: - _hs_error("patch failed: %s", hs_strerror(result)); - - return 1; -} + hs_stream_init(&stream); + job = hs_mksum_begin(&stream, new_block_len, strong_len); + result = hs_whole_run(job, old_file, sig_file); + hs_job_free(job); - -enum hs_result hs_rdiff_signature(int argc, char *argv[]) -{ - FILE *old_file, *sig_file; - char *inbuf; - HSFILE *mksum; - int len; - enum hs_result result; - - if (argc != 3) { - _hs_error("Signature operation needs two filenames"); - return 1; - } - - old_file = _hs_file_open(argv[1], O_RDONLY); - sig_file = _hs_file_open(argv[2], output_mode); - - inbuf = malloc(hs_inbuflen); - mksum = hs_mksum_open(sig_file, HS_DEFAULT_BLOCK_LEN, - HS_DEFAULT_STRONG_LEN); - - do { - len = fread(inbuf, 1, hs_inbuflen, old_file); - if (len < 0) { - _hs_error("%s: %s", argv[1], strerror(errno)); - return 1; - } - - _hs_trace("got %d bytes from input file", len); - result = hs_mksum_write(mksum, inbuf, len); - if (result != HS_BLOCKED && result != HS_OK) - goto failed; - } while (!feof(old_file)); - - result = hs_mksum_close(mksum); - if (result != HS_OK) - goto failed; - - return 0; - - failed: - _hs_error("signature failed: %s", hs_strerror(result)); - - return 1; + return result; } @@ -3,7 +3,7 @@ * libhsync -- the library for network deltas * $Id$ * - * Copyright (C) 2000 by Martin Pool <mbp@linuxcare.com.au> + * Copyright (C) 2001 by Martin Pool <mbp@linuxcare.com.au> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -20,8 +20,5 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -enum hs_result _hs_fill_from_file(hs_stream_t *stream, - char *buf, size_t buf_len, FILE *f); -enum hs_result _hs_drain_to_file(hs_stream_t *stream, - char *buf, size_t buf_len, FILE *f); +hs_result hs_whole_run(hs_job_t *job, FILE *in_file, FILE *out_file); |