From aaa3a4e3d0e41e0ae55daa1efe1a647c6c363f59 Mon Sep 17 00:00:00 2001 From: Ahmed Ammar Date: Tue, 24 Oct 2017 03:07:14 +0200 Subject: [PATCH 1/5] Compilation fixes. --- c/librcksum/md4.h | 1 + c/libzsync/zsync.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/c/librcksum/md4.h b/c/librcksum/md4.h index e90603a..f2a23d4 100644 --- a/c/librcksum/md4.h +++ b/c/librcksum/md4.h @@ -17,6 +17,7 @@ #define _MD4_H_ #include "zsglobal.h" +#include #ifdef HAVE_INTTYPES_H #include diff --git a/c/libzsync/zsync.c b/c/libzsync/zsync.c index 793a426..783c349 100644 --- a/c/libzsync/zsync.c +++ b/c/libzsync/zsync.c @@ -116,7 +116,7 @@ struct zsync_state { }; static int zsync_read_blocksums(struct zsync_state *zs, FILE * f, - int rsum_bytes, int checksum_bytes, + int rsum_bytes, unsigned int checksum_bytes, int seq_matches); static int zsync_sha1(struct zsync_state *zs, int fh); static int zsync_recompress(struct zsync_state *zs); From c0a8b2c92ed65dfd99df9260293dd10873ca294b Mon Sep 17 00:00:00 2001 From: Ahmed Ammar Date: Tue, 24 Oct 2017 17:13:01 +0200 Subject: [PATCH 2/5] Add zsync_file_length() function. --- c/libzsync/zsync.c | 4 ++++ c/libzsync/zsync.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/c/libzsync/zsync.c b/c/libzsync/zsync.c index 783c349..1a93e33 100644 --- a/c/libzsync/zsync.c +++ b/c/libzsync/zsync.c @@ -523,6 +523,10 @@ static char *zsync_cur_filename(struct zsync_state *zs) { return zs->cur_filename; } +off_t zsync_file_length(struct zsync_state *zs) { + return zs->filelen; +} + /* zsync_rename_file(self, filename) * Tell libzsync to move the local copy of the target (or under construction * target) to the given filename. */ diff --git a/c/libzsync/zsync.h b/c/libzsync/zsync.h index 06ae222..c191ae9 100644 --- a/c/libzsync/zsync.h +++ b/c/libzsync/zsync.h @@ -25,6 +25,8 @@ int zsync_hint_decompress(const struct zsync_state*); /* zsync_filename - return the suggested filename from the .zsync file */ char* zsync_filename(const struct zsync_state*); +/* zsync_file_length - return the file length from the .zsync file */ +off_t zsync_file_length(struct zsync_state*); /* zsync_mtime - return the suggested mtime from the .zsync file */ time_t zsync_mtime(const struct zsync_state*); From 029e6111199e107a1f6f4ea6675747075edf1727 Mon Sep 17 00:00:00 2001 From: Ahmed Ammar Date: Thu, 26 Oct 2017 04:19:09 +0200 Subject: [PATCH 3/5] Don't build broken librckrum binary. --- c/librcksum/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c/librcksum/Makefile.am b/c/librcksum/Makefile.am index 0216e49..fd63dad 100644 --- a/c/librcksum/Makefile.am +++ b/c/librcksum/Makefile.am @@ -3,7 +3,7 @@ noinst_LIBRARIES = librcksum.a TESTS = md4test rsumtest -noinst_PROGRAMS = md4test rsumtest +#noinst_PROGRAMS = md4test rsumtest md4test_SOURCES = md4test.c md4.h md4.c rsumtest_SOURCES = rsum.c rsumtest.c hash.c range.c state.c md4.c ../progress.c From df596fd2e28532c31539ff9deefcc448550942eb Mon Sep 17 00:00:00 2001 From: Ahmed Ammar Date: Wed, 25 Oct 2017 03:19:45 +0200 Subject: [PATCH 4/5] Use md5 instead of md4. --- c/librcksum/Makefile.am | 2 +- c/librcksum/md5.c | 291 ++++++++++++++++++++++++++++++++++++++++ c/librcksum/md5.h | 38 ++++++ c/librcksum/rsum.c | 10 +- c/libzsync/zsync.c | 2 +- c/make.c | 2 +- 6 files changed, 337 insertions(+), 8 deletions(-) create mode 100644 c/librcksum/md5.c create mode 100644 c/librcksum/md5.h diff --git a/c/librcksum/Makefile.am b/c/librcksum/Makefile.am index fd63dad..58e2d96 100644 --- a/c/librcksum/Makefile.am +++ b/c/librcksum/Makefile.am @@ -7,4 +7,4 @@ TESTS = md4test rsumtest md4test_SOURCES = md4test.c md4.h md4.c rsumtest_SOURCES = rsum.c rsumtest.c hash.c range.c state.c md4.c ../progress.c -librcksum_a_SOURCES = internal.h rcksum.h md4.h rsum.c hash.c state.c range.c md4.c +librcksum_a_SOURCES = internal.h rcksum.h md4.h md5.h rsum.c hash.c state.c range.c md4.c md5.c diff --git a/c/librcksum/md5.c b/c/librcksum/md5.c new file mode 100644 index 0000000..0d9feef --- /dev/null +++ b/c/librcksum/md5.c @@ -0,0 +1,291 @@ +/* + * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. + * MD5 Message-Digest Algorithm (RFC 1321). + * + * Homepage: + * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 + * + * Author: + * Alexander Peslyak, better known as Solar Designer + * + * This software was written by Alexander Peslyak in 2001. No copyright is + * claimed, and the software is hereby placed in the public domain. + * In case this attempt to disclaim copyright and place the software in the + * public domain is deemed null and void, then the software is + * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the + * general public under the following terms: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + * + * (This is a heavily cut-down "BSD license".) + * + * This differs from Colin Plumb's older public domain implementation in that + * no exactly 32-bit integer data type is required (any 32-bit or wider + * unsigned integer data type will do), there's no compile-time endianness + * configuration, and the function prototypes match OpenSSL's. No code from + * Colin Plumb's implementation has been reused; this comment merely compares + * the properties of the two independent implementations. + * + * The primary goals of this implementation are portability and ease of use. + * It is meant to be fast, but not as fast as possible. Some known + * optimizations are not included to reduce source code size and avoid + * compile-time configuration. + */ + +#ifndef HAVE_OPENSSL + +#include + +#include "md5.h" + +/* + * The basic MD5 functions. + * + * F and G are optimized compared to their RFC 1321 definitions for + * architectures that lack an AND-NOT instruction, just like in Colin Plumb's + * implementation. + */ +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) +#define H(x, y, z) (((x) ^ (y)) ^ (z)) +#define H2(x, y, z) ((x) ^ ((y) ^ (z))) +#define I(x, y, z) ((y) ^ ((x) | ~(z))) + +/* + * The MD5 transformation for all four rounds. + */ +#define STEP(f, a, b, c, d, x, t, s) \ + (a) += f((b), (c), (d)) + (x) + (t); \ + (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ + (a) += (b); + +/* + * SET reads 4 input bytes in little-endian byte order and stores them in a + * properly aligned word in host byte order. + * + * The check for little-endian architectures that tolerate unaligned memory + * accesses is just an optimization. Nothing will break if it fails to detect + * a suitable architecture. + * + * Unfortunately, this optimization may be a C strict aliasing rules violation + * if the caller's data buffer has effective type that cannot be aliased by + * MD5_u32plus. In practice, this problem may occur if these MD5 routines are + * inlined into a calling function, or with future and dangerously advanced + * link-time optimizations. For the time being, keeping these MD5 routines in + * their own translation unit avoids the problem. + */ +#if defined(__i386__) || defined(__x86_64__) || defined(__vax__) +#define SET(n) \ + (*(MD5_u32plus *)&ptr[(n) * 4]) +#define GET(n) \ + SET(n) +#else +#define SET(n) \ + (ctx->block[(n)] = \ + (MD5_u32plus)ptr[(n) * 4] | \ + ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \ + ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \ + ((MD5_u32plus)ptr[(n) * 4 + 3] << 24)) +#define GET(n) \ + (ctx->block[(n)]) +#endif + +/* + * This processes one or more 64-byte data blocks, but does NOT update the bit + * counters. There are no alignment requirements. + */ +static const void *body(MD5_CTX *ctx, const void *data, unsigned long size) +{ + const unsigned char *ptr; + MD5_u32plus a, b, c, d; + MD5_u32plus saved_a, saved_b, saved_c, saved_d; + + ptr = (const unsigned char *)data; + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + + do { + saved_a = a; + saved_b = b; + saved_c = c; + saved_d = d; + +/* Round 1 */ + STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7) + STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12) + STEP(F, c, d, a, b, SET(2), 0x242070db, 17) + STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22) + STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7) + STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12) + STEP(F, c, d, a, b, SET(6), 0xa8304613, 17) + STEP(F, b, c, d, a, SET(7), 0xfd469501, 22) + STEP(F, a, b, c, d, SET(8), 0x698098d8, 7) + STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12) + STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17) + STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22) + STEP(F, a, b, c, d, SET(12), 0x6b901122, 7) + STEP(F, d, a, b, c, SET(13), 0xfd987193, 12) + STEP(F, c, d, a, b, SET(14), 0xa679438e, 17) + STEP(F, b, c, d, a, SET(15), 0x49b40821, 22) + +/* Round 2 */ + STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5) + STEP(G, d, a, b, c, GET(6), 0xc040b340, 9) + STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14) + STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20) + STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5) + STEP(G, d, a, b, c, GET(10), 0x02441453, 9) + STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14) + STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20) + STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5) + STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9) + STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14) + STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20) + STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5) + STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9) + STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14) + STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20) + +/* Round 3 */ + STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4) + STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11) + STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16) + STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23) + STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4) + STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11) + STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16) + STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23) + STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4) + STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11) + STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16) + STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23) + STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4) + STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11) + STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16) + STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23) + +/* Round 4 */ + STEP(I, a, b, c, d, GET(0), 0xf4292244, 6) + STEP(I, d, a, b, c, GET(7), 0x432aff97, 10) + STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15) + STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21) + STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6) + STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10) + STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15) + STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21) + STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6) + STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10) + STEP(I, c, d, a, b, GET(6), 0xa3014314, 15) + STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21) + STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6) + STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10) + STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15) + STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21) + + a += saved_a; + b += saved_b; + c += saved_c; + d += saved_d; + + ptr += 64; + } while (size -= 64); + + ctx->a = a; + ctx->b = b; + ctx->c = c; + ctx->d = d; + + return ptr; +} + +void MD5_Init(MD5_CTX *ctx) +{ + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + + ctx->lo = 0; + ctx->hi = 0; +} + +void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size) +{ + MD5_u32plus saved_lo; + unsigned long used, available; + + saved_lo = ctx->lo; + if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) + ctx->hi++; + ctx->hi += size >> 29; + + used = saved_lo & 0x3f; + + if (used) { + available = 64 - used; + + if (size < available) { + memcpy(&ctx->buffer[used], data, size); + return; + } + + memcpy(&ctx->buffer[used], data, available); + data = (const unsigned char *)data + available; + size -= available; + body(ctx, ctx->buffer, 64); + } + + if (size >= 64) { + data = body(ctx, data, size & ~(unsigned long)0x3f); + size &= 0x3f; + } + + memcpy(ctx->buffer, data, size); +} + +#define OUT(dst, src) \ + (dst)[0] = (unsigned char)(src); \ + (dst)[1] = (unsigned char)((src) >> 8); \ + (dst)[2] = (unsigned char)((src) >> 16); \ + (dst)[3] = (unsigned char)((src) >> 24); + +void MD5_Final(unsigned char *result, MD5_CTX *ctx) +{ + unsigned long used, available; + + used = ctx->lo & 0x3f; + + ctx->buffer[used++] = 0x80; + + available = 64 - used; + + if (available < 8) { + memset(&ctx->buffer[used], 0, available); + body(ctx, ctx->buffer, 64); + used = 0; + available = 64; + } + + memset(&ctx->buffer[used], 0, available - 8); + + ctx->lo <<= 3; + OUT(&ctx->buffer[56], ctx->lo) + OUT(&ctx->buffer[60], ctx->hi) + + body(ctx, ctx->buffer, 64); + + OUT(&result[0], ctx->a) + OUT(&result[4], ctx->b) + OUT(&result[8], ctx->c) + OUT(&result[12], ctx->d) + + memset(ctx, 0, sizeof(*ctx)); +} + +#endif diff --git a/c/librcksum/md5.h b/c/librcksum/md5.h new file mode 100644 index 0000000..2dea077 --- /dev/null +++ b/c/librcksum/md5.h @@ -0,0 +1,38 @@ +/* + * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. + * MD5 Message-Digest Algorithm (RFC 1321). + * + * Homepage: + * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 + * + * Author: + * Alexander Peslyak, better known as Solar Designer + * + * This software was written by Alexander Peslyak in 2001. No copyright is + * claimed, and the software is hereby placed in the public domain. + * In case this attempt to disclaim copyright and place the software in the + * public domain is deemed null and void, then the software is + * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the + * general public under the following terms: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + * + * See md5.c for more information. + */ + +/* Any 32-bit or wider unsigned integer data type will do */ +typedef unsigned int MD5_u32plus; + +typedef struct { + MD5_u32plus lo, hi; + MD5_u32plus a, b, c, d; + unsigned char buffer[64]; + MD5_u32plus block[16]; +} MD5_CTX; + +void MD5_Init(MD5_CTX *ctx); +void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size); +void MD5_Final(unsigned char *result, MD5_CTX *ctx); diff --git a/c/librcksum/rsum.c b/c/librcksum/rsum.c index 15cda0a..faaf353 100644 --- a/c/librcksum/rsum.c +++ b/c/librcksum/rsum.c @@ -32,7 +32,7 @@ # include #endif -#include "md4.h" +#include "md5.h" #include "rcksum.h" #include "internal.h" /* TODO: decide how to handle progress; this is now being used by the client @@ -66,10 +66,10 @@ rcksum_calc_rsum_block(const unsigned char *data, size_t len) { * Returns the MD4 checksum (in checksum_buf) of the given data block */ void rcksum_calc_checksum(unsigned char *c, const unsigned char *data, size_t len) { - MD4_CTX ctx; - MD4Init(&ctx); - MD4Update(&ctx, data, len); - MD4Final(c, &ctx); + MD5_CTX ctx; + MD5_Init(&ctx); + MD5_Update(&ctx, data, len); + MD5_Final(c, &ctx); } #ifndef HAVE_PWRITE diff --git a/c/libzsync/zsync.c b/c/libzsync/zsync.c index 1a93e33..51192bf 100644 --- a/c/libzsync/zsync.c +++ b/c/libzsync/zsync.c @@ -178,7 +178,7 @@ struct zsync_state *zsync_begin(FILE * f) { if (p && *(p + 1) == ' ') { *p++ = 0; p++; - if (!strcmp(buf, "zsync")) { + if (!strcmp(buf, "zsync-md5")) { if (!strcmp(p, "0.0.4")) { fprintf(stderr, "This version of zsync is not compatible with zsync 0.0.4 streams.\n"); free(zs); diff --git a/c/make.c b/c/make.c index a5173cc..3bca926 100644 --- a/c/make.c +++ b/c/make.c @@ -822,7 +822,7 @@ int main(int argc, char **argv) { } /* Okay, start writing the zsync file */ - fprintf(fout, "zsync: " VERSION "\n"); + fprintf(fout, "zsync-md5: " VERSION "\n"); /* Lines we might include but which older clients can ignore */ if (do_recompress) { From be2e4e2b7743ee717b289fb78986f16f49c64120 Mon Sep 17 00:00:00 2001 From: Ahmed Ammar Date: Thu, 26 Oct 2017 04:18:15 +0200 Subject: [PATCH 5/5] Basic implementation for remote updates, zbyteranges will represent what needs to be sent to remote end-point. --- c/client.c | 4 ++-- c/librcksum/internal.h | 6 ++++++ c/librcksum/rcksum.h | 5 +++-- c/librcksum/rsum.c | 24 ++++++++++++++++-------- c/libzsync/zsync.c | 8 ++++---- c/libzsync/zsync.h | 3 ++- 6 files changed, 33 insertions(+), 17 deletions(-) diff --git a/c/client.c b/c/client.c index 2a2e4bf..385d6aa 100644 --- a/c/client.c +++ b/c/client.c @@ -95,7 +95,7 @@ void read_seed_file(struct zsync_state *z, const char *fname) { /* Give the contents to libzsync to read and find any useful * content */ - zsync_submit_source_file(z, f, !no_progress); + zsync_submit_source_file(z, f, !no_progress, false); /* Close and check for errors */ if (pclose(f) != 0) { @@ -116,7 +116,7 @@ void read_seed_file(struct zsync_state *z, const char *fname) { * is part of the target file. */ if (!no_progress) fprintf(stderr, "reading seed file %s: ", fname); - zsync_submit_source_file(z, f, !no_progress); + zsync_submit_source_file(z, f, !no_progress, false); /* And close */ if (fclose(f) != 0) { diff --git a/c/librcksum/internal.h b/c/librcksum/internal.h index 657d461..930eeb3 100644 --- a/c/librcksum/internal.h +++ b/c/librcksum/internal.h @@ -92,6 +92,12 @@ static inline zs_blockid get_HE_blockid(const struct rcksum_state *z, return e - z->blockhashes; } +/* From a file offset return the corresponding local file blockid */ +static inline zs_blockid get_L_blockid(struct rcksum_state *const z, off_t offset, int x) { + int lid = (offset + x) / z->blocksize; + return offset ? lid - z->context/z->blocksize : lid; +} + void add_to_ranges(struct rcksum_state *z, zs_blockid n); int already_got_block(struct rcksum_state *z, zs_blockid n); zs_blockid next_known_block(struct rcksum_state *rs, zs_blockid x); diff --git a/c/librcksum/rcksum.h b/c/librcksum/rcksum.h index 75d77c3..84e9dc9 100644 --- a/c/librcksum/rcksum.h +++ b/c/librcksum/rcksum.h @@ -17,6 +17,7 @@ /* This is the library interface. Very changeable at this stage. */ #include +#include struct rcksum_state; @@ -44,8 +45,8 @@ int rcksum_filehandle(struct rcksum_state* z); void rcksum_add_target_block(struct rcksum_state* z, zs_blockid b, struct rsum r, void* checksum); int rcksum_submit_blocks(struct rcksum_state* z, const unsigned char* data, zs_blockid bfrom, zs_blockid bto); -int rcksum_submit_source_data(struct rcksum_state* z, unsigned char* data, size_t len, off_t offset); -int rcksum_submit_source_file(struct rcksum_state* z, FILE* f, int progress); +int rcksum_submit_source_data(struct rcksum_state* z, unsigned char* data, size_t len, off_t offset, bool remote); +int rcksum_submit_source_file(struct rcksum_state* z, FILE* f, int progress, bool remote); /* This reads back in data which is already known. */ ssize_t rcksum_read_known_data(struct rcksum_state *z, unsigned char *buf, diff --git a/c/librcksum/rsum.c b/c/librcksum/rsum.c index faaf353..eb22c2c 100644 --- a/c/librcksum/rsum.c +++ b/c/librcksum/rsum.c @@ -185,7 +185,7 @@ int rcksum_submit_blocks(struct rcksum_state *const z, const unsigned char *data static int check_checksums_on_hash_chain(struct rcksum_state *const z, const struct hash_entry *e, const unsigned char *data, - int onlyone) { + int onlyone, bool write) { unsigned char md4sum[2][CHECKSUM_SIZE]; signed int done_md4 = -1; int got_blocks = 0; @@ -276,7 +276,7 @@ static int check_checksums_on_hash_chain(struct rcksum_state *const z, } /* Write out the matched blocks that we don't yet know */ - write_blocks(z, data, id, id + num_write_blocks - 1); + if (write) write_blocks(z, data, id, id + num_write_blocks - 1); got_blocks += num_write_blocks; } } @@ -304,7 +304,7 @@ static int check_checksums_on_hash_chain(struct rcksum_state *const z, * r[1] - rolling checksum of the next blocksize bytes of the buffer (if seq_matches > 1) */ int rcksum_submit_source_data(struct rcksum_state *const z, unsigned char *data, - size_t len, off_t offset) { + size_t len, off_t offset, bool remote) { /* The window in data[] currently being considered is [x, x+bs) */ int x = 0; int got_blocks = 0; /* Count the number of useful data blocks found. */ @@ -351,7 +351,10 @@ int rcksum_submit_source_data(struct rcksum_state *const z, unsigned char *data, * the target immediately after our previous hit. */ if (z->next_match && z->seq_matches > 1) { int thismatch; - if (0 != (thismatch = check_checksums_on_hash_chain(z, z->next_match, data + x, 1))) { + const struct hash_entry *e = z->next_match; + if (0 != (thismatch = check_checksums_on_hash_chain(z, z->next_match, data + x, 1, !remote))) { + if (remote && get_L_blockid(z, offset, x) == get_HE_blockid(z,e)) + add_to_ranges(z, get_L_blockid(z, offset, x) ); blocks_matched = 1; got_blocks += thismatch; } @@ -390,9 +393,14 @@ int rcksum_submit_source_data(struct rcksum_state *const z, unsigned char *data, /* Okay, we have a hash hit. Follow the hash chain and * check our block against all the entries. */ - thismatch = check_checksums_on_hash_chain(z, e, data + x, 0); - if (thismatch) + thismatch = check_checksums_on_hash_chain(z, e, data + x, 0, !remote); + if (thismatch) { + if (remote && get_L_blockid(z, offset, x) == get_HE_blockid(z,e)) { + add_to_ranges(z, get_L_blockid(z, offset, x)); + if (seq_matches) add_to_ranges(z, get_L_blockid(z, offset, x + z->blocksize)); + } blocks_matched = seq_matches; + } } } got_blocks += thismatch; @@ -463,7 +471,7 @@ static off_t get_file_size(FILE* f) { * identify any blocks of data in common with the target file. Blocks found are * written to our working target output. Progress reports if progress != 0 */ -int rcksum_submit_source_file(struct rcksum_state *z, FILE * f, int progress) { +int rcksum_submit_source_file(struct rcksum_state *z, FILE * f, int progress, bool remote) { /* Track progress */ int got_blocks = 0; off_t in = 0; @@ -521,7 +529,7 @@ int rcksum_submit_source_file(struct rcksum_state *z, FILE * f, int progress) { } /* Process the data in the buffer, and report progress */ - got_blocks += rcksum_submit_source_data(z, buf, len, start_in); + got_blocks += rcksum_submit_source_data(z, buf, len, start_in, remote); if (progress && in_mb != in / 1000000) { do_progress(p, 100.0 * in / size, in); in_mb = in / 1000000; diff --git a/c/libzsync/zsync.c b/c/libzsync/zsync.c index 51192bf..d3322fd 100644 --- a/c/libzsync/zsync.c +++ b/c/libzsync/zsync.c @@ -507,13 +507,13 @@ off_t *zsync_needed_byte_ranges(struct zsync_state * zs, int *num, int type) { } } -/* zsync_submit_source_file(self, FILE*, progress) +/* zsync_submit_source_file(self, FILE*, progress, remote) * Read the given stream, applying the rsync rolling checksum algorithm to * identify any blocks of data in common with the target file. Blocks found are * written to our local copy of the target in progress. Progress reports if - * progress != 0 */ -int zsync_submit_source_file(struct zsync_state *zs, FILE * f, int progress) { - return rcksum_submit_source_file(zs->rs, f, progress); + * progress != 0. Remote reporting enabled if remote == true */ +int zsync_submit_source_file(struct zsync_state *zs, FILE * f, int progress, bool remote) { + return rcksum_submit_source_file(zs->rs, f, progress, remote); } static char *zsync_cur_filename(struct zsync_state *zs) { diff --git a/c/libzsync/zsync.h b/c/libzsync/zsync.h index c191ae9..9753e06 100644 --- a/c/libzsync/zsync.h +++ b/c/libzsync/zsync.h @@ -12,6 +12,7 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * COPYING file for details. */ +#include struct zsync_state; @@ -51,7 +52,7 @@ void zsync_progress(const struct zsync_state* zs, long long* got, long long* tot /* zsync_submit_source_file - submit local file data to zsync */ -int zsync_submit_source_file(struct zsync_state* zs, FILE* f, int progress); +int zsync_submit_source_file(struct zsync_state* zs, FILE* f, int progress, bool remote); /* zsync_get_url - returns a URL from which to get needed data. * Returns NULL on failure, or a array of pointers to URLs.