++#ifdef SUPPORT_ACLS
++ if (preserve_acls && f >= 0) {
++ sx.st.st_mode = file->mode;
++ sx.acc_acl = sx.def_acl = NULL;
++ if (get_acl(fname, &sx) < 0)
++ return NULL;
++ }
++#endif
++
+ maybe_emit_filelist_progress(flist->count + flist_count_offset);
+
+ flist_expand(flist);
+ flist->files[flist->count++] = file;
+- if (f >= 0)
++ if (f >= 0) {
+ send_file_entry(file, f, flist->count - 1);
++#ifdef SUPPORT_ACLS
++ if (preserve_acls)
++ send_acl(&sx, f);
++#endif
++ }
+ return file;
+ }
+
+--- old/generator.c
++++ new/generator.c
+@@ -35,6 +35,7 @@ extern int do_progress;
+ extern int relative_paths;
+ extern int implied_dirs;
+ extern int keep_dirlinks;
++extern int preserve_acls;
+ extern int preserve_links;
+ extern int preserve_devices;
+ extern int preserve_specials;
+@@ -87,6 +88,7 @@ extern int force_delete;
+ extern int one_file_system;
+ extern struct stats stats;
+ extern dev_t filesystem_dev;
++extern mode_t orig_umask;
+ extern char *backup_dir;
+ extern char *backup_suffix;
+ extern int backup_suffix_len;
+@@ -518,21 +520,26 @@ static void do_delete_pass(struct file_l
+ rprintf(FINFO, " \r");
+ }
+
+-int unchanged_attrs(struct file_struct *file, STRUCT_STAT *st)
++int unchanged_attrs(struct file_struct *file, statx *sxp)
+ {
+- if (preserve_perms && !BITS_EQUAL(st->st_mode, file->mode, CHMOD_BITS))
++ if (preserve_perms && !BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
+ return 0;
+
+- if (am_root && preserve_uid && st->st_uid != F_UID(file))
++ if (am_root && preserve_uid && sxp->st.st_uid != F_UID(file))
+ return 0;
+
+- if (preserve_gid && F_GID(file) != GID_NONE && st->st_gid != F_GID(file))
++ if (preserve_gid && F_GID(file) != GID_NONE && sxp->st.st_gid != F_GID(file))
+ return 0;
+
++#ifdef SUPPORT_ACLS
++ if (preserve_acls && set_acl(NULL, file, sxp) == 0)
++ return 0;
++#endif
++
+ return 1;
+ }
+
+-void itemize(struct file_struct *file, int ndx, int statret, STRUCT_STAT *st,
++void itemize(struct file_struct *file, int ndx, int statret, statx *sxp,
+ int32 iflags, uchar fnamecmp_type, const char *xname)
+ {
+ if (statret >= 0) { /* A from-dest-dir statret can == 1! */
+@@ -540,20 +547,24 @@ void itemize(struct file_struct *file, i
+ : S_ISDIR(file->mode) ? !omit_dir_times
+ : !S_ISLNK(file->mode);
+
+- if (S_ISREG(file->mode) && F_LENGTH(file) != st->st_size)
++ if (S_ISREG(file->mode) && F_LENGTH(file) != sxp->st.st_size)
+ iflags |= ITEM_REPORT_SIZE;
+ if ((iflags & (ITEM_TRANSFER|ITEM_LOCAL_CHANGE) && !keep_time
+ && !(iflags & ITEM_MATCHED)
+ && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname))
+- || (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 (!BITS_EQUAL(st->st_mode, file->mode, CHMOD_BITS))
++ if (!BITS_EQUAL(sxp->st.st_mode, 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)
+ iflags |= ITEM_REPORT_OWNER;
+ if (preserve_gid && F_GID(file) != GID_NONE
+- && st->st_gid != F_GID(file))
++ && sxp->st.st_gid != F_GID(file))
+ iflags |= ITEM_REPORT_GROUP;
++#ifdef SUPPORT_ACLS
++ if (preserve_acls && set_acl(NULL, file, sxp) == 0)
++ iflags |= ITEM_REPORT_ACL;
++#endif
+ } else
+ iflags |= ITEM_IS_NEW;
+
+@@ -808,7 +819,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,
+- char *cmpbuf, STRUCT_STAT *stp, int itemizing,
++ char *cmpbuf, statx *sxp, int itemizing,
+ enum logcode code)
+ {
+ int best_match = -1;
+@@ -817,7 +828,7 @@ static int try_dests_reg(struct file_str
+
+ do {
+ pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname);
+- if (link_stat(cmpbuf, stp, 0) < 0 || !S_ISREG(stp->st_mode))
++ if (link_stat(cmpbuf, &sxp->st, 0) < 0 || !S_ISREG(sxp->st.st_mode))
+ continue;
+ switch (match_level) {
+ case 0:
+@@ -825,16 +836,20 @@ static int try_dests_reg(struct file_str
+ match_level = 1;
+ /* FALL THROUGH */
+ case 1:
+- if (!unchanged_file(cmpbuf, file, stp))
++ if (!unchanged_file(cmpbuf, file, &sxp->st))
+ continue;
+ best_match = j;
+ match_level = 2;
+ /* FALL THROUGH */
+ case 2:
+- if (!unchanged_attrs(file, stp))
++#ifdef SUPPORT_ACLS
++ if (preserve_acls)
++ get_acl(cmpbuf, sxp);
++#endif
++ if (!unchanged_attrs(file, sxp))
+ continue;
+ if (always_checksum && preserve_times
+- && cmp_time(stp->st_mtime, file->modtime))
++ && cmp_time(sxp->st.st_mtime, file->modtime))
+ continue;
+ best_match = j;
+ match_level = 3;
+@@ -849,7 +864,7 @@ static int try_dests_reg(struct file_str
+ if (j != best_match) {
+ j = best_match;
+ pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname);
+- if (link_stat(cmpbuf, stp, 0) < 0)
++ if (link_stat(cmpbuf, &sxp->st, 0) < 0)
+ return -1;
+ }
+
+@@ -859,16 +874,25 @@ static int try_dests_reg(struct file_str
+ if (!hard_link_one(file, fname, cmpbuf, 1))
+ goto try_a_copy;
+ if (preserve_hard_links && F_IS_HLINKED(file))
+- finish_hard_link(file, fname, stp, itemizing, code, j);
++ finish_hard_link(file, fname, &sxp->st, itemizing, code, j);
+ if (itemizing && (verbose > 1 || stdout_format_has_i > 1)) {
+- itemize(file, ndx, 1, stp,
++#ifdef SUPPORT_ACLS
++ if (preserve_acls && !ACL_READY(*sxp))
++ get_acl(fname, sxp);
++#endif
++ itemize(file, ndx, 1, sxp,
+ ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS,
+ 0, "");
+ }
+ } else
+ #endif
+- if (itemizing)
+- itemize(file, ndx, 0, stp, 0, 0, NULL);
++ if (itemizing) {
++#ifdef SUPPORT_ACLS
++ if (preserve_acls && !ACL_READY(*sxp))
++ get_acl(fname, sxp);
++#endif
++ itemize(file, ndx, 0, sxp, 0, 0, NULL);
++ }
+ if (verbose > 1 && maybe_ATTRS_REPORT)
+ rprintf(FCLIENT, "%s is uptodate\n", fname);
+ return -2;
+@@ -885,8 +909,13 @@ static int try_dests_reg(struct file_str
+ }
+ return -1;
+ }
+- if (itemizing)
+- itemize(file, ndx, 0, stp, ITEM_LOCAL_CHANGE, 0, NULL);
++ if (itemizing) {
++#ifdef SUPPORT_ACLS
++ if (preserve_acls && !ACL_READY(*sxp))
++ get_acl(fname, sxp);
++#endif
++ itemize(file, ndx, 0, sxp, ITEM_LOCAL_CHANGE, 0, NULL);
++ }
+ set_file_attrs(fname, file, NULL, 0);
+ if (maybe_ATTRS_REPORT
+ && ((!itemizing && verbose && match_level == 2)
+@@ -897,7 +926,7 @@ static int try_dests_reg(struct file_str
+ }
+ #ifdef SUPPORT_HARD_LINKS
+ if (preserve_hard_links && F_IS_HLINKED(file))
+- finish_hard_link(file, fname, stp, itemizing, code, -1);
++ finish_hard_link(file, fname, &sxp->st, itemizing, code, -1);
+ #endif
+ return -2;
+ }
+@@ -909,7 +938,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,
+- char *cmpbuf, STRUCT_STAT *stp, int itemizing,
++ char *cmpbuf, statx *sxp, int itemizing,
+ enum logcode code)
+ {
+ char lnk[MAXPATHLEN];
+@@ -942,24 +971,24 @@ static int try_dests_non(struct file_str
+
+ do {
+ pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname);
+- if (link_stat(cmpbuf, stp, 0) < 0)
++ if (link_stat(cmpbuf, &sxp->st, 0) < 0)
+ continue;
+ switch (type) {
+ case TYPE_DIR:
+- if (!S_ISDIR(stp->st_mode))
++ if (!S_ISDIR(sxp->st.st_mode))
+ continue;
+ break;
+ case TYPE_SPECIAL:
+- if (!IS_SPECIAL(stp->st_mode))
++ if (!IS_SPECIAL(sxp->st.st_mode))
+ continue;
+ break;
+ case TYPE_DEVICE:
+- if (!IS_DEVICE(stp->st_mode))
++ if (!IS_DEVICE(sxp->st.st_mode))
+ continue;
+ break;
+ #ifdef SUPPORT_LINKS
+ case TYPE_SYMLINK:
+- if (!S_ISLNK(stp->st_mode))
++ if (!S_ISLNK(sxp->st.st_mode))
+ continue;
+ break;
+ #endif
+@@ -974,7 +1003,7 @@ static int try_dests_non(struct file_str
+ case TYPE_SPECIAL:
+ case TYPE_DEVICE:
+ devp = F_RDEV_P(file);
+- if (stp->st_rdev != MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp)))
++ if (sxp->st.st_rdev != MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp)))
+ continue;
+ break;
+ #ifdef SUPPORT_LINKS
+@@ -991,7 +1020,11 @@ static int try_dests_non(struct file_str
+ match_level = 2;
+ best_match = j;
+ }
+- if (unchanged_attrs(file, stp)) {
++#ifdef SUPPORT_ACLS
++ if (preserve_acls)
++ get_acl(cmpbuf, sxp);
++#endif
++ if (unchanged_attrs(file, sxp)) {
+ match_level = 3;
+ best_match = j;
+ break;
+@@ -1004,7 +1037,7 @@ static int try_dests_non(struct file_str
+ if (j != best_match) {
+ j = best_match;
+ pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname);
+- if (link_stat(cmpbuf, stp, 0) < 0)
++ if (link_stat(cmpbuf, &sxp->st, 0) < 0)
+ return -1;
+ }
+
+@@ -1035,7 +1068,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;
+- itemize(file, ndx, 0, stp, chg + ITEM_MATCHED, 0, lp);
++#ifdef SUPPORT_ACLS
++ if (preserve_acls)
++ get_acl(fname, sxp);
++#endif
++ itemize(file, ndx, 0, sxp, chg + ITEM_MATCHED, 0, lp);
++#ifdef SUPPORT_ACLS
++ if (preserve_acls)
++ free_acl(sxp);
++#endif
+ }
+ if (verbose > 1 && maybe_ATTRS_REPORT) {
+ rprintf(FCLIENT, "%s%s is uptodate\n",
+@@ -1048,6 +1089,7 @@ static int try_dests_non(struct file_str
+ }
+
+ static int phase = 0;
++static int dflt_perms;
+
+ /* 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
+@@ -1068,7 +1110,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_STAT st, real_st, partial_st;
++ statx sx, real_sx;
++ STRUCT_STAT partial_st;
+ struct file_struct *back_file = NULL;
+ int statret, real_ret, stat_errno;
+ char *fnamecmp, *partialptr, *backupptr = NULL;
+@@ -1124,6 +1167,9 @@ static void recv_generator(char *fname,
+ } else if (!dry_run)
+ return;
+ }
++#ifdef SUPPORT_ACLS
++ sx.acc_acl = sx.def_acl = NULL;
++#endif
+ if (dry_run > 1) {
+ statret = -1;
+ stat_errno = ENOENT;
+@@ -1131,7 +1177,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
+- && do_stat(dn, &st) < 0
++ && do_stat(dn, &sx.st) < 0
+ && create_directory_path(fname) < 0) {
+ rsyserr(FERROR, errno,
+ "recv_generator: mkdir %s failed",
+@@ -1143,6 +1189,10 @@ static void recv_generator(char *fname,
+ }
+ if (fuzzy_basis)
+ need_fuzzy_dirlist = 1;
++#ifdef SUPPORT_ACLS
++ if (!preserve_perms)
++ dflt_perms = default_perms_for_dir(dn);
++#endif
+ }
+ parent_dirname = dn;
+
+@@ -1152,7 +1202,7 @@ static void recv_generator(char *fname,
+ need_fuzzy_dirlist = 0;
+ }
+
+- statret = link_stat(fname, &st,
++ statret = link_stat(fname, &sx.st,
+ keep_dirlinks && S_ISDIR(file->mode));
+ stat_errno = errno;
+ }
+@@ -1170,8 +1220,9 @@ static void recv_generator(char *fname,
+ * mode based on the local permissions and some heuristics. */
+ if (!preserve_perms) {
+ int exists = statret == 0
+- && S_ISDIR(st.st_mode) == S_ISDIR(file->mode);
+- file->mode = dest_mode(file->mode, st.st_mode, exists);
++ && S_ISDIR(sx.st.st_mode) == S_ISDIR(file->mode);
++ file->mode = dest_mode(file->mode, sx.st.st_mode, dflt_perms,
++ exists);
+ }
+
+ if (S_ISDIR(file->mode)) {
+@@ -1180,8 +1231,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. */
+- if (statret == 0 && !S_ISDIR(st.st_mode)) {
+- if (delete_item(fname, st.st_mode, "directory", del_opts) != 0)
++ if (statret == 0 && !S_ISDIR(sx.st.st_mode)) {
++ if (delete_item(fname, sx.st.st_mode, "directory", del_opts) != 0)
+ return;
+ statret = -1;
+ }
+@@ -1190,14 +1241,14 @@ static void recv_generator(char *fname,
+ dry_run++;
+ }
+ real_ret = statret;
+- real_st = st;
++ real_sx = sx;
+ if (new_root_dir) {
+ if (*fname == '.' && fname[1] == '\0')
+ statret = -1;
+ new_root_dir = 0;
+ }
+ if (statret != 0 && basis_dir[0] != NULL) {
+- int j = try_dests_non(file, fname, ndx, fnamecmpbuf, &st,
++ int j = try_dests_non(file, fname, ndx, fnamecmpbuf, &sx,
+ itemizing, code);
+ if (j == -2) {
+ itemizing = 0;
+@@ -1206,7 +1257,11 @@ static void recv_generator(char *fname,
+ statret = 1;
+ }
+ if (itemizing && f_out != -1) {
+- itemize(file, ndx, statret, &st,
++#ifdef SUPPORT_ACLS
++ if (preserve_acls && statret == 0)
++ get_acl(fname, &sx);
++#endif
++ itemize(file, ndx, statret, &sx,
+ statret ? ITEM_LOCAL_CHANGE : 0, 0, NULL);
+ }
+ if (real_ret != 0 && do_mkdir(fname,file->mode) < 0 && errno != EEXIST) {
+@@ -1226,21 +1281,21 @@ static void recv_generator(char *fname,
+ return;
+ }
+ }
+- if (set_file_attrs(fname, file, real_ret ? NULL : &real_st, 0)
++ if (set_file_attrs(fname, file, real_ret ? NULL : &real_sx, 0)
+ && verbose && code != FNONE && f_out != -1)
+ rprintf(code, "%s/\n", fname);
+ if (real_ret != 0 && one_file_system)
+- real_st.st_dev = filesystem_dev;
++ real_sx.st.st_dev = filesystem_dev;
+ if (delete_during && f_out != -1 && !phase && dry_run < 2
+ && (file->flags & FLAG_XFER_DIR))
+- delete_in_dir(the_file_list, fname, file, &real_st);
+- return;
++ delete_in_dir(the_file_list, fname, file, &real_sx.st);
++ goto cleanup;
+ }
+
+ #ifdef SUPPORT_HARD_LINKS
+ if (preserve_hard_links && F_HLINK_NOT_FIRST(file)
+- && hard_link_check(file, ndx, fname, statret, &st, itemizing, code))
+- return;
++ && hard_link_check(file, ndx, fname, statret, &sx, itemizing, code))
++ goto cleanup;
+ #endif
+
+ if (preserve_links && S_ISLNK(file->mode)) {
+@@ -1260,17 +1315,17 @@ static void recv_generator(char *fname,
+ char lnk[MAXPATHLEN];
+ int len;
+
+- if (!S_ISLNK(st.st_mode))
++ if (!S_ISLNK(sx.st.st_mode))
+ statret = -1;
+ else if ((len = readlink(fname, lnk, MAXPATHLEN-1)) > 0
+ && strncmp(lnk, sl, len) == 0 && sl[len] == '\0') {
+ /* The link is pointing to the right place. */
+ if (itemizing)
+- itemize(file, ndx, 0, &st, 0, 0, NULL);
+- set_file_attrs(fname, file, &st, maybe_ATTRS_REPORT);
++ itemize(file, ndx, 0, &sx, 0, 0, NULL);
++ set_file_attrs(fname, file, &sx, maybe_ATTRS_REPORT);
+ #ifdef SUPPORT_HARD_LINKS
+ if (preserve_hard_links && F_IS_HLINKED(file))
+- finish_hard_link(file, fname, &st, itemizing, code, -1);
++ finish_hard_link(file, fname, &sx.st, itemizing, code, -1);
+ #endif
+ if (remove_source_files == 1)
+ goto return_with_success;
+@@ -1278,10 +1333,10 @@ static void recv_generator(char *fname,
+ }
+ /* Not the right symlink (or not a symlink), so
+ * delete it. */
+- if (delete_item(fname, st.st_mode, "symlink", del_opts) != 0)
++ if (delete_item(fname, sx.st.st_mode, "symlink", del_opts) != 0)
+ return;
+ } else if (basis_dir[0] != NULL) {
+- int j = try_dests_non(file, fname, ndx, fnamecmpbuf, &st,
++ int j = try_dests_non(file, fname, ndx, fnamecmpbuf, &sx,
+ itemizing, code);
+ if (j == -2) {
+ #ifndef CAN_HARDLINK_SYMLINK
+@@ -1306,7 +1361,7 @@ static void recv_generator(char *fname,
+ } else {
+ set_file_attrs(fname, file, NULL, 0);
+ if (itemizing) {
+- itemize(file, ndx, statret, &st,
++ itemize(file, ndx, statret, &sx,
+ ITEM_LOCAL_CHANGE, 0, NULL);
+ }
+ if (code != FNONE && verbose)
+@@ -1332,33 +1387,38 @@ static void recv_generator(char *fname,
+ if (statret == 0) {
+ char *t;
+ if (IS_DEVICE(file->mode)) {
+- if (!IS_DEVICE(st.st_mode))
++ if (!IS_DEVICE(sx.st.st_mode))
+ statret = -1;
+ t = "device file";
+ } else {
+- if (!IS_SPECIAL(st.st_mode))
++ if (!IS_SPECIAL(sx.st.st_mode))
+ statret = -1;
+ t = "special file";
+ }
+ if (statret == 0
+- && BITS_EQUAL(st.st_mode, file->mode, _S_IFMT)
+- && st.st_rdev == rdev) {
++ && BITS_EQUAL(sx.st.st_mode, file->mode, _S_IFMT)
++ && sx.st.st_rdev == rdev) {
+ /* The device or special file is identical. */
+- if (itemizing)
+- itemize(file, ndx, 0, &st, 0, 0, NULL);
+- set_file_attrs(fname, file, &st, maybe_ATTRS_REPORT);
++ if (itemizing) {
++#ifdef SUPPORT_ACLS
++ if (preserve_acls)
++ get_acl(fname, &sx);
++#endif
++ itemize(file, ndx, 0, &sx, 0, 0, NULL);
++ }
++ set_file_attrs(fname, file, &sx, maybe_ATTRS_REPORT);
+ #ifdef SUPPORT_HARD_LINKS
+ if (preserve_hard_links && F_IS_HLINKED(file))
+- finish_hard_link(file, fname, &st, itemizing, code, -1);
++ finish_hard_link(file, fname, &sx.st, itemizing, code, -1);
+ #endif
+ if (remove_source_files == 1)
+ goto return_with_success;
+- return;
++ goto cleanup;
+ }
+- if (delete_item(fname, st.st_mode, t, del_opts) != 0)
++ if (delete_item(fname, sx.st.st_mode, t, del_opts) != 0)
+ return;
+ } else if (basis_dir[0] != NULL) {
+- int j = try_dests_non(file, fname, ndx, fnamecmpbuf, &st,
++ int j = try_dests_non(file, fname, ndx, fnamecmpbuf, &sx,
+ itemizing, code);
+ if (j == -2) {
+ #ifndef CAN_HARDLINK_SPECIAL
+@@ -1388,7 +1448,11 @@ static void recv_generator(char *fname,
+ } else {
+ set_file_attrs(fname, file, NULL, 0);
+ if (itemizing) {
+- itemize(file, ndx, statret, &st,
++#ifdef SUPPORT_ACLS
++ if (preserve_acls && statret == 0)
++ get_acl(fname, &sx);
++#endif
++ itemize(file, ndx, statret, &sx,
+ ITEM_LOCAL_CHANGE, 0, NULL);
+ }
+ if (code != FNONE && verbose)
+@@ -1400,7 +1464,7 @@ static void recv_generator(char *fname,
+ if (remove_source_files == 1)
+ goto return_with_success;
+ }
+- return;
++ goto cleanup;
+ }
+
+ if (!S_ISREG(file->mode)) {
+@@ -1434,7 +1498,7 @@ static void recv_generator(char *fname,
+ }
+
+ if (update_only && statret == 0
+- && cmp_time(st.st_mtime, file->modtime) > 0) {
++ && cmp_time(sx.st.st_mtime, file->modtime) > 0) {
+ if (verbose > 1)
+ rprintf(FINFO, "%s is newer\n", fname);
+ return;
+@@ -1443,20 +1507,20 @@ static void recv_generator(char *fname,
+ fnamecmp = fname;
+ fnamecmp_type = FNAMECMP_FNAME;
+
+- if (statret == 0 && !S_ISREG(st.st_mode)) {
+- if (delete_item(fname, st.st_mode, "regular file", del_opts) != 0)
++ if (statret == 0 && !S_ISREG(sx.st.st_mode)) {
++ if (delete_item(fname, sx.st.st_mode, "regular file", del_opts) != 0)
+ return;
+ statret = -1;
+ stat_errno = ENOENT;
+ }
+
+ if (statret != 0 && basis_dir[0] != NULL) {
+- int j = try_dests_reg(file, fname, ndx, fnamecmpbuf, &st,
++ int j = try_dests_reg(file, fname, ndx, fnamecmpbuf, &sx,
+ itemizing, code);
+ if (j == -2) {
+ if (remove_source_files == 1)
+ goto return_with_success;
+- return;
++ goto cleanup;
+ }
+ if (j >= 0) {
+ fnamecmp = fnamecmpbuf;
+@@ -1466,7 +1530,7 @@ static void recv_generator(char *fname,
+ }
+
+ real_ret = statret;
+- real_st = st;
++ real_sx = sx;
+
+ if (partial_dir && (partialptr = partial_dir_fname(fname)) != NULL
+ && link_stat(partialptr, &partial_st, 0) == 0
+@@ -1485,7 +1549,7 @@ static void recv_generator(char *fname,
+ rprintf(FINFO, "fuzzy basis selected for %s: %s\n",
+ fname, fnamecmpbuf);
+ }
+- st.st_size = F_LENGTH(fuzzy_file);
++ sx.st.st_size = F_LENGTH(fuzzy_file);
+ statret = 0;
+ fnamecmp = fnamecmpbuf;
+ fnamecmp_type = FNAMECMP_FUZZY;
+@@ -1504,36 +1568,41 @@ static void recv_generator(char *fname,
+ return;
+ }
+
+- if (append_mode && st.st_size > F_LENGTH(file))
++ if (append_mode && sx.st.st_size > F_LENGTH(file))
+ return;