From 7c91d5b7dfeca1188eedcf91d87635d8e506ca55 Mon Sep 17 00:00:00 2001 From: Wayne Davison Date: Fri, 25 Jul 2008 06:48:42 -0700 Subject: [PATCH] Improved the %C (checksum) escape to work for all files when the --checksum option is specified. --- log-checksum.diff | 223 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 171 insertions(+), 52 deletions(-) diff --git a/log-checksum.diff b/log-checksum.diff index 1eac37f..3d36e52 100644 --- a/log-checksum.diff +++ b/log-checksum.diff @@ -6,54 +6,163 @@ compute them. -- Matt McCutchen +To use this patch, run these commands for a successful build: + + patch -p1 0 + if (extra_len & (EXTRA_ROUNDING * EXTRA_LEN)) + extra_len = (extra_len | (EXTRA_ROUNDING * EXTRA_LEN)) + EXTRA_LEN; +@@ -1250,9 +1257,6 @@ struct file_struct *make_file(const char *fname, struct file_list *flist, + memcpy(bp + basename_len, linkname, linkname_len); + #endif + +- if (always_checksum && am_sender && S_ISREG(st.st_mode)) +- file_checksum(thisname, tmp_sum, st.st_size); +- + if (am_sender) + F_PATHNAME(file) = pathname; + else if (!pool) +@@ -1283,6 +1287,9 @@ struct file_struct *make_file(const char *fname, struct file_list *flist, + return NULL; + } + ++ if (sender_keeps_checksum && S_ISREG(st.st_mode)) ++ memcpy(F_SUM(file), tmp_sum, checksum_len); ++ + if (unsort_ndx) + F_NDX(file) = dir_count; + diff --git a/log.c b/log.c --- a/log.c +++ b/log.c -@@ -58,6 +58,9 @@ extern char curr_dir[]; +@@ -32,8 +32,10 @@ extern int local_server; + extern int quiet; + extern int module_id; + extern int msg_fd_out; ++extern int checksum_len; + extern int allow_8bit_chars; + extern int protocol_version; ++extern int always_checksum; + extern int preserve_times; + extern int uid_ndx; + extern int gid_ndx; +@@ -57,6 +59,7 @@ extern iconv_t ic_send, ic_recv; + extern char curr_dir[]; extern char *module_dir; extern unsigned int module_dirlen; - +extern char sender_file_sum[MAX_DIGEST_LEN]; -+extern int file_sum_len; -+ + static int log_initialised; static int logfile_was_closed; - static FILE *logfile_fp; -@@ -628,6 +631,19 @@ static void log_formatted(enum logcode code, const char *format, const char *op, +@@ -628,6 +631,28 @@ static void log_formatted(enum logcode code, const char *format, const char *op, snprintf(buf2, sizeof buf2, fmt, (double)b); n = buf2; break; + case 'C': -+ if (iflags & ITEM_TRANSFER && protocol_version >= 30) { -+ int i; -+ for (i = 0; i < file_sum_len; i++) -+ snprintf(buf2 + i*2, 3, "%02x", (int)CVAL(sender_file_sum,i)); ++ if (protocol_version >= 30 ++ && (iflags & ITEM_TRANSFER ++ || (always_checksum && S_ISREG(file->mode)))) { ++ int i, x1, x2; ++ const char *sum = iflags & ITEM_TRANSFER ++ ? sender_file_sum : F_SUM(file); ++ c = buf2 + checksum_len*2; ++ *c = '\0'; ++ for (i = checksum_len; --i >= 0; ) { ++ x1 = CVAL(sum, i); ++ x2 = x1 >> 4; ++ x1 &= 0xF; ++ *--c = x1 <= 9 ? x1 + '0' : x1 + 'a' - 10; ++ *--c = x2 <= 9 ? x2 + '0' : x2 + 'a' - 10; ++ } + } else { -+ int i; -+ for (i = 0; i < file_sum_len*2; i++) -+ buf2[i] = '?'; -+ buf2[i] = '\0'; ++ memset(buf2, ' ', checksum_len*2); ++ buf2[checksum_len*2] = '\0'; + } + n = buf2; + break; case 'i': if (iflags & ITEM_DELETED) { n = "*deleting "; +diff --git a/main.c b/main.c +--- a/main.c ++++ b/main.c +@@ -37,6 +37,7 @@ extern int am_generator; + extern int am_daemon; + extern int inc_recurse; + extern int blocking_io; ++extern int always_checksum; + extern int remove_source_files; + extern int need_messages_from_generator; + extern int kluge_around_eof; +@@ -68,6 +69,8 @@ extern int connect_timeout; + extern pid_t cleanup_child_pid; + extern unsigned int module_dirlen; + extern struct stats stats; ++extern char *stdout_format; ++extern char *logfile_format; + extern char *filesfrom_host; + extern char *partial_dir; + extern char *dest_option; +@@ -85,6 +88,7 @@ int local_server = 0; + int daemon_over_rsh = 0; + mode_t orig_umask = 0; + int batch_gen_fd = -1; ++int sender_keeps_checksum = 0; + + /* There's probably never more than at most 2 outstanding child processes, + * but set it higher, just in case. */ +@@ -1003,6 +1007,12 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[]) + + if (am_sender) { + keep_dirlinks = 0; /* Must be disabled on the sender. */ ++ ++ if (always_checksum ++ && (log_format_has(stdout_format, 'C') ++ || log_format_has(logfile_format, 'C'))) ++ sender_keeps_checksum = 1; ++ + if (protocol_version >= 30) + io_start_multiplex_out(); + else diff --git a/match.c b/match.c --- a/match.c +++ b/match.c -@@ -312,6 +312,10 @@ static void hash_search(int f,struct sum_struct *s, - map_ptr(buf, len-1, 1); - } +@@ -25,8 +25,10 @@ extern int verbose; + extern int do_progress; + extern int checksum_seed; + extern int append_mode; ++extern int checksum_len; -+/* Global variables to make the sender's checksum of a transferred file -+ * available to the code for log escape %C. */ + int updating_basis_file; +char sender_file_sum[MAX_DIGEST_LEN]; -+int file_sum_len = MD5_DIGEST_LEN; - /** - * Scan through a origin file, looking for sections that match -@@ -329,9 +333,6 @@ static void hash_search(int f,struct sum_struct *s, + static int false_alarms; + static int hash_hits; +@@ -329,9 +331,6 @@ static void hash_search(int f,struct sum_struct *s, **/ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len) { @@ -63,7 +172,7 @@ diff --git a/match.c b/match.c last_match = 0; false_alarms = 0; hash_hits = 0; -@@ -379,14 +380,26 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len) +@@ -379,18 +378,28 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len) matched(f, s, buf, len, -1); } @@ -71,30 +180,33 @@ diff --git a/match.c b/match.c - /* If we had a read error, send a bad checksum. */ - if (buf && buf->status != 0) - file_sum[0]++; -+ file_sum_len = sum_end(sender_file_sum); ++ if (sum_end(sender_file_sum) != checksum_len) ++ overflow_exit("checksum_len"); /* Impossible... */ + + /* If we had a read error, send a bad checksum. We use all bits -+ * off or all bits on so that a user logging checksums with %C -+ * can recognize a bad checksum. */ ++ * off as long as the checksum doesn't happen to be that, in ++ * which case we turn the last 0 bit into a 1. */ + if (buf && buf->status != 0) { + int i; -+ for (i = 0; i < file_sum_len; i++) { -+ if (sender_file_sum[i]) -+ break; -+ } -+ if (i < file_sum_len) -+ memset(sender_file_sum, 0, file_sum_len); -+ else -+ memset(sender_file_sum, 0xFF, file_sum_len); ++ for (i = 0; i < checksum_len && sender_file_sum[i] == 0; i++) {} ++ memset(sender_file_sum, 0, checksum_len); ++ if (i == checksum_len) ++ sender_file_sum[i-1]++; + } if (verbose > 2) rprintf(FINFO,"sending file_sum\n"); - write_buf(f, file_sum, sum_len); -+ write_buf(f, sender_file_sum, file_sum_len); ++ write_buf(f, sender_file_sum, checksum_len); - if (verbose > 2) +- if (verbose > 2) ++ if (verbose > 2) { rprintf(FINFO, "false_alarms=%d hash_hits=%d matches=%d\n", + false_alarms, hash_hits, matches); ++ } + + total_hash_hits += hash_hits; + total_false_alarms += false_alarms; diff --git a/options.c b/options.c --- a/options.c +++ b/options.c @@ -111,17 +223,23 @@ diff --git a/options.c b/options.c diff --git a/receiver.c b/receiver.c --- a/receiver.c +++ b/receiver.c -@@ -62,6 +62,9 @@ static int phase = 0, redoing = 0; - /* We're either updating the basis file or an identical copy: */ - static int updating_basis_or_equiv; - +@@ -46,6 +46,7 @@ extern int remove_source_files; + extern int append_mode; + extern int sparse_files; + extern int keep_partial; ++extern int checksum_len; + extern int checksum_seed; + extern int inplace; + extern int delay_updates; +@@ -54,6 +55,7 @@ extern struct stats stats; + extern char *tmpdir; + extern char *partial_dir; + extern char *basis_dir[]; +extern char sender_file_sum[MAX_DIGEST_LEN]; -+extern int file_sum_len; -+ - /* - * get_tmpname() - create a tmp filename for a given filename - * -@@ -165,10 +168,9 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r, + extern struct file_list *cur_flist, *first_flist, *dir_flist; + extern struct filter_list_struct daemon_filter_list; + +@@ -165,10 +167,9 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r, const char *fname, int fd, OFF_T total_size) { static char file_sum1[MAX_DIGEST_LEN]; @@ -133,22 +251,23 @@ diff --git a/receiver.c b/receiver.c OFF_T offset = 0; OFF_T offset2; char *data; -@@ -298,15 +300,15 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r, +@@ -298,15 +299,16 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r, exit_cleanup(RERR_FILEIO); } - sum_len = sum_end(file_sum1); -+ file_sum_len = sum_end(file_sum1); ++ if (sum_end(file_sum1) != checksum_len) ++ overflow_exit("checksum_len"); /* Impossible... */ if (mapbuf) unmap_file(mapbuf); - read_buf(f_in, file_sum2, sum_len); -+ read_buf(f_in, sender_file_sum, file_sum_len); ++ read_buf(f_in, sender_file_sum, checksum_len); if (verbose > 2) rprintf(FINFO,"got file_sum\n"); - if (fd != -1 && memcmp(file_sum1, file_sum2, sum_len) != 0) -+ if (fd != -1 && memcmp(file_sum1, sender_file_sum, file_sum_len) != 0) ++ if (fd != -1 && memcmp(file_sum1, sender_file_sum, checksum_len) != 0) return 0; return 1; } @@ -173,7 +292,7 @@ diff --git a/rsyncd.conf.yo b/rsyncd.conf.yo it() %B the permission bits of the file (e.g. rwxrwxrwt) - it() %c the checksum bytes received for this file (only when sending) + it() %c the total size of the block checksums received for the basis file (only when sending) -+ it() %C the full-file MD5 checksum of a transferred file (only for protocol 30 or above). ++ it() %C the full-file MD5 checksum if bf(--checksum) is enabled or a file was transferred (only for protocol 30 or above). it() %f the filename (long form on sender; no trailing "/") it() %G the gid of the file (decimal) or "DEFAULT" it() %h the remote host name -- 2.34.1