Check the return value of flush_write_file() and report an error
[rsync/rsync.git] / receiver.c
index 1118beb..70978fd 100644 (file)
@@ -22,7 +22,6 @@
 
 extern int verbose;
 extern int recurse;
-extern int delete_mode;
 extern int delete_after;
 extern int max_delete;
 extern int csum_length;
@@ -31,6 +30,7 @@ extern int dry_run;
 extern int read_batch;
 extern int batch_gen_fd;
 extern int am_server;
+extern int protocol_version;
 extern int relative_paths;
 extern int keep_dirlinks;
 extern int preserve_hard_links;
@@ -39,7 +39,7 @@ extern int cvs_exclude;
 extern int io_error;
 extern char *tmpdir;
 extern char *partial_dir;
-extern char *compare_dest;
+extern char *basis_dir[];
 extern int make_backups;
 extern int do_progress;
 extern char *backup_dir;
@@ -66,10 +66,6 @@ static void delete_one(char *fn, int is_dir)
                        rprintf(FINFO, "deleting %s\n", safe_fname(fn));
        } else {
                if (do_rmdir(fn) != 0) {
-                       if (errno == ENOTDIR && keep_dirlinks) {
-                               delete_one(fn, 0);
-                               return;
-                       }
                        if (errno != ENOTEMPTY && errno != EEXIST) {
                                rsyserr(FERROR, errno,
                                        "delete_one: rmdir %s failed",
@@ -121,22 +117,22 @@ void delete_files(struct file_list *flist)
                        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)
+                       if (max_delete && deletion_count >= max_delete)
                                break;
                        if (!local_file_list->files[i]->basename)
                                continue;
                        if (flist_find(flist,local_file_list->files[i]) < 0) {
                                char *f = f_name(local_file_list->files[i]);
-                               if (make_backups && (backup_dir || !is_backup_file(f))) {
+                               int mode = local_file_list->files[i]->mode;
+                               if (make_backups && (backup_dir || !is_backup_file(f))
+                                 && !S_ISDIR(mode)) {
                                        make_backup(f);
                                        if (verbose) {
                                                rprintf(FINFO, "deleting %s\n",
                                                        safe_fname(f));
                                        }
-                               } else {
-                                       int mode = local_file_list->files[i]->mode;
+                               } else
                                        delete_one(f, S_ISDIR(mode) != 0);
-                               }
                                deletion_count++;
                        }
                }
@@ -223,7 +219,8 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
        read_sum_head(f_in, &sum);
 
        if (fd_r >= 0 && size_r > 0) {
-               mapbuf = map_file(fd_r, size_r, sum.blength);
+               OFF_T map_size = MAX(sum.blength * 2, 16*1024);
+               mapbuf = map_file(fd_r, size_r, map_size, sum.blength);
                if (verbose > 2) {
                        rprintf(FINFO, "recv mapped %s of size %.0f\n",
                                safe_fname(fname_r), (double)size_r);
@@ -292,7 +289,8 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
                offset += len;
        }
 
-       flush_write_file(fd);
+       if (flush_write_file(fd) < 0)
+               goto report_write_error;
 
 #ifdef HAVE_FTRUNCATE
        if (inplace && fd != -1)
@@ -333,7 +331,8 @@ static void discard_receive_data(int f_in, OFF_T length)
  * main routine for receiver process.
  *
  * 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 recv_files(int f_in, struct file_list *flist, char *local_name,
+              int f_in_name)
 {
        int next_gen_i = -1;
        int fd1,fd2;
@@ -362,8 +361,13 @@ 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) {}
+                               if (next_gen_i != flist->count) {
+                                       do {
+                                               if (f_in_name >= 0
+                                                   && next_gen_i >= 0)
+                                                       read_byte(f_in_name);
+                                       } while (read_int(batch_gen_fd) != -1);
+                               }
                                next_gen_i = -1;
                        }
 
@@ -411,6 +415,8 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
 
                if (read_batch) {
                        while (i > next_gen_i) {
+                               if (f_in_name >= 0 && next_gen_i >= 0)
+                                       read_byte(f_in_name);
                                next_gen_i = read_int(batch_gen_fd);
                                if (next_gen_i == -1)
                                        next_gen_i = flist->count;
@@ -421,44 +427,43 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
                                discard_receive_data(f_in, file->length);
                                continue;
                        }
+                       next_gen_i = -1;
                }
 
                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",
-                                       safe_fname(fname));
-                       }
-                       discard_receive_data(f_in, file->length);
-                       continue;
+                       rprintf(FERROR, "attempt to hack rsync failed.\n");
+                       exit_cleanup(RERR_PROTOCOL);
                }
 
-               if (partial_dir) {
-                       if ((partialptr = partial_dir_fname(fname)) != NULL)
-                               fnamecmp = partialptr;
-                       else
+               partialptr = partial_dir ? partial_dir_fname(fname) : fname;
+
+               if (f_in_name >= 0) {
+                       uchar j;
+                       switch (j = read_byte(f_in_name)) {
+                       case FNAMECMP_FNAME:
                                fnamecmp = fname;
+                               break;
+                       case FNAMECMP_PARTIAL_DIR:
+                               fnamecmp = partialptr ? partialptr : fname;
+                               break;
+                       case FNAMECMP_BACKUP:
+                               fnamecmp = get_backup_name(fname);
+                               break;
+                       case FNAMECMP_BASIS_DIR:
+                       default:
+                               pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
+                                        basis_dir[j], fname);
+                               fnamecmp = fnamecmpbuf;
+                               break;
+                       }
                } else
-                       fnamecmp = partialptr = fname;
+                       fnamecmp = fname;
 
                /* open the file */
                fd1 = do_open(fnamecmp, O_RDONLY, 0);
 
-               if (fd1 == -1 && fnamecmp != fname) {
-                       fnamecmp = fname;
-                       fd1 = do_open(fnamecmp, O_RDONLY, 0);
-               }
-
-               if (fd1 == -1 && compare_dest != NULL) {
-                       /* try the file at compare_dest instead */
-                       pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
-                                compare_dest, fname);
-                       fnamecmp = fnamecmpbuf;
-                       fd1 = do_open(fnamecmp, O_RDONLY, 0);
-               }
-
                if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
                        rsyserr(FERROR, errno, "fstat %s failed",
                                full_fname(fnamecmp));
@@ -494,10 +499,10 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
 
                /* We now check to see if we are writing file "inplace" */
                if (inplace)  {
-                       fd2 = do_open(fnamecmp, O_WRONLY|O_CREAT, 0);
+                       fd2 = do_open(fname, O_WRONLY|O_CREAT, 0);
                        if (fd2 == -1) {
                                rsyserr(FERROR, errno, "open %s failed",
-                                       full_fname(fnamecmp));
+                                       full_fname(fname));
                                discard_receive_data(f_in, file->length);
                                if (fd1 != -1)
                                        close(fd1);