+@@ -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;
+
+ if (fnamecmp_type <= FNAMECMP_BASIS_DIR_HIGH)
+ ;
+ else if (fnamecmp_type == FNAMECMP_FUZZY)
+ ;
+- else if (unchanged_file(fnamecmp, file, &st)) {
++ else if (unchanged_file(fnamecmp, file, &sx.st)) {
+ if (partialptr) {
+ do_unlink(partialptr);
+ handle_partial_dir(partialptr, PDIR_DELETE);
+ }
+- if (itemizing)
+- itemize(file, ndx, statret, &st, 0, 0, NULL);
+- set_file_attrs(fname, file, &st, maybe_ATTRS_REPORT);
++ if (itemizing) {
++#ifdef SUPPORT_ACLS
++ if (preserve_acls && statret == 0)
++ get_acl(fnamecmp, &sx);
++#endif
++ itemize(file, ndx, statret, &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)
+- return;
++ goto cleanup;
+ return_with_success:
+ if (!dry_run)
+ send_msg_int(MSG_SUCCESS, ndx);
+- return;
++ goto cleanup;
+ }
+
+ prepare_to_open:
+ if (partialptr) {
+- st = partial_st;
++ sx.st = partial_st;
+ fnamecmp = partialptr;
+ fnamecmp_type = FNAMECMP_PARTIAL_DIR;
+ statret = 0;
+@@ -1558,16 +1627,20 @@ static void recv_generator(char *fname,
+ /* pretend the file didn't exist */
+ #ifdef SUPPORT_HARD_LINKS
+ if (preserve_hard_links && F_HLINK_NOT_LAST(file))
+- return;
++ goto cleanup;
+ #endif
+ statret = real_ret = -1;
++#ifdef SUPPORT_ACLS
++ if (preserve_acls && ACL_READY(sx))
++ free_acl(&sx);
++#endif
+ goto notify_others;
+ }
+
+ if (inplace && make_backups && fnamecmp_type == FNAMECMP_FNAME) {
+ if (!(backupptr = get_backup_name(fname))) {
+ close(fd);
+- return;
++ goto cleanup;
+ }
+ if (!(back_file = make_file(fname, NULL, NULL, 0, NO_FILTERS))) {
+ close(fd);
+@@ -1578,7 +1651,7 @@ static void recv_generator(char *fname,
+ full_fname(backupptr));
+ unmake_file(back_file);
+ close(fd);
+- return;
++ goto cleanup;
+ }
+ if ((f_copy = do_open(backupptr,
+ O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0) {
+@@ -1586,14 +1659,14 @@ static void recv_generator(char *fname,
+ full_fname(backupptr));
+ unmake_file(back_file);
+ close(fd);
+- return;
++ goto cleanup;
+ }
+ fnamecmp_type = FNAMECMP_BACKUP;
+ }
+
+ if (verbose > 3) {
+ rprintf(FINFO, "gen mapped %s of size %.0f\n",
+- fnamecmp, (double)st.st_size);
++ fnamecmp, (double)sx.st.st_size);
+ }
+
+ if (verbose > 2)
+@@ -1615,26 +1688,34 @@ static void recv_generator(char *fname,
+ iflags |= ITEM_BASIS_TYPE_FOLLOWS;
+ if (fnamecmp_type == FNAMECMP_FUZZY)
+ iflags |= ITEM_XNAME_FOLLOWS;
+- itemize(file, -1, real_ret, &real_st, iflags, fnamecmp_type,
++#ifdef SUPPORT_ACLS
++ if (preserve_acls && real_ret == 0)
++ get_acl(fnamecmp, &real_sx);
++#endif
++ itemize(file, -1, real_ret, &real_sx, iflags, fnamecmp_type,
+ fuzzy_file ? fuzzy_file->basename : NULL);
++#ifdef SUPPORT_ACLS
++ if (preserve_acls)
++ free_acl(&real_sx);
++#endif
+ }
+
+ if (!do_xfers) {
+ #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
+- return;
++ goto cleanup;
+ }
+ if (read_batch)
+- return;
++ goto cleanup;
+
+ if (statret != 0 || whole_file) {
+ write_sum_head(f_out, NULL);
+- return;
++ goto cleanup;
+ }
+
+- generate_and_send_sums(fd, st.st_size, f_out, f_copy);
++ generate_and_send_sums(fd, sx.st.st_size, f_out, f_copy);
+
+ if (f_copy >= 0) {
+ close(f_copy);
+@@ -1647,6 +1728,13 @@ static void recv_generator(char *fname,
+ }
+
+ close(fd);
++
++ cleanup:
++#ifdef SUPPORT_ACLS
++ if (preserve_acls)
++ free_acl(&sx);
++#endif
++ return;
+ }
+
+ void generate_files(int f_out, struct file_list *flist, char *local_name)
+@@ -1713,6 +1801,8 @@ void generate_files(int f_out, struct fi