From b7e8628c4bc66be139ae1a7efcb16034c146edb7 Mon Sep 17 00:00:00 2001 From: Wayne Davison Date: Sat, 27 Nov 2004 17:52:47 +0000 Subject: [PATCH] - Added support for --copy-dest, which behaves like --link-dest, but it copies the identical files instead of hard-linking them. - Added support for multiple --*-dest options. --- generator.c | 86 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 59 insertions(+), 27 deletions(-) diff --git a/generator.c b/generator.c index 248c32a8..f2b9cb04 100644 --- a/generator.c +++ b/generator.c @@ -46,7 +46,8 @@ extern int io_timeout; extern int protocol_version; extern int always_checksum; extern char *partial_dir; -extern char *compare_dest; +extern char *basis_dir[]; +extern int copy_dest; extern int link_dest; extern int whole_file; extern int local_server; @@ -59,30 +60,32 @@ extern unsigned int block_size; extern struct exclude_list_struct server_exclude_list; - -/* choose whether to skip a particular file */ -static int skip_file(char *fname, struct file_struct *file, STRUCT_STAT *st) +static int unchanged_attrs(struct file_struct *file, STRUCT_STAT *st) { - if (st->st_size != file->length) + if (preserve_perms + && (st->st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS)) return 0; - if (link_dest) { - if (preserve_perms - && (st->st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS)) - return 0; - if (am_root && preserve_uid && st->st_uid != file->uid) - return 0; + if (am_root && preserve_uid && st->st_uid != file->uid) + return 0; - if (preserve_gid && file->gid != GID_NONE - && st->st_gid != file->gid) - return 0; - } + if (preserve_gid && file->gid != GID_NONE && st->st_gid != file->gid) + return 0; + + return 1; +} + +/* Perform our quick-check heuristic for determining if a file is unchanged. */ +static int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st) +{ + if (st->st_size != file->length) + return 0; /* if always checksum is set then we use the checksum instead of the file time to determine whether to sync */ if (always_checksum && S_ISREG(st->st_mode)) { char sum[MD4_SUM_LENGTH]; - file_checksum(fname,sum,st->st_size); + file_checksum(fn, sum, st->st_size); return memcmp(sum, file->u.sum, protocol_version < 21 ? 2 : MD4_SUM_LENGTH) == 0; } @@ -131,7 +134,6 @@ void write_sum_head(int f, struct sum_struct *sum) * * This might be made one of several selectable heuristics. */ - static void sum_sizes_sqroot(struct sum_struct *sum, uint64 len) { unsigned int blength; @@ -429,13 +431,42 @@ static void recv_generator(char *fname, struct file_struct *file, int i, fnamecmp = fname; fnamecmp_type = FNAMECMP_FNAME; - if (statret == -1 && compare_dest != NULL) { - /* try the file at compare_dest instead */ - pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, compare_dest, fname); - if (link_stat(fnamecmpbuf, &st, 0) == 0 - && S_ISREG(st.st_mode)) { + if (statret == -1 && basis_dir[0] != NULL) { + int fallback_match = -1; + int match_level = 0; + int i = 0; + do { + pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, + basis_dir[i], fname); + if (link_stat(fnamecmpbuf, &st, 0) == 0 + && S_ISREG(st.st_mode)) { + statret = 0; + if (link_dest) { + if (!match_level) { + fallback_match = i; + match_level = 1; + } else if (match_level == 2 + && !unchanged_attrs(file, &st)) + continue; + if (!unchanged_file(fnamecmpbuf, file, &st)) + continue; + fallback_match = i; + match_level = 2; + if (!unchanged_attrs(file, &st)) + continue; + } + match_level = 3; + break; + } + } while (basis_dir[++i] != NULL); + if (statret == 0) { + if (match_level < 3) { + i = fallback_match; + pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, + basis_dir[i], fname); + } #if HAVE_LINK - if (link_dest && !dry_run) { + if (link_dest && match_level == 3 && !dry_run) { if (do_link(fnamecmpbuf, fname) < 0) { if (verbose) { rsyserr(FINFO, errno, @@ -444,15 +475,14 @@ static void recv_generator(char *fname, struct file_struct *file, int i, safe_fname(fname)); } fnamecmp = fnamecmpbuf; - fnamecmp_type = FNAMECMP_CMPDEST; + fnamecmp_type = FNAMECMP_BASIS_DIR + i; } } else #endif { fnamecmp = fnamecmpbuf; - fnamecmp_type = FNAMECMP_CMPDEST; + fnamecmp_type = FNAMECMP_BASIS_DIR + i; } - statret = 0; } } @@ -497,7 +527,9 @@ static void recv_generator(char *fname, struct file_struct *file, int i, return; } - if (skip_file(fnamecmp, file, &st)) { + if ((link_dest || copy_dest) && fnamecmp_type != FNAMECMP_FNAME) + ; + else if (unchanged_file(fnamecmp, file, &st)) { if (fnamecmp_type == FNAMECMP_FNAME) set_perms(fname, file, &st, PERMS_REPORT); return; -- 2.34.1