Make sure that the generator sent us a valid index into basis_dir[].
[rsync/rsync.git] / receiver.c
index f10f25d..3e72768 100644 (file)
@@ -40,6 +40,7 @@ extern int io_error;
 extern char *tmpdir;
 extern char *partial_dir;
 extern char *basis_dir[];
+extern int basis_dir_cnt;
 extern int make_backups;
 extern int do_progress;
 extern char *backup_dir;
@@ -381,7 +382,7 @@ int recv_files(int f_in, struct file_list *flist, char *local_name,
                        if (verbose > 2)
                                rprintf(FINFO, "recv_files phase=%d\n", phase);
                        send_msg(MSG_DONE, "", 0);
-                       if (keep_partial)
+                       if (keep_partial && !partial_dir)
                                make_backups = 0; /* prevents double backup */
                        continue;
                }
@@ -453,8 +454,13 @@ int recv_files(int f_in, struct file_list *flist, char *local_name,
                        case FNAMECMP_BACKUP:
                                fnamecmp = get_backup_name(fname);
                                break;
-                       case FNAMECMP_BASIS_DIR:
                        default:
+                               if (j >= basis_dir_cnt) {
+                                       rprintf(FERROR,
+                                               "invalid basis_dir index: %d.\n",
+                                               j);
+                                       exit_cleanup(RERR_PROTOCOL);
+                               }
                                pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
                                         basis_dir[j], fname);
                                fnamecmp = fnamecmpbuf;
@@ -566,21 +572,21 @@ int recv_files(int f_in, struct file_list *flist, char *local_name,
                        exit_cleanup(RERR_FILEIO);
                }
 
-               if (recv_ok || inplace)
-                       finish_transfer(fname, fnametmp, file, recv_ok);
-               else if (keep_partial && partialptr
-                   && handle_partial_dir(partialptr, PDIR_CREATE))
-                       finish_transfer(partialptr, fnametmp, file, 0);
-               else {
+               if (recv_ok || inplace) {
+                       finish_transfer(fname, fnametmp, file, recv_ok, 1);
+                       if (partialptr != fname && fnamecmp == partialptr) {
+                               do_unlink(partialptr);
+                               handle_partial_dir(partialptr, PDIR_DELETE);
+                       }
+               } else if (keep_partial && partialptr
+                   && handle_partial_dir(partialptr, PDIR_CREATE)) {
+                       finish_transfer(partialptr, fnametmp, file, recv_ok,
+                                       !partial_dir);
+               } else {
                        partialptr = NULL;
                        do_unlink(fnametmp);
                }
 
-               if (partialptr != fname && fnamecmp == partialptr && recv_ok) {
-                       do_unlink(partialptr);
-                       handle_partial_dir(partialptr, PDIR_DELETE);
-               }
-
                cleanup_disable();
 
                if (!recv_ok) {