- We now accept an itemized-changes flag byte over the socket if we're
[rsync/rsync.git] / sender.c
index c5dffc1..5524b6f 100644 (file)
--- a/sender.c
+++ b/sender.c
@@ -20,6 +20,8 @@
 #include "rsync.h"
 
 extern int verbose;
+extern int itemize_changes;
+extern int log_before_transfer;
 extern int csum_length;
 extern struct stats stats;
 extern int io_error;
@@ -27,6 +29,11 @@ extern int dry_run;
 extern int am_server;
 extern int am_daemon;
 extern int protocol_version;
+extern int updating_basis_file;
+extern int make_backups;
+extern int do_progress;
+extern int inplace;
+extern char *log_format;
 extern struct stats stats;
 
 
@@ -37,22 +44,6 @@ extern struct stats stats;
  * and transmits them to the receiver.  The sender process runs on the
  * machine holding the source files.
  **/
-void read_sum_head(int f, struct sum_struct *sum)
-{
-       sum->count = read_int(f);
-       sum->blength = read_int(f);
-       if (protocol_version < 27) {
-               sum->s2length = csum_length;
-       } else {
-               sum->s2length = read_int(f);
-               if (sum->s2length > MD4_SUM_LENGTH) {
-                       rprintf(FERROR, "Invalid checksum length %ld\n",
-                           (long)sum->s2length);
-                       exit_cleanup(RERR_PROTOCOL);
-               }
-       }
-       sum->remainder = read_int(f);
-}
 
 /**
  * Receive the checksums for a buffer
@@ -60,7 +51,7 @@ void read_sum_head(int f, struct sum_struct *sum)
 static struct sum_struct *receive_sums(int f)
 {
        struct sum_struct *s;
-       int i;
+       int32 i;
        OFF_T offset = 0;
 
        if (!(s = new(struct sum_struct)))
@@ -71,8 +62,8 @@ static struct sum_struct *receive_sums(int f)
        s->sums = NULL;
 
        if (verbose > 3) {
-               rprintf(FINFO, "count=%ld n=%u rem=%u\n",
-                       (long)s->count, s->blength, s->remainder);
+               rprintf(FINFO, "count=%.0f n=%ld rem=%ld\n",
+                       (double)s->count, (long)s->blength, (long)s->remainder);
        }
 
        if (s->count == 0)
@@ -81,14 +72,14 @@ static struct sum_struct *receive_sums(int f)
        if (!(s->sums = new_array(struct sum_buf, s->count)))
                out_of_memory("receive_sums");
 
-       for (i = 0; i < (int)s->count; i++) {
+       for (i = 0; i < s->count; i++) {
                s->sums[i].sum1 = read_int(f);
                read_buf(f, s->sums[i].sum2, s->s2length);
 
                s->sums[i].offset = offset;
                s->sums[i].flags = 0;
 
-               if (i == (int)s->count-1 && s->remainder != 0)
+               if (i == s->count-1 && s->remainder != 0)
                        s->sums[i].len = s->remainder;
                else
                        s->sums[i].len = s->blength;
@@ -116,11 +107,12 @@ void send_files(struct file_list *flist, int f_out, int f_in)
        struct map_struct *mbuf = NULL;
        STRUCT_STAT st;
        char *fname2, fname[MAXPATHLEN];
-       int i;
+       int iflags;
        struct file_struct *file;
        int phase = 0;
        struct stats initial_stats;
-       int j;
+       int save_make_backups = make_backups;
+       int i, j;
 
        if (verbose > 2)
                rprintf(FINFO, "send_files starting\n");
@@ -136,6 +128,9 @@ void send_files(struct file_list *flist, int f_out, int f_in)
                                write_int(f_out, -1);
                                if (verbose > 2)
                                        rprintf(FINFO, "send_files phase=%d\n", phase);
+                               /* For inplace: redo phase turns off the backup
+                                * flag so that we do a regular inplace send. */
+                               make_backups = 0;
                                continue;
                        }
                        break;
@@ -149,13 +144,38 @@ void send_files(struct file_list *flist, int f_out, int f_in)
 
                file = flist->files[i];
 
+               if (itemize_changes) {
+                       iflags = read_byte(f_in);
+                       if (!(iflags & ITEM_UPDATING) || !S_ISREG(file->mode)) {
+                               if (am_server) {
+                                       write_int(f_out, i);
+                                       write_byte(f_out, iflags);
+                               } else
+                                       log_send(file, &stats, iflags);
+                               continue;
+                       }
+               } else
+                       iflags = ITEM_UPDATING | ITEM_MISSING_DATA;
+
+               if (inplace && protocol_version >= 29) {
+                       uchar fnamecmp_type = read_byte(f_in);
+                       updating_basis_file = fnamecmp_type == FNAMECMP_FNAME;
+               } else
+                       updating_basis_file = inplace && !make_backups;
+
+               if (!S_ISREG(file->mode)) {
+                       rprintf(FERROR, "[%s] got index of non-regular file: %d\n",
+                               who_am_i(), i);
+                       exit_cleanup(RERR_PROTOCOL);
+               }
+
                stats.current_file_index = i;
                stats.num_transferred_files++;
                stats.total_transferred_size += file->length;
 
-               if (file->basedir) {
+               if (file->dir.root) {
                        /* N.B. We're sure that this fits, so offset is OK. */
-                       offset = strlcpy(fname, file->basedir, sizeof fname);
+                       offset = strlcpy(fname, file->dir.root, sizeof fname);
                        if (!offset || fname[offset-1] != '/')
                                fname[offset++] = '/';
                } else
@@ -165,10 +185,14 @@ void send_files(struct file_list *flist, int f_out, int f_in)
                if (verbose > 2)
                        rprintf(FINFO, "send_files(%d, %s)\n", i, fname);
 
-               if (dry_run) {
-                       if (!am_server && verbose) /* log the transfer */
+               if (dry_run) { /* log the transfer */
+                       if (!am_server && verbose && !log_format)
                                rprintf(FINFO, "%s\n", safe_fname(fname2));
+                       else if (!am_server)
+                               log_send(file, &stats, iflags);
                        write_int(f_out, i);
+                       if (itemize_changes)
+                               write_byte(f_out, iflags);
                        continue;
                }
 
@@ -208,7 +232,11 @@ void send_files(struct file_list *flist, int f_out, int f_in)
                        return;
                }
 
-               mbuf = st.st_size ? map_file(fd, st.st_size, s->blength) : NULL;
+               if (st.st_size) {
+                       int32 read_size = MAX(s->blength * 3, MAX_MAP_SIZE);
+                       mbuf = map_file(fd, st.st_size, read_size, s->blength);
+               } else
+                       mbuf = NULL;
 
                if (verbose > 2) {
                        rprintf(FINFO, "send_files mapped %s of size %.0f\n",
@@ -216,6 +244,8 @@ void send_files(struct file_list *flist, int f_out, int f_in)
                }
 
                write_int(f_out, i);
+               if (itemize_changes)
+                       write_byte(f_out, iflags);
                write_sum_head(f_out, s);
 
                if (verbose > 2) {
@@ -223,13 +253,16 @@ void send_files(struct file_list *flist, int f_out, int f_in)
                                safe_fname(fname));
                }
 
-               if (!am_server && verbose) /* log the transfer */
+               if (log_before_transfer)
+                       log_send(file, &initial_stats, iflags);
+               else if (!am_server && verbose && (!log_format || do_progress))
                        rprintf(FINFO, "%s\n", safe_fname(fname2));
 
                set_compression(fname);
 
                match_sums(f_out, s, mbuf, st.st_size);
-               log_send(file, &initial_stats);
+               if (!log_before_transfer)
+                       log_send(file, &initial_stats, iflags);
 
                if (mbuf) {
                        j = unmap_file(mbuf);
@@ -249,6 +282,7 @@ void send_files(struct file_list *flist, int f_out, int f_in)
                                safe_fname(fname));
                }
        }
+       make_backups = save_make_backups;
 
        if (verbose > 2)
                rprintf(FINFO, "send files finished\n");