Added logic to the receiving side to ensure that the --delete-during
[rsync/rsync.git] / rsync.c
diff --git a/rsync.c b/rsync.c
index 302971f..21f5288 100644 (file)
--- a/rsync.c
+++ b/rsync.c
@@ -27,7 +27,6 @@
 #include <langinfo.h>
 #endif
 
-extern int verbose;
 extern int dry_run;
 extern int preserve_acls;
 extern int preserve_xattrs;
@@ -46,8 +45,11 @@ extern int gid_ndx;
 extern int inc_recurse;
 extern int inplace;
 extern int flist_eof;
+extern int msgs2stderr;
 extern int keep_dirlinks;
 extern int make_backups;
+extern int delete_during;
+extern int check_for_io_err;
 extern struct file_list *cur_flist, *first_flist, *dir_flist;
 extern struct chmod_mode_struct *daemon_chmod_modes;
 #ifdef ICONV_OPTION
@@ -80,23 +82,23 @@ void setup_iconv(void)
 # endif
 
        if (!am_server && !allow_8bit_chars) {
-
                /* It's OK if this fails... */
                ic_chck = iconv_open(defset, defset);
 
-               if (verbose > 3) {
+               if (DEBUG_GTE(ICONV, 2)) {
                        if (ic_chck == (iconv_t)-1) {
                                rprintf(FINFO,
-                                       "note: iconv_open(\"%s\", \"%s\") failed (%d)"
-                                       " -- using isprint() instead of iconv().\n",
+                                       "msg checking via isprint()"
+                                       " (iconv_open(\"%s\", \"%s\") errno: %d)\n",
                                        defset, defset, errno);
                        } else {
                                rprintf(FINFO,
-                                       "note: iconv_open(\"%s\", \"%s\") succeeded.\n",
-                                       defset, defset);
+                                       "msg checking charset: %s\n",
+                                       defset);
                        }
                }
-       }
+       } else
+               ic_chck = (iconv_t)-1;
 
 # ifdef ICONV_OPTION
        if (!iconv_opt)
@@ -126,10 +128,9 @@ void setup_iconv(void)
                exit_cleanup(RERR_UNSUPPORTED);
        }
 
-       if (verbose > 1) {
-               rprintf(FINFO, "%s charset: %s\n",
-                       am_server ? "server" : "client",
-                       *charset ? charset : "[LOCALE]");
+       if (DEBUG_GTE(ICONV, 1)) {
+               rprintf(FINFO, "[%s] charset: %s\n",
+                       who_am_i(), *charset ? charset : "[LOCALE]");
        }
 # endif
 }
@@ -205,20 +206,63 @@ int iconvbufs(iconv_t ic, xbuf *in, xbuf *out, int flags)
 }
 #endif
 
+void send_protected_args(int fd, char *args[])
+{
+       int i;
+#ifdef ICONV_OPTION
+       int convert = ic_send != (iconv_t)-1;
+       xbuf outbuf, inbuf;
+
+       if (convert)
+               alloc_xbuf(&outbuf, 1024);
+#endif
+
+       for (i = 0; args[i]; i++) {} /* find first NULL */
+       args[i] = "rsync"; /* set a new arg0 */
+       if (DEBUG_GTE(CMD, 1))
+               print_child_argv("protected args:", args + i + 1);
+       do {
+#ifdef ICONV_OPTION
+               if (convert) {
+                       INIT_XBUF_STRLEN(inbuf, args[i]);
+                       iconvbufs(ic_send, &inbuf, &outbuf,
+                                 ICB_EXPAND_OUT | ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE);
+                       outbuf.buf[outbuf.len] = '\0';
+                       write_buf(fd, outbuf.buf, outbuf.len + 1);
+                       outbuf.len = 0;
+               } else
+#endif
+                       write_buf(fd, args[i], strlen(args[i]) + 1);
+       } while (args[++i]);
+       write_byte(fd, 0);
+
+#ifdef ICONV_OPTION
+       if (convert)
+               free(outbuf.buf);
+#endif
+}
+
 int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr,
                       char *buf, int *len_ptr)
 {
        int len, iflags = 0;
        struct file_list *flist;
        uchar fnamecmp_type = FNAMECMP_FNAME;
-       int ndx, save_verbose = verbose;
+       int ndx;
 
   read_loop:
        while (1) {
                ndx = read_ndx(f_in);
 
-               if (ndx >= 0)
+               if (ndx >= 0) {
+                       if (check_for_io_err) {
+                               /* Let generator know there was no I/O error. */
+                               send_msg_int(MSG_IO_ERROR, 0);
+                               check_for_io_err = 0;
+                       }
                        break;
+               }
+               check_for_io_err = 0;
                if (ndx == NDX_DONE)
                        return ndx;
                if (!inc_recurse || am_sender)
@@ -239,17 +283,23 @@ int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr,
                }
 
                /* Send everything read from f_in to msg_fd_out. */
-               if (verbose > 3) {
+               if (DEBUG_GTE(FLIST, 2)) {
                        rprintf(FINFO, "[%s] receiving flist for dir %d\n",
                                who_am_i(), ndx);
                }
-               verbose = 0;
+               if (!msgs2stderr)
+                       negate_output_levels(); /* turn off all info/debug output */
                send_msg_int(MSG_FLIST, ndx);
                start_flist_forward(f_in);
                flist = recv_file_list(f_in);
                flist->parent_ndx = ndx;
                stop_flist_forward();
-               verbose = save_verbose;
+               if (!msgs2stderr)
+                       negate_output_levels(); /* restore info/debug output */
+               /* If the sender is going to send us an MSG_IO_ERROR value, it
+                * will always be the very next message following a file list. */
+               if (delete_during)
+                       check_for_io_err = 1;
        }
 
        iflags = protocol_version >= 29 ? read_shortint(f_in)
@@ -412,7 +462,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
        } else
 #endif
        if (change_uid || change_gid) {
-               if (verbose > 2) {
+               if (DEBUG_GTE(OWN, 1)) {
                        if (change_uid) {
                                rprintf(FINFO,
                                        "set uid of %s from %u to %u\n",
@@ -471,7 +521,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
        }
 #endif
 
-       if (verbose > 1 && flags & ATTRS_REPORT) {
+       if (INFO_GTE(NAME, 2) && flags & ATTRS_REPORT) {
                if (updated)
                        rprintf(FCLIENT, "%s\n", fname);
                else
@@ -519,21 +569,25 @@ int finish_transfer(const char *fname, const char *fnametmp,
        const char *temp_copy_name = partialptr && *partialptr != '/' ? partialptr : NULL;
 
        if (inplace) {
-               if (verbose > 2)
+               if (DEBUG_GTE(RECV, 1))
                        rprintf(FINFO, "finishing %s\n", fname);
                fnametmp = fname;
                goto do_set_file_attrs;
        }
 
-       if (make_backups > 0 && overwriting_basis && !make_backup(fname))
-               return 1;
+       if (make_backups > 0 && overwriting_basis) {
+               if (!make_backup(fname))
+                       return 1;
+               if (fnamecmp == fname)
+                       fnamecmp = get_backup_name(fname);
+       }
 
        /* Change permissions before putting the file into place. */
        set_file_attrs(fnametmp, file, NULL, fnamecmp,
                       ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
 
        /* move tmp file over real file */
-       if (verbose > 2)
+       if (DEBUG_GTE(RECV, 1))
                rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname);
        ret = robust_rename(fnametmp, fname, temp_copy_name,
                            file->mode & INITACCESSPERMS);