extern char *backup_dir;
extern char *backup_suffix;
extern int backup_suffix_len;
-@@ -446,22 +448,27 @@ static void do_delete_pass(struct file_l
+@@ -517,22 +519,27 @@ static void do_delete_pass(struct file_l
rprintf(FINFO, " \r");
}
+int unchanged_attrs(struct file_struct *file, statx *sxp)
{
if (preserve_perms
-- && (st->st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS))
-+ && (sxp->st.st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS))
+- && (unsigned)(st->st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS))
++ && (unsigned)(sxp->st.st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS))
return 0;
- if (am_root && preserve_uid && st->st_uid != F_UID(file))
int32 iflags, uchar fnamecmp_type, const char *xname)
{
if (statret >= 0) { /* A from-dest-dir statret can == 1! */
-@@ -469,20 +476,24 @@ void itemize(struct file_struct *file, i
+@@ -540,20 +547,24 @@ void itemize(struct file_struct *file, i
: S_ISDIR(file->mode) ? !omit_dir_times
: !S_ISLNK(file->mode);
- || (keep_time && cmp_time(file->modtime, st->st_mtime) != 0))
+ || (keep_time && cmp_time(file->modtime, sxp->st.st_mtime) != 0))
iflags |= ITEM_REPORT_TIME;
-- if ((file->mode & CHMOD_BITS) != (st->st_mode & CHMOD_BITS))
-+ if ((file->mode & CHMOD_BITS) != (sxp->st.st_mode & CHMOD_BITS))
+- if ((unsigned)(st->st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS))
++ if ((unsigned)(sxp->st.st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS))
iflags |= ITEM_REPORT_PERMS;
- if (preserve_uid && am_root && F_UID(file) != st->st_uid)
+ if (preserve_uid && am_root && F_UID(file) != sxp->st.st_uid)
} else
iflags |= ITEM_IS_NEW;
-@@ -736,7 +747,7 @@ void check_for_finished_hlinks(int itemi
+@@ -807,7 +818,7 @@ void check_for_finished_hlinks(int itemi
* handling the file, -1 if no dest-linking occurred, or a non-negative
* value if we found an alternate basis file. */
static int try_dests_reg(struct file_struct *file, char *fname, int ndx,
int maybe_ATTRS_REPORT, enum logcode code)
{
int best_match = -1;
-@@ -745,7 +756,7 @@ static int try_dests_reg(struct file_str
+@@ -816,7 +827,7 @@ static int try_dests_reg(struct file_str
do {
pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname);
continue;
switch (match_level) {
case 0:
-@@ -753,16 +764,20 @@ static int try_dests_reg(struct file_str
+@@ -824,16 +835,20 @@ static int try_dests_reg(struct file_str
match_level = 1;
/* FALL THROUGH */
case 1:
continue;
best_match = j;
match_level = 3;
-@@ -777,7 +792,7 @@ static int try_dests_reg(struct file_str
+@@ -848,7 +863,7 @@ static int try_dests_reg(struct file_str
if (j != best_match) {
j = best_match;
pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname);
return -1;
}
-@@ -785,15 +800,20 @@ static int try_dests_reg(struct file_str
+@@ -856,15 +871,20 @@ static int try_dests_reg(struct file_str
#ifdef SUPPORT_HARD_LINKS
if (link_dest) {
int i = itemizing && (verbose > 1 || stdout_format_has_i > 1);
if (verbose > 1 && maybe_ATTRS_REPORT) {
rprintf(FCLIENT, "%s is uptodate\n", fname);
}
-@@ -809,8 +829,13 @@ static int try_dests_reg(struct file_str
+@@ -880,8 +900,13 @@ static int try_dests_reg(struct file_str
}
return -1;
}
set_file_attrs(fname, file, NULL, 0);
if (maybe_ATTRS_REPORT
&& ((!itemizing && verbose && match_level == 2)
-@@ -833,7 +858,7 @@ static int try_dests_reg(struct file_str
+@@ -904,7 +929,7 @@ static int try_dests_reg(struct file_str
* handling the file, or -1 if no dest-linking occurred, or a non-negative
* value if we found an alternate basis file. */
static int try_dests_non(struct file_struct *file, char *fname, int ndx,
int maybe_ATTRS_REPORT, enum logcode code)
{
char lnk[MAXPATHLEN];
-@@ -866,24 +891,24 @@ static int try_dests_non(struct file_str
+@@ -937,24 +962,24 @@ static int try_dests_non(struct file_str
do {
pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname);
continue;
break;
#endif
-@@ -898,7 +923,7 @@ static int try_dests_non(struct file_str
+@@ -969,7 +994,7 @@ static int try_dests_non(struct file_str
case TYPE_SPECIAL:
case TYPE_DEVICE:
devp = F_RDEV_P(file);
continue;
break;
#ifdef SUPPORT_LINKS
-@@ -915,7 +940,11 @@ static int try_dests_non(struct file_str
+@@ -986,7 +1011,11 @@ static int try_dests_non(struct file_str
match_level = 2;
best_match = j;
}
match_level = 3;
best_match = j;
break;
-@@ -928,7 +957,7 @@ static int try_dests_non(struct file_str
+@@ -999,7 +1028,7 @@ static int try_dests_non(struct file_str
if (j != best_match) {
j = best_match;
pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname);
return -1;
}
-@@ -959,7 +988,15 @@ static int try_dests_non(struct file_str
+@@ -1030,7 +1059,15 @@ static int try_dests_non(struct file_str
: ITEM_LOCAL_CHANGE
+ (match_level == 3 ? ITEM_XNAME_FOLLOWS : 0);
char *lp = match_level == 3 ? "" : NULL;
}
if (verbose > 1 && maybe_ATTRS_REPORT) {
rprintf(FCLIENT, "%s%s is uptodate\n",
-@@ -972,6 +1009,7 @@ static int try_dests_non(struct file_str
+@@ -1043,6 +1080,7 @@ static int try_dests_non(struct file_str
}
static int phase = 0;
/* Acts on the_file_list->file's ndx'th item, whose name is fname. If a dir,
* make sure it exists, and has the right permissions/timestamp info. For
-@@ -993,7 +1031,8 @@ static void recv_generator(char *fname,
+@@ -1064,7 +1102,8 @@ static void recv_generator(char *fname,
static int need_fuzzy_dirlist = 0;
struct file_struct *fuzzy_file = NULL;
int fd = -1, f_copy = -1;
struct file_struct *back_file = NULL;
int statret, real_ret, stat_errno;
char *fnamecmp, *partialptr, *backupptr = NULL;
-@@ -1049,6 +1088,9 @@ static void recv_generator(char *fname,
+@@ -1120,6 +1159,9 @@ static void recv_generator(char *fname,
} else if (!dry_run)
return;
}
if (dry_run > 1) {
statret = -1;
stat_errno = ENOENT;
-@@ -1056,7 +1098,7 @@ static void recv_generator(char *fname,
+@@ -1127,7 +1169,7 @@ static void recv_generator(char *fname,
const char *dn = file->dirname ? file->dirname : ".";
if (parent_dirname != dn && strcmp(parent_dirname, dn) != 0) {
if (relative_paths && !implied_dirs
&& create_directory_path(fname) < 0) {
rsyserr(FERROR, errno,
"recv_generator: mkdir %s failed",
-@@ -1068,6 +1110,10 @@ static void recv_generator(char *fname,
+@@ -1139,6 +1181,10 @@ static void recv_generator(char *fname,
}
if (fuzzy_basis)
need_fuzzy_dirlist = 1;
}
parent_dirname = dn;
-@@ -1077,7 +1123,7 @@ static void recv_generator(char *fname,
+@@ -1148,7 +1194,7 @@ static void recv_generator(char *fname,
need_fuzzy_dirlist = 0;
}
keep_dirlinks && S_ISDIR(file->mode));
stat_errno = errno;
}
-@@ -1095,8 +1141,9 @@ static void recv_generator(char *fname,
+@@ -1166,8 +1212,9 @@ static void recv_generator(char *fname,
* mode based on the local permissions and some heuristics. */
if (!preserve_perms) {
int exists = statret == 0
}
if (S_ISDIR(file->mode)) {
-@@ -1105,8 +1152,8 @@ static void recv_generator(char *fname,
+@@ -1176,8 +1223,8 @@ static void recv_generator(char *fname,
* file of that name and it is *not* a directory, then
* we need to delete it. If it doesn't exist, then
* (perhaps recursively) create it. */
return;
statret = -1;
}
-@@ -1115,14 +1162,14 @@ static void recv_generator(char *fname,
+@@ -1186,14 +1233,14 @@ static void recv_generator(char *fname,
dry_run++;
}
real_ret = statret;
itemizing, maybe_ATTRS_REPORT, code);
if (j == -2) {
itemizing = 0;
-@@ -1131,7 +1178,11 @@ static void recv_generator(char *fname,
+@@ -1202,7 +1249,11 @@ static void recv_generator(char *fname,
statret = 1;
}
if (itemizing && f_out != -1) {
statret ? ITEM_LOCAL_CHANGE : 0, 0, NULL);
}
if (real_ret != 0 && do_mkdir(fname,file->mode) < 0 && errno != EEXIST) {
-@@ -1151,22 +1202,22 @@ static void recv_generator(char *fname,
+@@ -1222,22 +1273,22 @@ static void recv_generator(char *fname,
return;
}
}
#endif
if (preserve_links && S_ISLNK(file->mode)) {
-@@ -1186,14 +1237,14 @@ static void recv_generator(char *fname,
+@@ -1257,14 +1308,14 @@ static void recv_generator(char *fname,
char lnk[MAXPATHLEN];
int len;
#ifdef SUPPORT_HARD_LINKS
if (preserve_hard_links && F_IS_HLINKED(file))
hard_link_cluster(file, ndx, itemizing, code, -1);
-@@ -1204,10 +1255,10 @@ static void recv_generator(char *fname,
+@@ -1275,10 +1326,10 @@ static void recv_generator(char *fname,
}
/* Not the right symlink (or not a symlink), so
* delete it. */
itemizing, maybe_ATTRS_REPORT, code);
if (j == -2) {
#ifndef CAN_HARDLINK_SYMLINK
-@@ -1224,7 +1275,7 @@ static void recv_generator(char *fname,
+@@ -1295,7 +1346,7 @@ static void recv_generator(char *fname,
}
#ifdef SUPPORT_HARD_LINKS
if (preserve_hard_links && F_IS_HLINKED(file)
itemizing, code, HL_SKIP))
return;
#endif
-@@ -1234,7 +1285,7 @@ static void recv_generator(char *fname,
+@@ -1305,7 +1356,7 @@ static void recv_generator(char *fname,
} else {
set_file_attrs(fname, file, NULL, 0);
if (itemizing) {
ITEM_LOCAL_CHANGE, 0, NULL);
}
if (code != FNONE && verbose)
-@@ -1260,33 +1311,38 @@ static void recv_generator(char *fname,
+@@ -1331,33 +1382,38 @@ static void recv_generator(char *fname,
if (statret == 0) {
char *t;
if (IS_DEVICE(file->mode)) {
t = "special file";
}
if (statret == 0
-- && (st.st_mode & ~CHMOD_BITS) == (file->mode & ~CHMOD_BITS)
+- && (unsigned)(st.st_mode & ~CHMOD_BITS) == (file->mode & ~CHMOD_BITS)
- && st.st_rdev == rdev) {
-+ && (sx.st.st_mode & ~CHMOD_BITS) == (file->mode & ~CHMOD_BITS)
++ && (unsigned)(sx.st.st_mode & ~CHMOD_BITS) == (file->mode & ~CHMOD_BITS)
+ && sx.st.st_rdev == rdev) {
/* The device or special file is identical. */
- if (itemizing)
itemizing, maybe_ATTRS_REPORT, code);
if (j == -2) {
#ifndef CAN_HARDLINK_SPECIAL
-@@ -1303,7 +1359,7 @@ static void recv_generator(char *fname,
+@@ -1374,7 +1430,7 @@ static void recv_generator(char *fname,
}
#ifdef SUPPORT_HARD_LINKS
if (preserve_hard_links && F_IS_HLINKED(file)
itemizing, code, HL_SKIP))
return;
#endif
-@@ -1318,7 +1374,11 @@ static void recv_generator(char *fname,
+@@ -1389,7 +1445,11 @@ static void recv_generator(char *fname,
} else {
set_file_attrs(fname, file, NULL, 0);
if (itemizing) {
ITEM_LOCAL_CHANGE, 0, NULL);
}
if (code != FNONE && verbose)
-@@ -1330,7 +1390,7 @@ static void recv_generator(char *fname,
+@@ -1401,7 +1461,7 @@ static void recv_generator(char *fname,
if (remove_source_files == 1)
goto return_with_success;
}
}
if (!S_ISREG(file->mode)) {
-@@ -1364,7 +1424,7 @@ static void recv_generator(char *fname,
+@@ -1435,7 +1495,7 @@ static void recv_generator(char *fname,
}
if (update_only && statret == 0
if (verbose > 1)
rprintf(FINFO, "%s is newer\n", fname);
return;
-@@ -1373,20 +1433,20 @@ static void recv_generator(char *fname,
+@@ -1444,20 +1504,20 @@ static void recv_generator(char *fname,
fnamecmp = fname;
fnamecmp_type = FNAMECMP_FNAME;
}
if (j >= 0) {
fnamecmp = fnamecmpbuf;
-@@ -1396,7 +1456,7 @@ static void recv_generator(char *fname,
+@@ -1467,7 +1527,7 @@ static void recv_generator(char *fname,
}
real_ret = statret;
if (partial_dir && (partialptr = partial_dir_fname(fname)) != NULL
&& link_stat(partialptr, &partial_st, 0) == 0
-@@ -1415,7 +1475,7 @@ static void recv_generator(char *fname,
+@@ -1486,7 +1546,7 @@ static void recv_generator(char *fname,
rprintf(FINFO, "fuzzy basis selected for %s: %s\n",
fname, fnamecmpbuf);
}
statret = 0;
fnamecmp = fnamecmpbuf;
fnamecmp_type = FNAMECMP_FUZZY;
-@@ -1425,7 +1485,7 @@ static void recv_generator(char *fname,
+@@ -1496,7 +1556,7 @@ static void recv_generator(char *fname,
if (statret != 0) {
#ifdef SUPPORT_HARD_LINKS
if (preserve_hard_links && F_IS_HLINKED(file)
itemizing, code, HL_SKIP))
return;
#endif
-@@ -1436,38 +1496,51 @@ static void recv_generator(char *fname,
+@@ -1507,38 +1567,51 @@ static void recv_generator(char *fname,
return;
}
fnamecmp = partialptr;
fnamecmp_type = FNAMECMP_PARTIAL_DIR;
statret = 0;
-@@ -1492,18 +1565,22 @@ static void recv_generator(char *fname,
+@@ -1563,18 +1636,22 @@ static void recv_generator(char *fname,
/* pretend the file didn't exist */
#ifdef SUPPORT_HARD_LINKS
if (preserve_hard_links && F_IS_HLINKED(file)
}
if (!(back_file = make_file(fname, NULL, NULL, 0, NO_FILTERS))) {
close(fd);
-@@ -1514,7 +1591,7 @@ static void recv_generator(char *fname,
+@@ -1585,7 +1662,7 @@ static void recv_generator(char *fname,
full_fname(backupptr));
unmake_file(back_file);
close(fd);
}
if ((f_copy = do_open(backupptr,
O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0) {
-@@ -1522,14 +1599,14 @@ static void recv_generator(char *fname,
+@@ -1593,14 +1670,14 @@ static void recv_generator(char *fname,
full_fname(backupptr));
unmake_file(back_file);
close(fd);
}
if (verbose > 2)
-@@ -1547,8 +1624,16 @@ static void recv_generator(char *fname,
+@@ -1618,8 +1695,16 @@ static void recv_generator(char *fname,
iflags |= ITEM_BASIS_TYPE_FOLLOWS;
if (fnamecmp_type == FNAMECMP_FUZZY)
iflags |= ITEM_XNAME_FOLLOWS;
}
if (!do_xfers) {
-@@ -1556,17 +1641,17 @@ static void recv_generator(char *fname,
+@@ -1627,17 +1712,17 @@ static void recv_generator(char *fname,
if (preserve_hard_links && F_IS_HLINKED(file))
hard_link_cluster(file, ndx, itemizing, code, -1);
#endif
if (f_copy >= 0) {
close(f_copy);
-@@ -1579,6 +1664,13 @@ static void recv_generator(char *fname,
+@@ -1650,6 +1735,13 @@ static void recv_generator(char *fname,
}
close(fd);
}
void generate_files(int f_out, struct file_list *flist, char *local_name)
-@@ -1640,6 +1732,8 @@ void generate_files(int f_out, struct fi
+@@ -1716,6 +1808,8 @@ void generate_files(int f_out, struct fi
* notice that and let us know via the redo pipe (or its closing). */
ignore_timeout = 1;
extern int whole_file;
extern int list_only;
extern int new_root_dir;
-@@ -91,16 +92,19 @@ extern char *backup_dir;
+@@ -91,18 +92,21 @@ extern char *backup_dir;
extern char *backup_suffix;
extern int backup_suffix_len;
extern struct file_list *the_file_list;
static int deletion_count = 0; /* used to implement --max-delete */
+static int unexplored_dirs = 1;
- static FILE *delete_delay_fp = NULL;
+ static int deldelay_size = 0, deldelay_cnt = 0;
+ static char *deldelay_buf = NULL;
+ static int deldelay_fd = -1;
static BOOL solo_file = 0;
-/* For calling delete_item() and delete_dir_contents(). */
#define DEL_RECURSE (1<<1) /* recurse */
#define DEL_DIR_IS_EMPTY (1<<2) /* internal delete_FUNCTIONS use only */
-@@ -122,11 +126,121 @@ static int is_backup_file(char *fn)
+@@ -124,11 +128,121 @@ static int is_backup_file(char *fn)
return k > 0 && strcmp(fn+k, backup_suffix) == 0;
}
*/
static enum delret delete_item(char *fbuf, int mode, char *replace, int flags)
{
-@@ -148,6 +262,8 @@ static enum delret delete_item(char *fbu
+@@ -150,6 +264,8 @@ static enum delret delete_item(char *fbu
goto check_ret;
/* OK: try to delete the directory. */
}
if (!replace && max_delete >= 0 && ++deletion_count > max_delete)
return DR_AT_LIMIT;
-@@ -194,6 +310,8 @@ static enum delret delete_item(char *fbu
+@@ -196,6 +312,8 @@ static enum delret delete_item(char *fbu
* its contents, otherwise just checks for content. Returns DR_SUCCESS or
* DR_NOT_EMPTY. Note that fname must point to a MAXPATHLEN buffer! (The
* buffer is used for recursion, but returned unchanged.)
*/
static enum delret delete_dir_contents(char *fname, int flags)
{
-@@ -250,6 +368,8 @@ static enum delret delete_dir_contents(c
+@@ -252,6 +370,8 @@ static enum delret delete_dir_contents(c
if (S_ISDIR(fp->mode)
&& delete_dir_contents(fname, flags | DEL_RECURSE) != DR_SUCCESS)
ret = DR_NOT_EMPTY;
if (delete_item(fname, fp->mode, NULL, flags) != DR_SUCCESS)
ret = DR_NOT_EMPTY;
}
-@@ -334,15 +454,19 @@ static void delayed_deletions(char *delb
+@@ -404,15 +524,19 @@ static void do_delayed_deletions(char *d
* all the --delete-WHEN options. Note that the fbuf pointer must point to a
* MAXPATHLEN buffer with the name of the directory in it (the functions we
* call will append names onto the end, but the old dir value will be restored
int dlen, i;
if (!flist) {
-@@ -356,6 +480,8 @@ static void delete_in_dir(struct file_li
+@@ -426,6 +550,8 @@ static void delete_in_dir(struct file_li
if (verbose > 2)
rprintf(FINFO, "delete_in_dir(%s)\n", fbuf);
if (allowed_lull)
maybe_send_keepalive();
-@@ -363,12 +489,14 @@ static void delete_in_dir(struct file_li
+@@ -433,12 +559,14 @@ static void delete_in_dir(struct file_li
return; /* Impossible... */
if (io_error && !(lp_ignore_errors(module_id) || ignore_errors)) {
}
while (cur_depth >= file->dir.depth && cur_depth >= min_depth)
-@@ -379,6 +507,9 @@ static void delete_in_dir(struct file_li
+@@ -449,6 +577,9 @@ static void delete_in_dir(struct file_li
dlen = strlen(fbuf);
filt_array[cur_depth] = push_local_filters(fbuf, dlen);
if (one_file_system) {
if (file->flags & FLAG_TOP_DIR)
filesystem_dev = stp->st_dev;
-@@ -388,6 +519,11 @@ static void delete_in_dir(struct file_li
+@@ -458,6 +589,11 @@ static void delete_in_dir(struct file_li
dirlist = get_dirlist(fbuf, dlen, 0);
/* If an item in dirlist is not found in flist, delete it
* from the filesystem. */
for (i = dirlist->count; i--; ) {
-@@ -400,15 +536,22 @@ static void delete_in_dir(struct file_li
+@@ -470,16 +606,23 @@ static void delete_in_dir(struct file_li
f_name(fp, NULL));
continue;
}
+ }
if (flist_find(flist, fp) < 0) {
f_name(fp, delbuf);
-- if (delete_delay_fp)
-+ if (delete_delay_fp && !(flags & DEL_NO_DELETIONS))
- fprintf(delete_delay_fp, "%o %s%c", (short)fp->mode, delbuf, '\0');
- else
+- if (delete_during == 2) {
+++ if (delete_during == 2 && !(flags & DEL_NO_DELETIONS)) {
+ if (!remember_delete(fp, delbuf))
+ break;
+ } else
- delete_item(delbuf, fp->mode, NULL, DEL_RECURSE);
- }
+ delete_item(delbuf, fp->mode, NULL, flags);
flist_free(dirlist);
}
-@@ -438,9 +581,9 @@ static void do_delete_pass(struct file_l
+@@ -509,9 +652,9 @@ static void do_delete_pass(struct file_l
|| !S_ISDIR(st.st_mode))
continue;
if (do_progress && !am_server)
rprintf(FINFO, " \r");
-@@ -971,6 +1114,7 @@ static int try_dests_non(struct file_str
+@@ -1042,6 +1185,7 @@ static int try_dests_non(struct file_str
return j;
}
static int phase = 0;
/* Acts on the_file_list->file's ndx'th item, whose name is fname. If a dir,
-@@ -1157,8 +1301,12 @@ static void recv_generator(char *fname,
+@@ -1228,8 +1372,12 @@ static void recv_generator(char *fname,
if (real_ret != 0 && one_file_system)
real_st.st_dev = filesystem_dev;
if (delete_during && f_out != -1 && !phase && dry_run < 2
return;
}
-@@ -1429,8 +1577,14 @@ static void recv_generator(char *fname,
+@@ -1500,8 +1648,14 @@ static void recv_generator(char *fname,
itemizing, code, HL_SKIP))
return;
#endif
rsyserr(FERROR, stat_errno, "recv_generator: failed to stat %s",
full_fname(fname));
return;
-@@ -1619,13 +1773,19 @@ void generate_files(int f_out, struct fi
+@@ -1691,6 +1845,12 @@ void generate_files(int f_out, struct fi
(long)getpid(), flist->count);
}
+
if (delete_before && !local_name && flist->count > 0)
do_delete_pass(flist);
- if (delete_during == 2)
- start_delete_temp();
+ if (delete_during == 2) {
+@@ -1701,7 +1861,7 @@ void generate_files(int f_out, struct fi
+ }
do_progress = 0;
- if (append_mode || whole_file < 0)
whole_file = 0;
if (verbose >= 2) {
rprintf(FINFO, "delta-transmission %s\n",
-@@ -1682,7 +1842,23 @@ void generate_files(int f_out, struct fi
+@@ -1758,7 +1918,23 @@ void generate_files(int f_out, struct fi
}
recv_generator(NULL, NULL, 0, 0, 0, code, -1);
if (delete_during)