Document the new --partial-dir option.
[rsync/rsync.git] / receiver.c
index 6f2e2f5..35f964e 100644 (file)
@@ -28,6 +28,8 @@ extern int max_delete;
 extern int csum_length;
 extern struct stats stats;
 extern int dry_run;
+extern int read_batch;
+extern int batch_gen_fd;
 extern int am_server;
 extern int relative_paths;
 extern int keep_dirlinks;
@@ -60,7 +62,7 @@ static void delete_one(char *fn, int is_dir)
                        rsyserr(FERROR, errno, "delete_one: unlink %s failed",
                                full_fname(fn));
                } else if (verbose)
-                       rprintf(FINFO, "deleting %s\n", fn);
+                       rprintf(FINFO, "deleting %s\n", safe_fname(fn));
        } else {
                if (do_rmdir(fn) != 0) {
                        if (errno == ENOTDIR && keep_dirlinks) {
@@ -72,8 +74,10 @@ static void delete_one(char *fn, int is_dir)
                                        "delete_one: rmdir %s failed",
                                        full_fname(fn));
                        }
-               } else if (verbose)
-                       rprintf(FINFO, "deleting directory %s\n", fn);
+               } else if (verbose) {
+                       rprintf(FINFO, "deleting directory %s\n",
+                               safe_fname(fn));
+               }
        }
 }
 
@@ -113,7 +117,7 @@ void delete_files(struct file_list *flist)
                        continue;
 
                if (verbose > 1)
-                       rprintf(FINFO, "deleting in %s\n", fbuf);
+                       rprintf(FINFO, "deleting in %s\n", safe_fname(fbuf));
 
                for (i = local_file_list->count-1; i >= 0; i--) {
                        if (max_delete && deletion_count > max_delete)
@@ -124,8 +128,10 @@ void delete_files(struct file_list *flist)
                                char *f = f_name(local_file_list->files[i]);
                                if (make_backups && (backup_dir || !is_backup_file(f))) {
                                        make_backup(f);
-                                       if (verbose)
-                                               rprintf(FINFO, "deleting %s\n", f);
+                                       if (verbose) {
+                                               rprintf(FINFO, "deleting %s\n",
+                                                       safe_fname(f));
+                                       }
                                } else {
                                        int mode = local_file_list->files[i]->mode;
                                        delete_one(f, S_ISDIR(mode) != 0);
@@ -199,21 +205,31 @@ static int get_tmpname(char *fnametmp, char *fname)
 }
 
 
-static int receive_data(int f_in,struct map_struct *mapbuf,int fd,char *fname,
-                       OFF_T total_size)
+static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
+                       char *fname, int fd, OFF_T total_size)
 {
-       int i;
+       static char file_sum1[MD4_SUM_LENGTH];
+       static char file_sum2[MD4_SUM_LENGTH];
+       struct map_struct *mapbuf;
        struct sum_struct sum;
        unsigned int len;
        OFF_T offset = 0;
        OFF_T offset2;
        char *data;
-       static char file_sum1[MD4_SUM_LENGTH];
-       static char file_sum2[MD4_SUM_LENGTH];
+       int i;
        char *map = NULL;
 
        read_sum_head(f_in, &sum);
 
+       if (fd_r >= 0 && size_r > 0) {
+               mapbuf = map_file(fd_r, size_r, sum.blength);
+               if (verbose > 2) {
+                       rprintf(FINFO, "recv mapped %s of size %.0f\n",
+                               safe_fname(fname_r), (double)size_r);
+               }
+       } else
+               mapbuf = NULL;
+
        sum_init(checksum_seed);
 
        while ((i = recv_token(f_in, &data)) != 0) {
@@ -231,11 +247,8 @@ static int receive_data(int f_in,struct map_struct *mapbuf,int fd,char *fname,
 
                        sum_update(data,i);
 
-                       if (fd != -1 && write_file(fd,data,i) != i) {
-                               rsyserr(FERROR, errno, "write failed on %s",
-                                       full_fname(fname));
-                               exit_cleanup(RERR_FILEIO);
-                       }
+                       if (fd != -1 && write_file(fd,data,i) != i)
+                               goto report_write_error;
                        offset += i;
                        continue;
                }
@@ -259,27 +272,29 @@ static int receive_data(int f_in,struct map_struct *mapbuf,int fd,char *fname,
                        sum_update(map,len);
                }
 
-               if (!inplace || offset != offset2) {
-                       if (fd != -1 && write_file(fd, map, len) != (int)len) {
-                               rsyserr(FERROR, errno, "write failed on %s",
-                                       full_fname(fname));
-                               exit_cleanup(RERR_FILEIO);
-                       }
-               } else {
-                       flush_write_file(fd);
-                       if (do_lseek(fd,(OFF_T)len,SEEK_CUR) != offset+len) {
-                               rprintf(FERROR, "lseek failed on %s: %s, %lli, %lli, %i\n",
-                                       full_fname(fname), strerror(errno), do_lseek(fd,0,SEEK_CUR), (offset+len), i);
-                               exit_cleanup(RERR_FILEIO);
+               if (inplace) {
+                       if (offset == offset2 && fd != -1) {
+                               if (flush_write_file(fd) < 0)
+                                       goto report_write_error;
+                               offset += len;
+                               if (do_lseek(fd, len, SEEK_CUR) != offset) {
+                                       rsyserr(FERROR, errno,
+                                               "lseek failed on %s",
+                                               full_fname(fname));
+                                       exit_cleanup(RERR_FILEIO);
+                               }
+                               continue;
                        }
                }
+               if (fd != -1 && write_file(fd, map, len) != (int)len)
+                       goto report_write_error;
                offset += len;
        }
 
        flush_write_file(fd);
 
 #ifdef HAVE_FTRUNCATE
-       if (inplace)
+       if (inplace && fd != -1)
                ftruncate(fd, offset);
 #endif
 
@@ -287,6 +302,7 @@ static int receive_data(int f_in,struct map_struct *mapbuf,int fd,char *fname,
                end_progress(total_size);
 
        if (fd != -1 && offset > 0 && sparse_end(fd) != 0) {
+           report_write_error:
                rsyserr(FERROR, errno, "write failed on %s",
                        full_fname(fname));
                exit_cleanup(RERR_FILEIO);
@@ -294,6 +310,9 @@ static int receive_data(int f_in,struct map_struct *mapbuf,int fd,char *fname,
 
        sum_end(file_sum1);
 
+       if (mapbuf)
+               unmap_file(mapbuf);
+
        read_buf(f_in,file_sum2,MD4_SUM_LENGTH);
        if (verbose > 2)
                rprintf(FINFO,"got file_sum\n");
@@ -305,7 +324,7 @@ static int receive_data(int f_in,struct map_struct *mapbuf,int fd,char *fname,
 
 static void discard_receive_data(int f_in, OFF_T length)
 {
-       receive_data(f_in, NULL, -1, NULL, length);
+       receive_data(f_in, NULL, -1, 0, NULL, -1, length);
 }
 
 
@@ -315,6 +334,7 @@ static void discard_receive_data(int f_in, OFF_T length)
  * Receiver process runs on the same host as the generator process. */
 int recv_files(int f_in, struct file_list *flist, char *local_name)
 {
+       int next_gen_i = -1;
        int fd1,fd2;
        STRUCT_STAT st;
        char *fname, fbuf[MAXPATHLEN];
@@ -322,7 +342,6 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
        char fnametmp[MAXPATHLEN];
        char *fnamecmp;
        char fnamecmpbuf[MAXPATHLEN];
-       struct map_struct *mapbuf;
        struct file_struct *file;
        struct stats initial_stats;
        int save_make_backups = make_backups;
@@ -341,6 +360,12 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
 
                i = read_int(f_in);
                if (i == -1) {
+                       if (read_batch) {
+                               if (next_gen_i != flist->count)
+                                       while (read_int(batch_gen_fd) != -1) {}
+                               next_gen_i = -1;
+                       }
+
                        if (phase)
                                break;
 
@@ -373,25 +398,39 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
                        fname = f_name_to(file, fbuf);
 
                if (dry_run) {
-                       if (!am_server && verbose)
-                               rprintf(FINFO, "%s\n", fname);
+                       if (!am_server && verbose) /* log the transfer */
+                               rprintf(FINFO, "%s\n", safe_fname(fname));
                        continue;
                }
 
                initial_stats = stats;
 
                if (verbose > 2)
-                       rprintf(FINFO,"recv_files(%s)\n",fname);
+                       rprintf(FINFO, "recv_files(%s)\n", safe_fname(fname));
 
                fnamecmp = fname;
 
+               if (read_batch) {
+                       while (i > next_gen_i) {
+                               next_gen_i = read_int(batch_gen_fd);
+                               if (next_gen_i == -1)
+                                       next_gen_i = flist->count;
+                       }
+                       if (i < next_gen_i) {
+                               rprintf(FINFO, "skipping update for \"%s\"\n",
+                                       safe_fname(fname));
+                               discard_receive_data(f_in, file->length);
+                               continue;
+                       }
+               }
+
                if (server_exclude_list.head
                    && check_exclude(&server_exclude_list, fname,
                                     S_ISDIR(file->mode)) < 0) {
                        if (verbose) {
                                rprintf(FINFO,
                                        "skipping server-excluded update for \"%s\"\n",
-                                       fname);
+                                       safe_fname(fname));
                        }
                        discard_receive_data(f_in, file->length);
                        continue;
@@ -432,7 +471,6 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
                if (fd1 != -1 && !S_ISREG(st.st_mode)) {
                        close(fd1);
                        fd1 = -1;
-                       mapbuf = NULL;
                }
 
                if (fd1 != -1 && !preserve_perms) {
@@ -442,15 +480,6 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
                        file->mode = st.st_mode;
                }
 
-               if (fd1 != -1 && st.st_size > 0) {
-                       mapbuf = map_file(fd1,st.st_size);
-                       if (verbose > 2) {
-                               rprintf(FINFO, "recv mapped %s of size %.0f\n",
-                                       fnamecmp, (double)st.st_size);
-                       }
-               } else
-                       mapbuf = NULL;
-
                /* We now check to see if we are writing file "inplace" */
                if (inplace)  {
                        fd2 = do_open(fnamecmp, O_WRONLY|O_CREAT, 0);
@@ -458,8 +487,6 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
                                rsyserr(FERROR, errno, "open %s failed",
                                        full_fname(fnamecmp));
                                discard_receive_data(f_in, file->length);
-                               if (mapbuf)
-                                       unmap_file(mapbuf);
                                if (fd1 != -1)
                                        close(fd1);
                                continue;
@@ -467,8 +494,6 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
                } else {
                        if (!get_tmpname(fnametmp,fname)) {
                                discard_receive_data(f_in, file->length);
-                               if (mapbuf)
-                                       unmap_file(mapbuf);
                                if (fd1 != -1)
                                        close(fd1);
                                continue;
@@ -496,26 +521,23 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
                                rsyserr(FERROR, errno, "mkstemp %s failed",
                                        full_fname(fnametmp));
                                discard_receive_data(f_in, file->length);
-                               if (mapbuf)
-                                       unmap_file(mapbuf);
                                if (fd1 != -1)
                                        close(fd1);
                                continue;
                        }
 
-                       cleanup_set(fnametmp, fname, file, mapbuf, fd1, fd2);
+                       cleanup_set(fnametmp, fname, file, fd1, fd2);
                }
 
-               if (!am_server && verbose)
-                       rprintf(FINFO, "%s\n", fname);
+               if (!am_server && verbose) /* log the transfer */
+                       rprintf(FINFO, "%s\n", safe_fname(fname));
 
                /* recv file data */
-               recv_ok = receive_data(f_in,mapbuf,fd2,fname,file->length);
+               recv_ok = receive_data(f_in, fnamecmp, fd1, st.st_size,
+                                      fname, fd2, file->length);
 
                log_recv(file, &initial_stats);
 
-               if (mapbuf)
-                       unmap_file(mapbuf);
                if (fd1 != -1)
                        close(fd1);
                if (close(fd2) < 0) {
@@ -524,7 +546,7 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
                        exit_cleanup(RERR_FILEIO);
                }
 
-               if (recv_ok || keep_partial)
+               if (recv_ok || keep_partial || inplace)
                        finish_transfer(fname, fnametmp, file, recv_ok);
                else
                        do_unlink(fnametmp);
@@ -532,13 +554,26 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
                cleanup_disable();
 
                if (!recv_ok) {
-                       if (csum_length == SUM_LENGTH) {
-                               rprintf(FERROR,"ERROR: file corruption in %s. File changed during transfer?\n",
-                                       full_fname(fname));
-                       } else {
+                       int msgtype = csum_length == SUM_LENGTH || read_batch ?
+                               FERROR : FINFO;
+                       if (msgtype == FERROR || verbose) {
+                               char *errstr, *redostr;
+                               char *keptstr = keep_partial || inplace ?
+                                       "retain" : "discard";
+                               if (msgtype == FERROR) {
+                                       errstr = "ERROR";
+                                       redostr = "";
+                               } else {
+                                       errstr = "WARNING";
+                                       redostr = " (will try again)";
+                               }
+                               rprintf(msgtype,
+                                       "%s: %s failed verification -- update %sed%s.\n",
+                                       errstr, safe_fname(fname),
+                                       keptstr, redostr);
+                       }
+                       if (csum_length != SUM_LENGTH) {
                                char buf[4];
-                               if (verbose > 1)
-                                       rprintf(FINFO,"redoing %s(%d)\n",fname,i);
                                SIVAL(buf, 0, i);
                                send_msg(MSG_REDO, buf, 4);
                        }
@@ -546,8 +581,7 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
        }
        make_backups = save_make_backups;
 
-       if (delete_after && recurse && delete_mode && !local_name
-           && flist->count > 0)
+       if (delete_after && recurse && !local_name && flist->count > 0)
                delete_files(flist);
 
        if (verbose > 2)