If there is no lchown(), don't try to set the user & group of a symlink.
[rsync/rsync.git] / receiver.c
index 124a280..f10f25d 100644 (file)
@@ -30,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;
@@ -38,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;
@@ -122,16 +123,16 @@ void delete_files(struct file_list *flist)
                                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++;
                        }
                }
@@ -208,17 +209,17 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
        static char file_sum2[MD4_SUM_LENGTH];
        struct map_struct *mapbuf;
        struct sum_struct sum;
-       unsigned int len;
+       int32 len;
        OFF_T offset = 0;
        OFF_T offset2;
        char *data;
-       int i;
+       int32 i;
        char *map = NULL;
 
        read_sum_head(f_in, &sum);
 
        if (fd_r >= 0 && size_r > 0) {
-               OFF_T map_size = MAX(sum.blength * 2, 16*1024);
+               OFF_T map_size = MAX((OFF_T)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",
@@ -242,7 +243,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
                        stats.literal_data += i;
                        cleanup_got_literal = 1;
 
-                       sum_update(data,i);
+                       sum_update(data, i);
 
                        if (fd != -1 && write_file(fd,data,i) != i)
                                goto report_write_error;
@@ -251,22 +252,24 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
                }
 
                i = -(i+1);
-               offset2 = i*(OFF_T)sum.blength;
+               offset2 = i * (OFF_T)sum.blength;
                len = sum.blength;
                if (i == (int)sum.count-1 && sum.remainder != 0)
                        len = sum.remainder;
 
                stats.matched_data += len;
 
-               if (verbose > 3)
-                       rprintf(FINFO,"chunk[%d] of size %d at %.0f offset=%.0f\n",
-                               i,len,(double)offset2,(double)offset);
+               if (verbose > 3) {
+                       rprintf(FINFO,
+                               "chunk[%d] of size %ld at %.0f offset=%.0f\n",
+                               i, (long)len, (double)offset2, (double)offset);
+               }
 
                if (mapbuf) {
                        map = map_ptr(mapbuf,offset2,len);
 
                        see_token(map, len);
-                       sum_update(map,len);
+                       sum_update(map, len);
                }
 
                if (inplace) {
@@ -288,7 +291,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)
@@ -329,7 +333,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;
@@ -358,8 +363,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;
                        }
 
@@ -407,6 +417,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;
@@ -417,6 +429,7 @@ 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
@@ -426,35 +439,33 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
                        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;
-
-               if (inplace && make_backups) {
-                       if (!(fnamecmp = get_backup_name(fname)))
-                               fnamecmp = partialptr;
-               }
+                       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));