- Fix the code that removes .rsyncsums files when a dir becomes empty.
+based-on: patch/checksum-reading
diff --git a/flist.c b/flist.c
--- a/flist.c
+++ b/flist.c
-@@ -26,6 +26,7 @@
+@@ -27,6 +27,7 @@
+ #include "inums.h"
#include "io.h"
- extern int verbose;
+extern int dry_run;
extern int am_root;
extern int am_server;
extern int am_daemon;
-@@ -94,6 +95,9 @@ extern iconv_t ic_send, ic_recv;
+@@ -107,6 +108,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 */
-@@ -133,8 +137,13 @@ static char empty_sum[MAX_DIGEST_LEN];
+@@ -146,8 +150,13 @@ static char tmp_sum[MAX_DIGEST_LEN];
+ static char empty_sum[MAX_DIGEST_LEN];
static int flist_count_offset; /* for --delete --progress */
- static int dir_count = 0;
+#define REGULAR_SKIPPED(flist) ((flist)->to_redo)
+
} *csum_cache = NULL;
static void flist_sort_and_clean(struct file_list *flist, int flags);
-@@ -351,7 +360,79 @@ static void flist_done_allocating(struct file_list *flist)
+@@ -365,7 +374,79 @@ static void flist_done_allocating(struct file_list *flist)
flist->pool_boundary = ptr;
}
{
int slot, slots = am_sender ? 1 : basis_dir_cnt + 1;
-@@ -365,6 +446,9 @@ void reset_checksum_cache()
+@@ -379,6 +460,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));
-@@ -375,6 +459,10 @@ void reset_checksum_cache()
+@@ -389,6 +473,10 @@ void reset_checksum_cache()
flist->low = 0;
flist->high = -1;
flist->next = NULL;
}
}
-@@ -382,7 +470,7 @@ void reset_checksum_cache()
+@@ -396,7 +484,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;
-@@ -399,7 +487,7 @@ static int add_checksum(struct file_list *flist, const char *dirname,
+@@ -413,7 +501,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);
-@@ -408,7 +496,14 @@ static int add_checksum(struct file_list *flist, const char *dirname,
+@@ -422,7 +510,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;
-@@ -437,10 +532,11 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
+@@ -451,10 +546,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))
-@@ -461,7 +557,7 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
+@@ -475,7 +571,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
-@@ -472,7 +568,14 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
+@@ -486,7 +582,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;
-@@ -490,13 +593,14 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
+@@ -504,13 +607,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
-@@ -546,24 +650,112 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
+@@ -560,24 +664,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);
}
-@@ -575,12 +767,31 @@ void get_cached_checksum(int slot, const char *fname, struct file_struct *file,
+@@ -589,12 +781,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
-@@ -1371,6 +1582,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1489,6 +1700,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;
}
-@@ -1417,13 +1630,13 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1535,13 +1748,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' */
-@@ -1509,7 +1722,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1647,7 +1860,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)
+ get_cached_checksum(0, thisname, file, basename_len, &st, tmp_sum);
else
file_checksum(thisname, st.st_size, tmp_sum);
- }
-@@ -1839,6 +2052,9 @@ static void send_directory(int f, struct file_list *flist, char *fbuf, int len,
+ if (sender_keeps_checksum)
+@@ -2020,6 +2233,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". */
-@@ -2435,6 +2651,9 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
- }
- } else
- flist_eof = 1;
-+
+@@ -2643,6 +2859,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 */
-
++
return flist;
}
+
diff --git a/generator.c b/generator.c
--- a/generator.c
+++ b/generator.c
-@@ -114,6 +114,7 @@ static int dir_tweaking;
+@@ -112,6 +112,7 @@ static int dir_tweaking;
static int symlink_timeset_failed_flags;
static int need_retouch_dir_times;
static int need_retouch_dir_perms;
+static int started_whole_dir, upcoming_whole_dir;
static const char *solo_file = NULL;
- /* For calling delete_item() and delete_dir_contents(). */
-@@ -723,7 +724,7 @@ int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st, int slot
+ enum nonregtype {
+@@ -534,7 +535,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;
-@@ -1365,7 +1366,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1185,7 +1186,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;
}
-@@ -1515,6 +1517,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1343,6 +1345,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;
}
-@@ -1807,6 +1810,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1616,6 +1619,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
-@@ -2243,6 +2248,7 @@ void generate_files(int f_out, const char *local_name)
+@@ -2120,6 +2125,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];
-@@ -2323,6 +2329,9 @@ void generate_files(int f_out, const char *local_name)
+@@ -2214,6 +2220,9 @@ void generate_files(int f_out, const char *local_name)
wait_for_receiver();
}
+ if (checksum_files)
+ reset_checksum_cache(started_whole_dir);
+
- do_progress = save_do_progress;
- if (delete_during == 2)
- do_delayed_deletions(fbuf);
+ info_levels[INFO_FLIST] = save_info_flist;
+ info_levels[INFO_PROGRESS] = save_info_progress;
+
diff --git a/io.c b/io.c
--- a/io.c
+++ b/io.c
-@@ -50,6 +50,7 @@ extern int read_batch;
- extern int csum_length;
+@@ -52,6 +52,7 @@ extern int list_only;
+ extern int read_batch;
extern int protect_args;
extern int checksum_seed;
+extern int checksum_files;
extern int protocol_version;
extern int remove_source_files;
extern int preserve_hard_links;
-@@ -205,6 +206,9 @@ static void got_flist_entry_status(enum festatus status, const char *buf)
+@@ -875,6 +876,9 @@ static void got_flist_entry_status(enum festatus status, int ndx)
flist_ndx_push(&hlink_list, ndx);
flist->in_progress++;
}
diff --git a/loadparm.c b/loadparm.c
--- a/loadparm.c
+++ b/loadparm.c
-@@ -300,6 +300,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
--- a/options.c
+++ b/options.c
-@@ -1233,7 +1233,15 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+@@ -1637,7 +1637,15 @@ int parse_arguments(int *argc_p, const char ***argv_p)
case OPT_SUMFILES:
arg = poptGetOptArg(pc);
diff --git a/receiver.c b/receiver.c
--- a/receiver.c
+++ b/receiver.c
-@@ -47,6 +47,7 @@ extern int append_mode;
- extern int sparse_files;
+@@ -47,6 +47,7 @@ extern int sparse_files;
extern int keep_partial;
+ extern int checksum_len;
extern int checksum_seed;
+extern int checksum_files;
extern int inplace;
extern int delay_updates;
extern mode_t orig_umask;
-@@ -339,7 +340,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);
-@@ -716,7 +717,7 @@ int recv_files(int f_in, char *local_name)
-
- switch (recv_ok) {
+@@ -829,7 +830,7 @@ int recv_files(int f_in, int f_out, char *local_name)
+ case 2:
+ break;
case 1:
- if (remove_source_files || inc_recurse
+ if (remove_source_files || inc_recurse || checksum_files & CSF_UPDATE
diff --git a/rsync.h b/rsync.h
--- a/rsync.h
+++ b/rsync.h
-@@ -871,6 +871,8 @@ typedef struct {
+@@ -917,6 +917,8 @@ typedef struct {
#define CSF_ENABLE (1<<1)
#define CSF_LAX (1<<2)
diff --git a/rsync.yo b/rsync.yo
--- a/rsync.yo
+++ b/rsync.yo
-@@ -544,9 +544,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
diff --git a/rsyncd.conf.yo b/rsyncd.conf.yo
--- a/rsyncd.conf.yo
+++ b/rsyncd.conf.yo
-@@ -284,13 +284,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