Added an extra phase to the end of the transfer to handle
[rsync/rsync.git] / receiver.c
index d89348d..ff02e20 100644 (file)
@@ -303,28 +303,44 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
 }
 
 
-static char *read_gen_name(int fd, char *dirname, char *buf)
+static void discard_receive_data(int f_in, OFF_T length)
 {
-       int dlen;
-
-       if (dirname) {
-               dlen = strlcpy(buf, dirname, MAXPATHLEN);
-               if (dlen != 1 || *buf != '/')
-                       buf[dlen++] = '/';
-       } else
-               dlen = 0;
-
-       if (read_vstring(fd, buf + dlen, MAXPATHLEN - dlen) < 0)
-               return NULL;
-       if (strchr(buf + dlen, '/') != NULL)
-               return NULL;
-       return buf;
+       receive_data(f_in, NULL, -1, 0, NULL, -1, length);
 }
 
-
-static void discard_receive_data(int f_in, OFF_T length)
+static void handle_delayed_updates(struct file_list *flist, char *local_name)
 {
-       receive_data(f_in, NULL, -1, 0, NULL, -1, length);
+       char *fname, *partialptr, numbuf[4];
+       int i;
+
+       for (i = -1; (i = next_delayed_bit(i)) >= 0; ) {
+               struct file_struct *file = flist->files[i];
+               fname = local_name ? local_name : f_name(file);
+               if ((partialptr = partial_dir_fname(fname)) != NULL) {
+                       if (make_backups && !make_backup(fname))
+                               continue;
+                       if (verbose > 2) {
+                               rprintf(FINFO, "renaming %s to %s\n",
+                                       safe_fname(partialptr),
+                                       safe_fname(fname));
+                       }
+                       if (do_rename(partialptr, fname) < 0) {
+                               rsyserr(FERROR, errno,
+                                       "rename failed for %s (from %s)",
+                                       full_fname(fname),
+                                       safe_fname(partialptr));
+                       } else {
+                               if (remove_sent_files
+                                   || (preserve_hard_links
+                                    && file->link_u.links)) {
+                                       SIVAL(numbuf, 0, i);
+                                       send_msg(MSG_SUCCESS,numbuf,4);
+                               }
+                               handle_partial_dir(partialptr,
+                                                  PDIR_DELETE);
+                       }
+               }
+       }
 }
 
 
@@ -337,9 +353,9 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
        int next_gen_i = -1;
        int fd1,fd2;
        STRUCT_STAT st;
-       int iflags;
+       int iflags, xlen;
        char *fname, fbuf[MAXPATHLEN];
-       char template[MAXPATHLEN];
+       char xname[MAXPATHLEN];
        char fnametmp[MAXPATHLEN];
        char *fnamecmp, *partialptr, numbuf[4];
        char fnamecmpbuf[MAXPATHLEN];
@@ -349,7 +365,8 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
        int save_make_backups = make_backups;
        int itemizing = am_daemon ? daemon_log_format_has_i
                      : !am_server && log_format_has_i;
-       int i, recv_ok, phase = 0;
+       int phase = 0, max_phase = protocol_version >= 29 ? 2 : 1;
+       int i, recv_ok;
 
        if (verbose > 2)
                rprintf(FINFO,"recv_files(%d) starting\n",flist->count);
@@ -372,21 +389,21 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
                                        while (read_int(batch_gen_fd) != -1) {}
                                next_gen_i = -1;
                        }
-
-                       if (phase)
+                       if (++phase > max_phase)
                                break;
-
-                       phase = 1;
                        csum_length = SUM_LENGTH;
                        if (verbose > 2)
                                rprintf(FINFO, "recv_files phase=%d\n", phase);
+                       if (phase == 2 && delay_updates)
+                               handle_delayed_updates(flist, local_name);
                        send_msg(MSG_DONE, "", 0);
                        if (keep_partial && !partial_dir)
                                make_backups = 0; /* prevents double backup */
                        continue;
                }
 
-               iflags = read_item_attrs(f_in, -1, i, fnametmp, &fnamecmp_type);
+               iflags = read_item_attrs(f_in, -1, i, &fnamecmp_type,
+                                        xname, &xlen);
                if (iflags == ITEM_IS_NEW) /* no-op packet */
                        continue;
 
@@ -397,9 +414,15 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
                        rprintf(FINFO, "recv_files(%s)\n", safe_fname(fname));
 
                if (!(iflags & ITEM_TRANSFER)) {
-                       maybe_log_item(file, iflags, itemizing, fnametmp);
+                       maybe_log_item(file, iflags, itemizing, xname);
                        continue;
                }
+               if (phase == 2) {
+                       rprintf(FERROR,
+                               "got transfer request in phase 2 [%s]\n",
+                               who_am_i());
+                       exit_cleanup(RERR_PROTOCOL);
+               }
 
                stats.current_file_index = i;
                stats.num_transferred_files++;
@@ -447,8 +470,12 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
                                fnamecmp = get_backup_name(fname);
                                break;
                        case FNAMECMP_FUZZY:
-                               fnamecmp = read_gen_name(f_in, file->dirname,
-                                                        fnamecmpbuf);
+                               if (file->dirname) {
+                                       pathjoin(fnamecmpbuf, MAXPATHLEN,
+                                                file->dirname, xname);
+                                       fnamecmp = fnamecmpbuf;
+                               } else
+                                       fnamecmp = xname;
                                break;
                        default:
                                if (fnamecmp_type >= basis_dir_cnt) {
@@ -549,8 +576,6 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
                                continue;
                        }
 
-                       strlcpy(template, fnametmp, sizeof template);
-
                        /* we initially set the perms without the
                         * setuid/setgid bits to ensure that there is no race
                         * condition. They are then correctly updated after
@@ -564,7 +589,8 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
                         * transferred, but that may not be the case with -R */
                        if (fd2 == -1 && relative_paths && errno == ENOENT
                            && create_directory_path(fnametmp, orig_umask) == 0) {
-                               strlcpy(fnametmp, template, sizeof fnametmp);
+                               /* Get back to name with XXXXXX in it. */
+                               get_tmpname(fnametmp, fname);
                                fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
                        }
                        if (fd2 == -1) {
@@ -658,37 +684,8 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
        }
        make_backups = save_make_backups;
 
-       if (delay_updates) {
-               for (i = -1; (i = next_delayed_bit(i)) >= 0; ) {
-                       struct file_struct *file = flist->files[i];
-                       fname = local_name ? local_name : f_name(file);
-                       partialptr = partial_dir_fname(fname);
-                       if (partialptr) {
-                               if (make_backups && !make_backup(fname))
-                                       continue;
-                               if (verbose > 2) {
-                                       rprintf(FINFO, "renaming %s to %s\n",
-                                               safe_fname(partialptr),
-                                               safe_fname(fname));
-                               }
-                               if (do_rename(partialptr, fname) < 0) {
-                                       rsyserr(FERROR, errno,
-                                               "rename failed for %s (from %s)",
-                                               full_fname(fname),
-                                               safe_fname(partialptr));
-                               } else {
-                                       if (remove_sent_files
-                                           || (preserve_hard_links
-                                            && file->link_u.links)) {
-                                               SIVAL(numbuf, 0, i);
-                                               send_msg(MSG_SUCCESS,numbuf,4);
-                                       }
-                                       handle_partial_dir(partialptr,
-                                                          PDIR_DELETE);
-                               }
-                       }
-               }
-       }
+       if (phase == 2 && delay_updates) /* for protocol_version < 29 */
+               handle_delayed_updates(flist, local_name);
 
        if (verbose > 2)
                rprintf(FINFO,"recv_files finished\n");