Mention option in the man-page.
[rsync/rsync-patches.git] / log-checksum.diff
CommitLineData
7ce3d7e0
WD
1This patch to rsync adds a %C log escape that expands to the sender's
2post-transfer checksum of a file for protocol 30 or above. This way, if
3you need the MD5 checksums of transferred files, you can have rsync log
4them instead of spending extra processor time on a separate command to
5compute them.
6
7-- Matt McCutchen <hashproduct@gmail.com>
8
9--- old/log.c
10+++ new/log.c
11@@ -55,6 +55,9 @@ extern char curr_dir[];
12 extern char *module_dir;
13 extern unsigned int module_dirlen;
14
15+extern char sender_file_sum[MAX_DIGEST_LEN];
16+extern int file_sum_len;
17+
18 static int log_initialised;
19 static int logfile_was_closed;
20 static FILE *logfile_fp;
21@@ -610,6 +613,19 @@ static void log_formatted(enum logcode c
22 snprintf(buf2, sizeof buf2, fmt, (double)b);
23 n = buf2;
24 break;
25+ case 'C':
26+ if (iflags & ITEM_TRANSFER && protocol_version >= 30) {
27+ int i;
28+ for (i = 0; i < file_sum_len; i++)
29+ snprintf(buf2 + i*2, 3, "%02x", (int)CVAL(sender_file_sum,i));
30+ } else {
31+ int i;
32+ for (i = 0; i < file_sum_len*2; i++)
33+ buf2[i] = '?';
34+ buf2[i] = '\0';
35+ }
36+ n = buf2;
37+ break;
38 case 'i':
39 if (iflags & ITEM_DELETED) {
40 n = "*deleting";
41--- old/match.c
42+++ new/match.c
43@@ -286,6 +286,10 @@ static void hash_search(int f,struct sum
44 map_ptr(buf, len-1, 1);
45 }
46
47+/* Global variables to make the sender's checksum of a transferred file
48+ * available to the code for log escape %C. */
49+char sender_file_sum[MAX_DIGEST_LEN];
50+int file_sum_len = MD5_DIGEST_LEN;
51
52 /**
53 * Scan through a origin file, looking for sections that match
54@@ -303,9 +307,6 @@ static void hash_search(int f,struct sum
55 **/
56 void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
57 {
58- char file_sum[MAX_DIGEST_LEN];
59- int sum_len;
60-
61 last_match = 0;
62 false_alarms = 0;
63 hash_hits = 0;
64@@ -353,14 +354,26 @@ void match_sums(int f, struct sum_struct
65 matched(f, s, buf, len, -1);
66 }
67
68- sum_len = sum_end(file_sum);
69- /* If we had a read error, send a bad checksum. */
70- if (buf && buf->status != 0)
71- file_sum[0]++;
72+ file_sum_len = sum_end(sender_file_sum);
73+
74+ /* If we had a read error, send a bad checksum. We use all bits
75+ * off or all bits on so that a user logging checksums with %C
76+ * can recognize a bad checksum. */
77+ if (buf && buf->status != 0) {
78+ int i;
79+ for (i = 0; i < file_sum_len; i++) {
80+ if (sender_file_sum[i])
81+ break;
82+ }
83+ if (i < file_sum_len)
84+ memset(sender_file_sum, 0, file_sum_len);
85+ else
86+ memset(sender_file_sum, 0xFF, file_sum_len);
87+ }
88
89 if (verbose > 2)
90 rprintf(FINFO,"sending file_sum\n");
91- write_buf(f, file_sum, sum_len);
92+ write_buf(f, sender_file_sum, file_sum_len);
93
94 if (verbose > 2)
95 rprintf(FINFO, "false_alarms=%d hash_hits=%d matches=%d\n",
96--- old/options.c
97+++ new/options.c
98@@ -1439,7 +1439,8 @@ int parse_arguments(int *argc, const cha
99 else if (log_format_has(stdout_format, 'i'))
100 stdout_format_has_i = itemize_changes | 1;
101 if (!log_format_has(stdout_format, 'b')
102- && !log_format_has(stdout_format, 'c'))
103+ && !log_format_has(stdout_format, 'c')
104+ && !log_format_has(stdout_format, 'C'))
105 log_before_transfer = !am_server;
106 } else if (itemize_changes) {
107 stdout_format = "%i %n%L";
108--- old/receiver.c
109+++ new/receiver.c
110@@ -62,6 +62,9 @@ static int phase = 0, redoing = 0;
111 /* We're either updating the basis file or an identical copy: */
112 static int updating_basis;
113
114+extern char sender_file_sum[MAX_DIGEST_LEN];
115+extern int file_sum_len;
116+
117 /*
118 * get_tmpname() - create a tmp filename for a given filename
119 *
120@@ -128,10 +131,9 @@ static int receive_data(int f_in, char *
121 const char *fname, int fd, OFF_T total_size)
122 {
123 static char file_sum1[MAX_DIGEST_LEN];
124- static char file_sum2[MAX_DIGEST_LEN];
125 struct map_struct *mapbuf;
126 struct sum_struct sum;
127- int32 len, sum_len;
128+ int32 len;
129 OFF_T offset = 0;
130 OFF_T offset2;
131 char *data;
132@@ -261,15 +263,15 @@ static int receive_data(int f_in, char *
133 exit_cleanup(RERR_FILEIO);
134 }
135
136- sum_len = sum_end(file_sum1);
137+ file_sum_len = sum_end(file_sum1);
138
139 if (mapbuf)
140 unmap_file(mapbuf);
141
142- read_buf(f_in, file_sum2, sum_len);
143+ read_buf(f_in, sender_file_sum, file_sum_len);
144 if (verbose > 2)
145 rprintf(FINFO,"got file_sum\n");
146- if (fd != -1 && memcmp(file_sum1, file_sum2, sum_len) != 0)
147+ if (fd != -1 && memcmp(file_sum1, sender_file_sum, file_sum_len) != 0)
148 return 0;
149 return 1;
150 }
151--- old/rsync.yo
152+++ new/rsync.yo
153@@ -1970,7 +1970,7 @@ by the server and defaults to the curren
154 is used to set a specific checksum seed, which is useful for
155 applications that want repeatable block and file checksums, or
156 in the case where the user wants a more random checksum seed.
157-Note that setting NUM to 0 causes rsync to use the default of code(time())
158+Setting NUM to 0 causes rsync to use the default of code(time())
159 for checksum seed.
160 enddit()
161
162--- old/rsyncd.conf.yo
163+++ new/rsyncd.conf.yo
164@@ -421,7 +421,8 @@ quote(itemization(
165 it() %a the remote IP address
166 it() %b the number of bytes actually transferred
167 it() %B the permission bits of the file (e.g. rwxrwxrwt)
168- it() %c the checksum bytes received for this file (only when sending)
169+ it() %c the total size of the block checksums received for the basis file (only when sending)
170+ it() %C the full-file MD5 checksum of a transferred file (only for protocol 30 or above).
171 it() %f the filename (long form on sender; no trailing "/")
172 it() %G the gid of the file (decimal) or "DEFAULT"
173 it() %h the remote host name