My version of Matt's improvements related to missing source args:
[rsync/rsync.git] / flist.c
diff --git a/flist.c b/flist.c
index 7d01c9c..09b4fc5 100644 (file)
--- a/flist.c
+++ b/flist.c
@@ -51,7 +51,7 @@ extern int preserve_links;
 extern int preserve_hard_links;
 extern int preserve_devices;
 extern int preserve_specials;
-extern int delete_missing_args;
+extern int missing_args;
 extern int uid_ndx;
 extern int gid_ndx;
 extern int eol_nulls;
@@ -794,7 +794,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
        if (!(xflags & XMIT_SAME_MODE))
                mode = from_wire_mode(read_int(f));
 
-       if (chmod_modes && !S_ISLNK(mode))
+       if (chmod_modes && !S_ISLNK(mode) && mode)
                mode = tweak_mode(mode, chmod_modes);
 
        if (preserve_uid && !(xflags & XMIT_SAME_UID)) {
@@ -1372,7 +1372,7 @@ static struct file_struct *send_file_name(int f, struct file_list *flist,
        if (!file)
                return NULL;
 
-       if (chmod_modes && !S_ISLNK(file->mode))
+       if (chmod_modes && !S_ISLNK(file->mode) && file->mode)
                file->mode = tweak_mode(file->mode, chmod_modes);
 
        if (f >= 0) {
@@ -2177,19 +2177,26 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
                if (link_stat(fbuf, &st, copy_dirlinks || name_type != NORMAL_NAME) != 0
                 || (name_type != DOTDIR_NAME && is_daemon_excluded(fbuf, S_ISDIR(st.st_mode)))
                 || (relative_paths && path_is_daemon_excluded(fbuf, 1))) {
-                       if (errno == ENOENT && delete_missing_args) {
-                               /* Rsync will treat a mode of 0 as deleted. */
-                               memset(&st, 0, sizeof st);
-                       } else {
-                               io_error |= IOERR_GENERAL;
+                       if (errno != ENOENT || missing_args == 0) {
+                               /* This is a transfer error, but inhibit deletion
+                                * only if we might be omitting an existing file. */
+                               if (errno != ENOENT)
+                                       io_error |= IOERR_GENERAL;
                                rsyserr(FERROR_XFER, errno, "link_stat %s failed",
                                        full_fname(fbuf));
                                continue;
+                       } else if (missing_args == 1) {
+                               /* Just ignore the arg. */
+                               continue;
+                       } else /* (missing_args == 2) */ {
+                               /* Send the arg as a "missing" entry with
+                                * mode 0, which tells the generator to delete it. */
+                               memset(&st, 0, sizeof st);
                        }
                }
 
                /* A dot-dir should not be excluded! */
-               if (name_type != DOTDIR_NAME
+               if (name_type != DOTDIR_NAME && st.st_mode != 0
                 && is_excluded(fbuf, S_ISDIR(st.st_mode) != 0, ALL_FILTERS))
                        continue;