- Fix the code that removes .rsyncsums files when a dir becomes empty.
+based-on: patch/master/checksum-reading
diff --git a/flist.c b/flist.c
-index 8a42d80..d65c475 100644
--- a/flist.c
+++ b/flist.c
@@ -27,6 +27,7 @@
extern int am_root;
extern int am_server;
extern int am_daemon;
-@@ -99,6 +100,9 @@ extern iconv_t ic_send, ic_recv;
+@@ -108,6 +109,9 @@ extern iconv_t ic_send, ic_recv;
#define PTR_SIZE (sizeof (struct file_struct *))
int io_error;
int checksum_len;
dev_t filesystem_dev; /* used to implement -x */
-@@ -137,8 +141,13 @@ static char tmp_sum[MAX_DIGEST_LEN];
+@@ -147,8 +151,13 @@ static char tmp_sum[MAX_DIGEST_LEN];
static char empty_sum[MAX_DIGEST_LEN];
static int flist_count_offset; /* for --delete --progress */
} *csum_cache = NULL;
static void flist_sort_and_clean(struct file_list *flist, int flags);
-@@ -356,7 +365,79 @@ static void flist_done_allocating(struct file_list *flist)
+@@ -366,7 +375,79 @@ static void flist_done_allocating(struct file_list *flist)
flist->pool_boundary = ptr;
}
{
int slot, slots = am_sender ? 1 : basis_dir_cnt + 1;
-@@ -370,6 +451,9 @@ void reset_checksum_cache()
+@@ -380,6 +461,9 @@ void reset_checksum_cache()
struct file_list *flist = csum_cache[slot].flist;
if (flist) {
/* Reset the pool memory and empty the file-list array. */
pool_free_old(flist->file_pool,
pool_boundary(flist->file_pool, 0));
-@@ -380,6 +464,10 @@ void reset_checksum_cache()
+@@ -390,6 +474,10 @@ void reset_checksum_cache()
flist->low = 0;
flist->high = -1;
flist->next = NULL;
}
}
-@@ -387,7 +475,7 @@ void reset_checksum_cache()
+@@ -397,7 +485,7 @@ void reset_checksum_cache()
static int add_checksum(struct file_list *flist, const char *dirname,
const char *basename, int basename_len, OFF_T file_length,
time_t mtime, uint32 ctime, uint32 inode,
{
struct file_struct *file;
int alloc_len, extra_len;
-@@ -404,7 +492,7 @@ static int add_checksum(struct file_list *flist, const char *dirname,
+@@ -414,7 +502,7 @@ static int add_checksum(struct file_list *flist, const char *dirname,
if (extra_len & (EXTRA_ROUNDING * EXTRA_LEN))
extra_len = (extra_len | (EXTRA_ROUNDING * EXTRA_LEN)) + EXTRA_LEN;
#endif
bp = pool_alloc(flist->file_pool, alloc_len, "add_checksum");
memset(bp, 0, extra_len + FILE_STRUCT_LEN);
-@@ -413,7 +501,14 @@ static int add_checksum(struct file_list *flist, const char *dirname,
+@@ -423,7 +511,14 @@ static int add_checksum(struct file_list *flist, const char *dirname,
bp += FILE_STRUCT_LEN;
memcpy(bp, basename, basename_len);
file->mode = S_IFREG;
file->modtime = mtime;
file->len32 = (uint32)file_length;
-@@ -442,10 +537,11 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
+@@ -452,10 +547,11 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
char line[MAXPATHLEN+1024], fbuf[MAXPATHLEN], sum[MAX_DIGEST_LEN];
FILE *fp;
char *cp;
int dlen = dirname ? strlcpy(fbuf, dirname, sizeof fbuf) : 0;
if (dlen >= (int)(sizeof fbuf - 1 - RSYNCSUMS_LEN))
-@@ -466,7 +562,7 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
+@@ -476,7 +572,7 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
while (fgets(line, sizeof line, fp)) {
cp = line;
if (protocol_version >= 30) {
if (*cp == '=')
while (*++cp == '=') {}
else
-@@ -477,7 +573,14 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
+@@ -487,7 +583,14 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
}
if (*cp == '=') {
} else {
for (i = 0; i < checksum_len*2; i++, cp++) {
int x;
-@@ -495,13 +598,14 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
+@@ -505,13 +608,14 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
else
sum[i/2] = x << 4;
}
if (*cp == '=')
while (*++cp == '=') {}
else
-@@ -551,24 +655,112 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
+@@ -561,24 +665,112 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
continue;
strlcpy(fbuf+dlen, cp, sizeof fbuf - dlen);
read_checksums(slot, flist, file->dirname);
}
-@@ -580,12 +772,31 @@ void get_cached_checksum(int slot, const char *fname, struct file_struct *file,
+@@ -590,12 +782,31 @@ void get_cached_checksum(int slot, const char *fname, struct file_struct *file,
&& (checksum_files & CSF_LAX
|| (F_CTIME(fp) == (uint32)stp->st_ctime
&& F_INODE(fp) == (uint32)stp->st_ino))) {
}
/* Call this with EITHER (1) "file, NULL, 0" to chdir() to the file's
-@@ -1452,6 +1663,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1490,6 +1701,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
if (is_excluded(thisname, S_ISDIR(st.st_mode) != 0, filter_level)) {
if (ignore_perishable)
non_perishable_cnt++;
return NULL;
}
-@@ -1498,13 +1711,13 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1536,13 +1749,13 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
lastdir[len] = '\0';
lastdir_len = len;
if (checksum_files && am_sender && flist)
}
}
basename_len = strlen(basename) + 1; /* count the '\0' */
-@@ -1599,7 +1812,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1648,7 +1861,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
if (always_checksum && am_sender && S_ISREG(st.st_mode)) {
if (flist && checksum_files)
else
file_checksum(thisname, st.st_size, tmp_sum);
if (sender_keeps_checksum)
-@@ -1971,6 +2184,9 @@ static void send_directory(int f, struct file_list *flist, char *fbuf, int len,
+@@ -2021,6 +2234,9 @@ static void send_directory(int f, struct file_list *flist, char *fbuf, int len,
closedir(d);
if (f >= 0 && recurse && !divert_dirs) {
int i, end = flist->used - 1;
/* send_if_directory() bumps flist->used, so use "end". */
-@@ -2589,6 +2805,9 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
- } else
- flist_eof = 1;
+@@ -2671,6 +2887,9 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
+ rprintf(FINFO, "[%s] flist_eof=1\n", who_am_i());
+ }
+ if (checksum_files & CSF_UPDATE && flist_eof)
+ reset_checksum_cache(0); /* writes any last updates */
}
diff --git a/generator.c b/generator.c
-index 48a5062..8717ab7 100644
--- a/generator.c
+++ b/generator.c
-@@ -111,6 +111,7 @@ static int dir_tweaking;
+@@ -110,6 +110,7 @@ static int dir_tweaking;
static int symlink_timeset_failed_flags;
static int need_retouch_dir_times;
static int need_retouch_dir_perms;
static const char *solo_file = NULL;
enum nonregtype {
-@@ -533,7 +534,7 @@ int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st, int slot
+@@ -532,7 +533,7 @@ int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st, int slot
if (always_checksum > 0 && S_ISREG(st->st_mode)) {
char sum[MAX_DIGEST_LEN];
if (checksum_files && slot >= 0)
else
file_checksum(fn, st->st_size, sum);
return memcmp(sum, F_SUM(file), checksum_len) == 0;
-@@ -1177,7 +1178,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1183,7 +1184,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
fuzzy_dirlist = get_dirlist(fnamecmpbuf, -1, 1);
}
if (checksum_files) {
}
need_new_dirscan = 0;
}
-@@ -1335,6 +1337,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1341,6 +1343,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
else
change_local_filter_dir(fname, strlen(fname), F_DEPTH(file));
}
goto cleanup;
}
-@@ -1627,6 +1630,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1614,6 +1617,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
handle_partial_dir(partialptr, PDIR_DELETE);
}
set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT);
if (itemizing)
itemize(fnamecmp, file, ndx, statret, &sx, 0, 0, NULL);
#ifdef SUPPORT_HARD_LINKS
-@@ -2068,6 +2073,7 @@ void generate_files(int f_out, const char *local_name)
+@@ -2115,6 +2120,7 @@ void generate_files(int f_out, const char *local_name)
} else
change_local_filter_dir(fbuf, strlen(fbuf), F_DEPTH(fp));
}
}
for (i = cur_flist->low; i <= cur_flist->high; i++) {
struct file_struct *file = cur_flist->sorted[i];
-@@ -2162,6 +2168,9 @@ void generate_files(int f_out, const char *local_name)
+@@ -2209,6 +2215,9 @@ void generate_files(int f_out, const char *local_name)
wait_for_receiver();
}
info_levels[INFO_PROGRESS] = save_info_progress;
diff --git a/io.c b/io.c
-index 6a89c8f..50e73b1 100644
--- a/io.c
+++ b/io.c
-@@ -49,6 +49,7 @@ extern int list_only;
+@@ -52,6 +52,7 @@ extern int list_only;
extern int read_batch;
extern int protect_args;
extern int checksum_seed;
extern int protocol_version;
extern int remove_source_files;
extern int preserve_hard_links;
-@@ -161,6 +162,9 @@ static void got_flist_entry_status(enum festatus status, const char *buf)
+@@ -1025,6 +1026,9 @@ static void got_flist_entry_status(enum festatus status, int ndx)
flist_ndx_push(&hlink_list, ndx);
flist->in_progress++;
}
break;
case FES_REDO:
diff --git a/loadparm.c b/loadparm.c
-index 899d2b5..3123c93 100644
--- a/loadparm.c
+++ b/loadparm.c
-@@ -311,6 +311,10 @@ static struct enum_list enum_csum_modes[] = {
+@@ -312,6 +312,10 @@ static struct enum_list enum_csum_modes[] = {
{ CSF_IGNORE_FILES, "none" },
{ CSF_LAX_MODE, "lax" },
{ CSF_STRICT_MODE, "strict" },
};
diff --git a/options.c b/options.c
-index 2e110f3..26d5561 100644
--- a/options.c
+++ b/options.c
-@@ -1635,7 +1635,15 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+@@ -1657,7 +1657,15 @@ int parse_arguments(int *argc_p, const char ***argv_p)
case OPT_SUMFILES:
arg = poptGetOptArg(pc);
checksum_files |= CSF_LAX_MODE;
else if (strcmp(arg, "strict") == 0)
diff --git a/receiver.c b/receiver.c
-index 4325e30..2cea8fe 100644
--- a/receiver.c
+++ b/receiver.c
@@ -47,6 +47,7 @@ extern int sparse_files;
extern int inplace;
extern int delay_updates;
extern mode_t orig_umask;
-@@ -344,7 +345,7 @@ static void handle_delayed_updates(char *local_name)
+@@ -376,7 +377,7 @@ static void handle_delayed_updates(char *local_name)
"rename failed for %s (from %s)",
full_fname(fname), partialptr);
} else {
|| (preserve_hard_links && F_IS_HLINKED(file)))
send_msg_int(MSG_SUCCESS, ndx);
handle_partial_dir(partialptr, PDIR_DELETE);
-@@ -794,7 +795,7 @@ int recv_files(int f_in, char *local_name)
+@@ -829,7 +830,7 @@ int recv_files(int f_in, int f_out, char *local_name)
case 2:
break;
case 1:
send_msg_int(MSG_SUCCESS, ndx);
break;
diff --git a/rsync.h b/rsync.h
-index ba8f3db..89c47bd 100644
--- a/rsync.h
+++ b/rsync.h
-@@ -908,6 +908,8 @@ typedef struct {
+@@ -929,6 +929,8 @@ typedef struct {
#define CSF_ENABLE (1<<1)
#define CSF_LAX (1<<2)
#define CSF_IGNORE_FILES 0
#define CSF_LAX_MODE (CSF_ENABLE|CSF_LAX)
diff --git a/rsync.yo b/rsync.yo
-index 7aa62cf..a119ed7 100644
--- a/rsync.yo
+++ b/rsync.yo
-@@ -596,9 +596,13 @@ computed just as it would be if bf(--sumfiles) was not specified.
+@@ -599,9 +599,13 @@ computed just as it would be if bf(--sumfiles) was not specified.
The MODE value is either "lax", for relaxed checking (which compares size
and mtime), "strict" (which also compares ctime and inode), or "none" to
This option has no effect unless bf(--checksum, -c) was also specified. It
also only affects the current side of the transfer, so if you want the
diff --git a/rsyncd.conf.yo b/rsyncd.conf.yo
-index 0fc98fd..3024842 100644
--- a/rsyncd.conf.yo
+++ b/rsyncd.conf.yo
-@@ -295,13 +295,15 @@ The default is tt(/var/run/rsyncd.lock).
+@@ -315,13 +315,15 @@ The default is tt(/var/run/rsyncd.lock).
dit(bf(checksum files)) This parameter tells rsync to make use of any cached
checksum information it finds in per-directory .rsyncsums files when the
current transfer is using the bf(--checksum) option. The value can be set