extern int preserve_hard_links;
extern int update_only;
extern int opt_ignore_existing;
-extern int block_size;
extern int csum_length;
extern int ignore_times;
extern int size_only;
extern int io_timeout;
-extern int remote_version;
+extern int protocol_version;
extern int always_checksum;
extern int modify_window;
extern char *compare_dest;
}
}
file_checksum(fname,sum,st->st_size);
- if (remote_version < 21) {
+ if (protocol_version < 21) {
return (memcmp(sum,file->sum,2) == 0);
} else {
return (memcmp(sum,file->sum,MD4_SUM_LENGTH) == 0);
}
-/* use a larger block size for really big files */
-static int adapt_block_size(struct file_struct *file, int bsize)
-{
- int ret;
-
- if (bsize != BLOCK_SIZE) return bsize;
-
- ret = file->length / (10000); /* rough heuristic */
- ret = ret & ~15; /* multiple of 16 */
- if (ret < bsize) ret = bsize;
- if (ret > CHUNK_SIZE/2) ret = CHUNK_SIZE/2;
- return ret;
-}
-
-
/*
* NULL sum_struct means we have no checksums
- */
+ */
void write_sum_head(int f, struct sum_struct *sum)
{
write_int(f, sum->count);
write_int(f, sum->blength);
- if (remote_version >= 27)
+ if (protocol_version >= 27)
write_int(f, sum->s2length);
write_int(f, sum->remainder);
}
+/*
+ * set (initialize) the size entries in the per-file sum_struct
+ * calulating dynamic block ans checksum sizes.
+ *
+ * This is only called from generate_and_send_sums() but is a seperate
+ * function to encapsulate the logic.
+ *
+ * The block size is a rounded square root of file length.
+ *
+ * The checksum size is determined according to:
+ * blocksum_bits = BLOCKSUM_EXP + 2*log2(file_len) - log2(block_len)
+ * provided by Donovan Baarda which gives a probability of rsync
+ * algorithm corrupting data and falling back using the whole md4
+ * checksums.
+ *
+ * This might be made one of several selectable heuristics.
+ */
+
+static void sum_sizes_sqroot(struct sum_struct *sum, uint64 len)
+{
+ extern int block_size;
+ int blength, s2length, b;
+ uint32 c;
+ uint64 l;
+
+ if (block_size) {
+ blength = block_size;
+ } else if (len <= BLOCK_SIZE * BLOCK_SIZE) {
+ blength = BLOCK_SIZE;
+ } else {
+ l = len;
+ c = 1;
+ while (l >>= 2) {
+ c <<= 1;
+ }
+ blength = 0;
+ do {
+ blength |= c;
+ if (len < (uint64)blength * blength)
+ blength &= ~c;
+ c >>= 1;
+ } while (c >= 8); /* round to multiple of 8 */
+ blength = MAX(blength, BLOCK_SIZE);
+ }
+ if (protocol_version < 27) {
+ s2length = csum_length;
+ } else if (csum_length == SUM_LENGTH) {
+ s2length = SUM_LENGTH;
+ } else {
+ b = BLOCKSUM_BIAS;
+ l = len;
+ while (l >>= 1) {
+ b += 2;
+ }
+ c = blength;
+ while (c >>= 1 && b) {
+ b--;
+ }
+ s2length = (b + 1 - 32 + 7) / 8; /* add a bit,
+ * subtract rollsum,
+ * round up
+ * --optimize in compiler--
+ */
+ s2length = MAX(s2length, csum_length);
+ s2length = MIN(s2length, SUM_LENGTH);
+ }
+
+ sum->flength = len;
+ sum->blength = blength;
+ sum->s2length = s2length;
+ sum->count = (len + (blength - 1)) / blength;
+ sum->remainder = (len % blength);
+
+ if (sum->count && verbose > 2) {
+ rprintf(FINFO, "count=%ld rem=%ld blength=%ld s2length=%ld flength=%.0f\n",
+ (long) sum->count, (long) sum->remainder,
+ (long) sum->blength, (long) sum->s2length,
+ (double) sum->flength);
+ }
+}
/**
* Perhaps we want to just send an empty checksum set for this file,
*
* Generate approximately one checksum every block_len bytes.
*/
-static void generate_and_send_sums(struct map_struct *buf, OFF_T len,
- int block_len, int f_out)
+static void generate_and_send_sums(struct map_struct *buf, OFF_T len, int f_out)
{
size_t i;
struct sum_struct sum;
OFF_T offset = 0;
- sum.count = (len + (block_len - 1)) / block_len;
- sum.remainder = (len % block_len);
- sum.blength = block_len;
- sum.flength = len;
- sum.s2length = csum_length;
- /* not needed here sum.sums = NULL; */
-
- if (sum.count && verbose > 3) {
- rprintf(FINFO, "count=%ld rem=%ld n=%ld flength=%.0f\n",
- (long) sum.count, (long) sum.remainder,
- (long) sum.blength, (double) sum.flength);
- }
+ sum_sizes_sqroot(&sum, len);
write_sum_head(f_out, &sum);
for (i = 0; i < sum.count; i++) {
- int n1 = MIN(len, block_len);
+ int n1 = MIN(len, sum.blength);
char *map = map_ptr(buf, offset, n1);
uint32 sum1 = get_checksum1(map, n1);
char sum2[SUM_LENGTH];
if (verbose > 3) {
rprintf(FINFO,
- "chunk[%d] offset=%.0f len=%d sum1=%08lx\n",
- i, (double) offset, n1, (unsigned long) sum1);
+ "chunk[%ld] offset=%.0f len=%d sum1=%08lx\n",
+ (long)i,(double)offset,n1,(unsigned long)sum1);
}
write_int(f_out, sum1);
write_buf(f_out, sum2, sum.s2length);
if (dry_run) return; /* XXXX -- might cause inaccuracies?? -- mbp */
if (statret == 0 && !S_ISDIR(st.st_mode)) {
if (robust_unlink(fname) != 0) {
- rprintf(FERROR, RSYNC_NAME
- ": recv_generator: unlink \"%s\" to make room for directory: %s\n",
- fname,strerror(errno));
+ rprintf(FERROR,
+ "recv_generator: unlink %s to make room for directory: %s\n",
+ full_fname(fname), strerror(errno));
return;
}
statret = -1;
if (!(relative_paths && errno==ENOENT &&
create_directory_path(fname, orig_umask)==0 &&
do_mkdir(fname,file->mode)==0)) {
- rprintf(FERROR, RSYNC_NAME ": recv_generator: mkdir \"%s\": %s (2)\n",
- fname,strerror(errno));
+ rprintf(FERROR, "recv_generator: mkdir %s failed: %s\n",
+ full_fname(fname), strerror(errno));
}
}
/* f_out is set to -1 when doing final directory
if (safe_symlinks && unsafe_symlink(file->link, fname)) {
if (verbose) {
- rprintf(FINFO,"ignoring unsafe symlink \"%s\" -> \"%s\"\n",
- fname,file->link);
+ rprintf(FINFO, "ignoring unsafe symlink %s -> \"%s\"\n",
+ full_fname(fname), file->link);
}
return;
}
delete_file(fname);
}
if (do_symlink(file->link,fname) != 0) {
- rprintf(FERROR,RSYNC_NAME": symlink \"%s\" -> \"%s\": %s\n",
- fname,file->link,strerror(errno));
+ rprintf(FERROR, "symlink %s -> \"%s\" failed: %s\n",
+ full_fname(fname), file->link, strerror(errno));
} else {
set_perms(fname,file,NULL,0);
if (verbose) {
if (am_root && preserve_devices && IS_DEVICE(file->mode)) {
if (statret != 0 ||
st.st_mode != file->mode ||
- st.st_rdev != file->rdev) {
+ (DEV64_T)st.st_rdev != file->rdev) {
delete_file(fname);
if (verbose > 2)
rprintf(FINFO,"mknod(%s,0%o,0x%x)\n",
fname,(int)file->mode,(int)file->rdev);
if (do_mknod(fname,file->mode,file->rdev) != 0) {
- rprintf(FERROR,"mknod %s : %s\n",fname,strerror(errno));
+ rprintf(FERROR, "mknod %s failed: %s\n",
+ full_fname(fname), strerror(errno));
} else {
set_perms(fname,file,NULL,0);
if (verbose)
if (errno == ENOENT) {
write_int(f_out,i);
if (!dry_run) write_sum_head(f_out, NULL);
- } else {
- if (verbose > 1)
- rprintf(FERROR, RSYNC_NAME
- ": recv_generator failed to open \"%s\": %s\n",
- fname, strerror(errno));
+ } else if (verbose > 1) {
+ rprintf(FERROR,
+ "recv_generator: failed to open %s: %s\n",
+ full_fname(fname), strerror(errno));
}
return;
}
fd = do_open(fnamecmp, O_RDONLY, 0);
if (fd == -1) {
- rprintf(FERROR,RSYNC_NAME": failed to open \"%s\", continuing : %s\n",fnamecmp,strerror(errno));
+ rprintf(FERROR, "failed to open %s, continuing: %s\n",
+ full_fname(fnamecmp), strerror(errno));
/* pretend the file didn't exist */
write_int(f_out,i);
write_sum_head(f_out, NULL);
rprintf(FINFO, "generating and sending sums for %d\n", i);
write_int(f_out,i);
- generate_and_send_sums(buf, st.st_size,
- adapt_block_size(file, block_size), f_out);
+ generate_and_send_sums(buf, st.st_size, f_out);
close(fd);
if (buf) unmap_file(buf);