X-Git-Url: https://mattmccutchen.net/rsync/rsync-patches.git/blobdiff_plain/502d2817abc0387ff9f5bdd144b5e122b16dfcbc..0ef5abcbbb95298fa9faf1d3eb275a9e76e1d951:/checksum-xattr.diff diff --git a/checksum-xattr.diff b/checksum-xattr.diff index 1713186..bd6d3de 100644 --- a/checksum-xattr.diff +++ b/checksum-xattr.diff @@ -8,10 +8,11 @@ To use this patch, run these commands for a successful build: ./configure (optional if already run) make ---- old/flist.c -+++ new/flist.c -@@ -1193,7 +1193,8 @@ struct file_struct *make_file(const char - } +diff --git a/flist.c b/flist.c +--- a/flist.c ++++ b/flist.c +@@ -1286,7 +1286,8 @@ 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)) @@ -19,10 +20,11 @@ To use this patch, run these commands for a successful build: + && !get_sum_xattr(thisname, &st, tmp_sum)) file_checksum(thisname, tmp_sum, st.st_size); - F_PATHNAME(file) = pathname; ---- old/generator.c -+++ new/generator.c -@@ -627,7 +627,8 @@ int unchanged_file(char *fn, struct file + if (am_sender) +diff --git a/generator.c b/generator.c +--- a/generator.c ++++ b/generator.c +@@ -724,7 +724,8 @@ int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st) of the file time to determine whether to sync */ if (always_checksum > 0 && S_ISREG(st->st_mode)) { char sum[MAX_DIGEST_LEN]; @@ -32,26 +34,14 @@ To use this patch, run these commands for a successful build: return memcmp(sum, F_SUM(file), checksum_len) == 0; } ---- old/rsync.h -+++ new/rsync.h -@@ -1070,6 +1070,12 @@ isDigit(const char *ptr) - } - - static inline int -+isXDigit(const char *ptr) -+{ -+ return isxdigit(*(unsigned char *)ptr); -+} -+ -+static inline int - isPrint(const char *ptr) - { - return isprint(*(unsigned char *)ptr); ---- old/support/xsums -+++ new/support/xsums -@@ -0,0 +1,113 @@ -+#!/usr/bin/perl -w +diff --git a/support/xsums b/support/xsums +new file mode 100644 +--- /dev/null ++++ b/support/xsums +@@ -0,0 +1,119 @@ ++#!/usr/bin/perl +use strict; ++use warnings; + +use Getopt::Long; +use Cwd qw(abs_path cwd); @@ -116,11 +106,16 @@ To use this patch, run these commands for a successful build: + + foreach ($sum4, $sum5) { + if (defined $_) { -+ my($sum, $sz, $mt) = /^([0-9a-f]{32}) (\d+) (\d+)$/; -+ if (!defined($mt) || $sz != $size || $mt != $mtime) { -+ $_ = undef; ++ if (length($_) == 24) { ++ my($sz,$mt,$sum) = unpack('V2a16', $_); ++ if ($sz != ($size & 0xFFFFFFFF) ++ || $mt != ($mtime & 0xFFFFFFFF)) { ++ $_ = undef; ++ } else { ++ $_ = $sum; ++ } + } else { -+ $_ = $sum; ++ $_ = undef; + } + } + } @@ -136,13 +131,13 @@ To use this patch, run these commands for a successful build: + } + close IN; + -+ $sum4 = $md4->hexdigest; -+ $sum5 = $md5->hexdigest; -+ print " $sum4 $sum5" if $verbosity > 2; ++ $sum4 = $md4->digest; ++ $sum5 = $md5->digest; + print " $fn\n" if $verbosity > 1; + -+ setfattr($fn, 'rsync.%md4', "$sum4 $size $mtime"); -+ setfattr($fn, 'rsync.%md5', "$sum5 $size $mtime"); ++ my $szmt = pack('V2', $size, $mtime); # 32-bits, may truncate ++ setfattr($fn, 'rsync.%md4', $szmt.$sum4); ++ setfattr($fn, 'rsync.%md5', $szmt.$sum5); + #utime $mtime, $mtime, $fn; # Set mtime if it changes. + } + } @@ -163,94 +158,75 @@ To use this patch, run these commands for a successful build: + -h, --help Display this help message. +EOT +} ---- old/xattrs.c -+++ new/xattrs.c -@@ -31,6 +31,8 @@ extern int am_generator; - extern int read_only; +diff --git a/xattrs.c b/xattrs.c +--- a/xattrs.c ++++ b/xattrs.c +@@ -33,6 +33,8 @@ extern int read_only; extern int list_only; + extern int preserve_xattrs; extern int checksum_seed; +extern int checksum_len; +extern int protocol_version; #define RSYNC_XAL_INITIAL 5 #define RSYNC_XAL_LIST_INITIAL 100 -@@ -64,6 +66,9 @@ extern int checksum_seed; - #define XSTAT_ATTR RSYNC_PREFIX "%stat" - #define XSTAT_LEN ((int)sizeof XSTAT_ATTR - 1) +@@ -68,6 +70,10 @@ extern int checksum_seed; + #define XACC_ACL_ATTR RSYNC_PREFIX "%" XACC_ACL_SUFFIX + #define XDEF_ACL_SUFFIX "dacl" + #define XDEF_ACL_ATTR RSYNC_PREFIX "%" XDEF_ACL_SUFFIX ++#define MD4_SUFFIX "md4" ++#define MD4_ATTR RSYNC_PREFIX "%" MD4_SUFFIX ++#define MD5_SUFFIX "md5" ++#define MD5_ATTR RSYNC_PREFIX "%" MD5_SUFFIX -+#define MD4_ATTR RSYNC_PREFIX "%md4" -+#define MD5_ATTR RSYNC_PREFIX "%md5" -+ typedef struct { char *datum, *name; - size_t datum_len, name_len; -@@ -795,6 +800,71 @@ int set_xattr(const char *fname, const s - return rsync_xal_set(fname, lst + ndx, fnamecmp, sxp); +@@ -238,7 +244,9 @@ static int rsync_xal_get(const char *fname, item_list *xalp) + || (am_root < 0 + && (strcmp(name+RPRE_LEN+1, XSTAT_SUFFIX) == 0 + || strcmp(name+RPRE_LEN+1, XACC_ACL_SUFFIX) == 0 +- || strcmp(name+RPRE_LEN+1, XDEF_ACL_SUFFIX) == 0))) ++ || strcmp(name+RPRE_LEN+1, XDEF_ACL_SUFFIX) == 0 ++ || strcmp(name+RPRE_LEN+1, MD4_SUFFIX) == 0 ++ || strcmp(name+RPRE_LEN+1, MD5_SUFFIX) == 0))) + continue; + } + +@@ -894,6 +902,39 @@ int del_def_xattr_acl(const char *fname) } + #endif +int get_sum_xattr(const char *fname, STRUCT_STAT *stp, char *sum) +{ + const char *mdattr = protocol_version >= 30 + ? MD5_ATTR : MD4_ATTR; -+ char *cp, buf[256]; -+ OFF_T file_length; -+ time_t mtime; -+ int i, len; -+ -+ len = sys_lgetxattr(fname, mdattr, buf, sizeof buf - 1); -+ if (len >= (int)sizeof buf) { -+ len = -1; -+ errno = ERANGE; -+ } ++ char buf[256]; ++ uint32 file_length, mtime; ++ int len; ++ ++ len = sys_lgetxattr(fname, mdattr, buf, sizeof buf); + if (len < 0) { + if (errno == ENOTSUP || errno == ENOATTR) + return 0; -+ rsyserr(FERROR, errno, "failed to read xattr %s for %s", ++ rsyserr(FERROR_XFER, errno, "failed to read xattr %s for %s", + mdattr, full_fname(fname)); + return 0; + } -+ buf[len] = '\0'; -+ -+ for (i = 0, cp = buf; i < checksum_len*2; i++, cp++) { -+ int x; -+ if (isXDigit(cp)) { -+ if (isDigit(cp)) -+ x = *cp - '0'; -+ else -+ x = (*cp & 0xF) + 9; -+ } else { -+ cp = ""; -+ break; -+ } -+ if (i & 1) -+ sum[i/2] |= x; -+ else -+ sum[i/2] = x << 4; ++ if (len != 4 + 4 + checksum_len) { ++ rprintf(FERROR, "Corrupt %s xattr attached to %s -- skipping\n", ++ mdattr, full_fname(fname)); ++ return 0; + } -+ if (*cp++ != ' ') -+ goto parse_error; -+ -+ file_length = 0; -+ while (isDigit(cp)) -+ file_length = file_length * 10 + *cp++ - '0'; -+ if (*cp++ != ' ') -+ goto parse_error; + -+ mtime = 0; -+ while (isDigit(cp)) -+ mtime = mtime * 10 + *cp++ - '0'; -+ if (*cp) -+ goto parse_error; ++ file_length = IVAL(buf, 0); /* 32-bit values -- trunctions are OK */ ++ mtime = IVAL(buf, 4); + -+ if (stp->st_size != file_length || stp->st_mtime != mtime) ++ if ((uint32)stp->st_size != file_length || (uint32)stp->st_mtime != mtime) + return 0; + -+ return 1; ++ memcpy(sum, buf + 8, checksum_len); + -+ parse_error: -+ rprintf(FERROR, "Corrupt %s xattr attached to %s: \"%s\"\n", -+ mdattr, full_fname(fname), buf); -+ exit_cleanup(RERR_FILEIO); ++ return 1; +} + int get_stat_xattr(const char *fname, int fd, STRUCT_STAT *fst, STRUCT_STAT *xst)