Make batch mode actually work and add man page documentation. From Jos Backus.
authorDavid Dykstra <dwd@samba.org>
Wed, 6 Feb 2002 21:20:48 +0000 (21:20 +0000)
committerDavid Dykstra <dwd@samba.org>
Wed, 6 Feb 2002 21:20:48 +0000 (21:20 +0000)
NEWS
batch.c
errcode.h
log.c
main.c
options.c
rsync.yo

diff --git a/NEWS b/NEWS
index 620db73..8c54134 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -7,5 +7,7 @@ rsync 2.5.3 (not released yet)
       what was historically used so as not to break scripts that try
       to parse the output.
 
       what was historically used so as not to break scripts that try
       to parse the output.
 
-    * Added --no-whole-file and --no-blocking-io options
+    * Added --no-whole-file and --no-blocking-io options (Dave Dykstra)
 
 
+    * Made the --write-batch and --read-batch options actually work
+       and added documentation in the man page (Jos Backus)
diff --git a/batch.c b/batch.c
index a470710..237d57b 100644 (file)
--- a/batch.c
+++ b/batch.c
@@ -8,55 +8,38 @@
 #include "rsync.h"
 #include <time.h>
 
 #include "rsync.h"
 #include <time.h>
 
-char rsync_flist_file[27] = "rsync_flist.";
-char rsync_csums_file[27] = "rsync_csums.";
-char rsync_delta_file[27] = "rsync_delta.";
-char rsync_argvs_file[27] = "rsync_argvs.";
-
-char batch_file_ext[15];
-
-int fdb;
-int fdb_delta;
-int fdb_open;
-int fdb_close;
+extern char *batch_prefix;
 
 struct file_list *batch_flist;
 
 
 struct file_list *batch_flist;
 
-void create_batch_file_ext()
-{
-       struct tm *timeptr;
-       time_t elapsed_seconds;
-
-       /* Save run date and time to use for batch file extensions */
-       time(&elapsed_seconds);
-       timeptr = localtime(&elapsed_seconds);
-
-       sprintf(batch_file_ext, "%4d%02d%02d%02d%02d%02d",
-               timeptr->tm_year + 1900, timeptr->tm_mon + 1,
-               timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min,
-               timeptr->tm_sec);
-       rprintf(FINFO,"batch file extension: %s\n", batch_file_ext);
-}
+static char rsync_flist_file[] = ".rsync_flist";
+static char rsync_csums_file[] = ".rsync_csums";
+static char rsync_delta_file[] = ".rsync_delta";
+static char rsync_argvs_file[] = ".rsync_argvs";
 
 
-void set_batch_file_ext(char *ext)
-{
-       strcpy(batch_file_ext, ext);
-}
+static int fdb;
+static int fdb_delta;
+static int fdb_open;
+static int fdb_close;
 
 void write_batch_flist_file(char *buff, int bytes_to_write)
 {
 
 void write_batch_flist_file(char *buff, int bytes_to_write)
 {
+       char filename[MAXPATHLEN];
 
        if (fdb_open) {
                /* Set up file extension */
 
        if (fdb_open) {
                /* Set up file extension */
-               strcat(rsync_flist_file, batch_file_ext);
+               strlcpy(filename, batch_prefix, sizeof(filename));
+               strlcat(filename, rsync_flist_file, sizeof(filename));
 
 
-               /* Open batch flist file for writing; create it if it doesn't exist */
-               fdb =
-                   do_open(rsync_flist_file, O_WRONLY | O_CREAT | O_TRUNC,
+               /*
+                * Open batch flist file for writing;
+                * create it if it doesn't exist
+                */
+               fdb = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
                            S_IREAD | S_IWRITE);
                if (fdb == -1) {
                        rprintf(FERROR, "Batch file %s open error: %s\n",
                            S_IREAD | S_IWRITE);
                if (fdb == -1) {
                        rprintf(FERROR, "Batch file %s open error: %s\n",
-                               rsync_flist_file, strerror(errno));
+                               filename, strerror(errno));
                        close(fdb);
                        exit_cleanup(1);
                }
                        close(fdb);
                        exit_cleanup(1);
                }
@@ -67,12 +50,11 @@ void write_batch_flist_file(char *buff, int bytes_to_write)
 
        if (write(fdb, buff, bytes_to_write) == -1) {
                rprintf(FERROR, "Batch file %s write error: %s\n",
 
        if (write(fdb, buff, bytes_to_write) == -1) {
                rprintf(FERROR, "Batch file %s write error: %s\n",
-                       rsync_flist_file, strerror(errno));
+                       filename, strerror(errno));
                close(fdb);
                exit_cleanup(1);
        }
 
                close(fdb);
                exit_cleanup(1);
        }
 
-
        if (fdb_close) {
                close(fdb);
        }
        if (fdb_close) {
                close(fdb);
        }
@@ -110,7 +92,6 @@ void write_batch_flist_info(int flist_count, struct file_struct **fptr)
                }
                write_char_bufs(fptr[i]->sum);
        }
                }
                write_char_bufs(fptr[i]->sum);
        }
-
 }
 
 void write_char_bufs(char *buf)
 }
 
 void write_char_bufs(char *buf)
@@ -118,11 +99,8 @@ void write_char_bufs(char *buf)
        /* Write the size of the string which will follow  */
 
        char b[4];
        /* Write the size of the string which will follow  */
 
        char b[4];
-       if (buf != NULL)
-               SIVAL(b, 0, strlen(buf));
-       else {
-               SIVAL(b, 0, 0);
-       }
+
+       SIVAL(b, 0, buf != NULL ? strlen(buf) : 0);
 
        write_batch_flist_file(b, sizeof(int));
 
 
        write_batch_flist_file(b, sizeof(int));
 
@@ -137,36 +115,52 @@ void write_batch_argvs_file(int argc, char *argv[])
 {
        int fdb;
        int i;
 {
        int fdb;
        int i;
-       char buff[256];
-
-       strcat(rsync_argvs_file, batch_file_ext);
-
-
-       /* Open batch argvs file for writing; create it if it doesn't exist */
-       fdb = do_open(rsync_argvs_file, O_WRONLY | O_CREAT | O_TRUNC,
+       char buff[256]; /* XXX */
+       char buff2[MAXPATHLEN + 6];
+       char filename[MAXPATHLEN];
+
+       /* Set up file extension */
+       strlcpy(filename, batch_prefix, sizeof(filename));
+       strlcat(filename, rsync_argvs_file, sizeof(filename));
+
+       /*
+        * Open batch argvs file for writing;
+        * create it if it doesn't exist
+        */
+       fdb = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
                      S_IREAD | S_IWRITE | S_IEXEC);
        if (fdb == -1) {
                rprintf(FERROR, "Batch file %s open error: %s\n",
                      S_IREAD | S_IWRITE | S_IEXEC);
        if (fdb == -1) {
                rprintf(FERROR, "Batch file %s open error: %s\n",
-                       rsync_argvs_file, strerror(errno));
+                       filename, strerror(errno));
                close(fdb);
                exit_cleanup(1);
        }
        buff[0] = '\0';
                close(fdb);
                exit_cleanup(1);
        }
        buff[0] = '\0';
+
        /* Write argvs info to batch file */
 
        for (i = 0; i < argc; ++i) {
        /* Write argvs info to batch file */
 
        for (i = 0; i < argc; ++i) {
-               if (i == argc - 2)
+               if (i == argc - 2) /* Skip source directory on cmdline */
                    continue;
                /*
                 * FIXME:
                 * I think directly manipulating argv[] is probably bogus
                 */
                    continue;
                /*
                 * FIXME:
                 * I think directly manipulating argv[] is probably bogus
                 */
-               if (!strcmp(argv[i], "--write-batch")) {
+               if (!strncmp(argv[i], "--write-batch",
+                       strlen("--write-batch"))) {
                        /* Safer to change it here than script */
                        /* Safer to change it here than script */
-                       /* Change to --read-batch + ext * to get ready for remote */
-                       strlcat(buff, "--read-batch ", sizeof(buff));
-                       strlcat(buff, batch_file_ext, sizeof(buff));
-               } else {
+                       /*
+                        * Change to --read-batch=prefix
+                        * to get ready for remote
+                        */
+                       strlcat(buff, "--read-batch=", sizeof(buff));
+                       strlcat(buff, batch_prefix, sizeof(buff));
+               } else
+               if (i == argc - 1) {
+                   snprintf(buff2, sizeof(buff2), "${1:-%s}", argv[i]);
+                   strlcat(buff, buff2, sizeof(buff));
+               }
+               else {
                        strlcat(buff, argv[i], sizeof(buff));
                }
 
                        strlcat(buff, argv[i], sizeof(buff));
                }
 
@@ -177,14 +171,14 @@ void write_batch_argvs_file(int argc, char *argv[])
        strlcat(buff, "\n", sizeof(buff));
        if (!write(fdb, buff, strlen(buff))) {
                rprintf(FERROR, "Batch file %s write error: %s\n",
        strlcat(buff, "\n", sizeof(buff));
        if (!write(fdb, buff, strlen(buff))) {
                rprintf(FERROR, "Batch file %s write error: %s\n",
-                       rsync_argvs_file, strerror(errno));
+                       filename, strerror(errno));
                close(fdb);
                exit_cleanup(1);
        }
        close(fdb);
 }
 
                close(fdb);
                exit_cleanup(1);
        }
        close(fdb);
 }
 
-struct file_list *create_flist_from_batch()
+struct file_list *create_flist_from_batch(void)
 {
        unsigned char flags;
 
 {
        unsigned char flags;
 
@@ -201,7 +195,7 @@ struct file_list *create_flist_from_batch()
            (struct file_struct **) malloc(sizeof(batch_flist->files[0]) *
                                           batch_flist->malloced);
        if (!batch_flist->files) {
            (struct file_struct **) malloc(sizeof(batch_flist->files[0]) *
                                           batch_flist->malloced);
        if (!batch_flist->files) {
-               out_of_memory("create_flist_from_batch");       /* dw -- will exit */
+               out_of_memory("create_flist_from_batch");
        }
 
        for (flags = read_batch_flags(); flags; flags = read_batch_flags()) {
        }
 
        for (flags = read_batch_flags(); flags; flags = read_batch_flags()) {
@@ -231,23 +225,23 @@ struct file_list *create_flist_from_batch()
        }
 
        return batch_flist;
        }
 
        return batch_flist;
-
 }
 
 int read_batch_flist_file(char *buff, int len)
 {
        int bytes_read;
 }
 
 int read_batch_flist_file(char *buff, int len)
 {
        int bytes_read;
+       char filename[MAXPATHLEN];
 
        if (fdb_open) {
 
        if (fdb_open) {
-
-               /*  Set up file extension  */
-               strcat(rsync_flist_file, batch_file_ext);
+               /* Set up file extension */
+               strlcpy(filename, batch_prefix, sizeof(filename));
+               strlcat(filename, rsync_flist_file, sizeof(filename));
 
                /* Open batch flist file for reading */
 
                /* Open batch flist file for reading */
-               fdb = do_open(rsync_flist_file, O_RDONLY, 0);
+               fdb = do_open(filename, O_RDONLY, 0);
                if (fdb == -1) {
                        rprintf(FERROR, "Batch file %s open error: %s\n",
                if (fdb == -1) {
                        rprintf(FERROR, "Batch file %s open error: %s\n",
-                               rsync_flist_file, strerror(errno));
+                               filename, strerror(errno));
                        close(fdb);
                        exit_cleanup(1);
                }
                        close(fdb);
                        exit_cleanup(1);
                }
@@ -256,17 +250,17 @@ int read_batch_flist_file(char *buff, int len)
 
        /* Read flist batch file */
 
 
        /* Read flist batch file */
 
-       bytes_read = read(fdb, buff, len);
-
-       if (bytes_read == -1) {
+       switch (bytes_read = read(fdb, buff, len)) {
+           case -1:
                rprintf(FERROR, "Batch file %s read error: %s\n",
                rprintf(FERROR, "Batch file %s read error: %s\n",
-                       rsync_flist_file, strerror(errno));
+                       filename, strerror(errno));
                close(fdb);
                exit_cleanup(1);
                close(fdb);
                exit_cleanup(1);
-       }
-       if (bytes_read == 0) {  /* EOF */
+               break;
+           case 0:     /* EOF */
                close(fdb);
        }
                close(fdb);
        }
+
        return bytes_read;
 }
 
        return bytes_read;
 }
 
@@ -293,8 +287,12 @@ void read_batch_flist_info(struct file_struct **fptr)
                out_of_memory("read_batch_flist_info");
        memset((char *) file, 0, sizeof(*file));
 
                out_of_memory("read_batch_flist_info");
        memset((char *) file, 0, sizeof(*file));
 
-       (*fptr) = file;
+       *fptr = file;
 
 
+       /*
+        * Keep these in sync with bytes_to_write assignment
+        * in write_batch_flist_info()
+        */
        read_batch_flist_file((char *) &file->modtime, sizeof(time_t));
        read_batch_flist_file((char *) &file->length, sizeof(OFF_T));
        read_batch_flist_file((char *) &file->mode, sizeof(mode_t));
        read_batch_flist_file((char *) &file->modtime, sizeof(time_t));
        read_batch_flist_file((char *) &file->length, sizeof(OFF_T));
        read_batch_flist_file((char *) &file->mode, sizeof(mode_t));
@@ -356,20 +354,23 @@ void read_batch_flist_info(struct file_struct **fptr)
 
 void write_batch_csums_file(void *buff, int bytes_to_write)
 {
 
 void write_batch_csums_file(void *buff, int bytes_to_write)
 {
-
        static int fdb_open = 1;
        static int fdb_open = 1;
+       char filename[MAXPATHLEN];
 
        if (fdb_open) {
                /* Set up file extension */
 
        if (fdb_open) {
                /* Set up file extension */
-               strcat(rsync_csums_file, batch_file_ext);
+               strlcpy(filename, batch_prefix, sizeof(filename));
+               strlcat(filename, rsync_csums_file, sizeof(filename));
 
 
-               /* Open batch csums file for writing; create it if it doesn't exist */
-               fdb =
-                   do_open(rsync_csums_file, O_WRONLY | O_CREAT | O_TRUNC,
+               /*
+                * Open batch csums file for writing;
+                * create it if it doesn't exist
+                */
+               fdb = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
                            S_IREAD | S_IWRITE);
                if (fdb == -1) {
                        rprintf(FERROR, "Batch file %s open error: %s\n",
                            S_IREAD | S_IWRITE);
                if (fdb == -1) {
                        rprintf(FERROR, "Batch file %s open error: %s\n",
-                               rsync_csums_file, strerror(errno));
+                               filename, strerror(errno));
                        close(fdb);
                        exit_cleanup(1);
                }
                        close(fdb);
                        exit_cleanup(1);
                }
@@ -380,16 +381,15 @@ void write_batch_csums_file(void *buff, int bytes_to_write)
 
        if (write(fdb, buff, bytes_to_write) == -1) {
                rprintf(FERROR, "Batch file %s write error: %s\n",
 
        if (write(fdb, buff, bytes_to_write) == -1) {
                rprintf(FERROR, "Batch file %s write error: %s\n",
-                       rsync_csums_file, strerror(errno));
+                       filename, strerror(errno));
                close(fdb);
                exit_cleanup(1);
        }
 }
 
                close(fdb);
                exit_cleanup(1);
        }
 }
 
-void close_batch_csums_file()
+void close_batch_csums_file(void)
 {
        close(fdb);
 {
        close(fdb);
-
 }
 
 void write_batch_csum_info(int *flist_entry, int flist_count,
 }
 
 void write_batch_csum_info(int *flist_entry, int flist_count,
@@ -405,10 +405,7 @@ void write_batch_csum_info(int *flist_entry, int flist_count,
 
        /* FIXME: This will break if s->count is ever not exactly an int. */
        write_batch_csums_file(flist_entry, sizeof(int));
 
        /* FIXME: This will break if s->count is ever not exactly an int. */
        write_batch_csums_file(flist_entry, sizeof(int));
-       if (s)
-               write_batch_csums_file(&s->count, sizeof(int));
-       else
-               write_batch_csums_file(&int_zero, sizeof (int));
+       write_batch_csums_file(s ? &s->count : &int_zero, sizeof(int));
        
        if (s) {
                for (i = 0; i < s->count; i++) {
        
        if (s) {
                for (i = 0; i < s->count; i++) {
@@ -417,8 +414,7 @@ void write_batch_csum_info(int *flist_entry, int flist_count,
                            && (i == s->count - 1)) {
                                fdb_close = 1;
                        }
                            && (i == s->count - 1)) {
                                fdb_close = 1;
                        }
-                       write_batch_csums_file(s->sums[i].sum2,
-                                              csum_length);
+                       write_batch_csums_file(s->sums[i].sum2, csum_length);
                }
        }
 }
                }
        }
 }
@@ -427,17 +423,18 @@ int read_batch_csums_file(char *buff, int len)
 {
        static int fdb_open = 1;
        int bytes_read;
 {
        static int fdb_open = 1;
        int bytes_read;
+       char filename[MAXPATHLEN];
 
        if (fdb_open) {
 
        if (fdb_open) {
-
-               /*  Set up file extension  */
-               strcat(rsync_csums_file, batch_file_ext);
+               /* Set up file extension */
+               strlcpy(filename, batch_prefix, sizeof(filename));
+               strlcat(filename, rsync_csums_file, sizeof(filename));
 
                /* Open batch flist file for reading */
 
                /* Open batch flist file for reading */
-               fdb = do_open(rsync_csums_file, O_RDONLY, 0);
+               fdb = do_open(filename, O_RDONLY, 0);
                if (fdb == -1) {
                        rprintf(FERROR, "Batch file %s open error: %s\n",
                if (fdb == -1) {
                        rprintf(FERROR, "Batch file %s open error: %s\n",
-                               rsync_csums_file, strerror(errno));
+                               filename, strerror(errno));
                        close(fdb);
                        exit_cleanup(1);
                }
                        close(fdb);
                        exit_cleanup(1);
                }
@@ -450,14 +447,14 @@ int read_batch_csums_file(char *buff, int len)
 
        if (bytes_read == -1) {
                rprintf(FERROR, "Batch file %s read error: %s\n",
 
        if (bytes_read == -1) {
                rprintf(FERROR, "Batch file %s read error: %s\n",
-                       rsync_csums_file, strerror(errno));
+                       filename, strerror(errno));
                close(fdb);
                exit_cleanup(1);
        }
                close(fdb);
                exit_cleanup(1);
        }
+
        return bytes_read;
 }
 
        return bytes_read;
 }
 
-
 void read_batch_csum_info(int flist_entry, struct sum_struct *s,
                          int *checksums_match)
 {
 void read_batch_csum_info(int flist_entry, struct sum_struct *s,
                          int *checksums_match)
 {
@@ -468,11 +465,9 @@ void read_batch_csum_info(int flist_entry, struct sum_struct *s,
        char file_sum2[SUM_LENGTH];
        extern int csum_length;
 
        char file_sum2[SUM_LENGTH];
        extern int csum_length;
 
-
        read_batch_csums_file((char *) &file_flist_entry, sizeof(int));
        if (file_flist_entry != flist_entry) {
        read_batch_csums_file((char *) &file_flist_entry, sizeof(int));
        if (file_flist_entry != flist_entry) {
-               rprintf(FINFO, "file_list_entry NE flist_entry\n");
-               rprintf(FINFO, "file_flist_entry = %d  flist_entry = %d\n",
+               rprintf(FINFO, "file_flist_entry (%d) != flist_entry (%d)\n",
                        file_flist_entry, flist_entry);
                close(fdb);
                exit_cleanup(1);
                        file_flist_entry, flist_entry);
                close(fdb);
                exit_cleanup(1);
@@ -488,31 +483,33 @@ void read_batch_csum_info(int flist_entry, struct sum_struct *s,
                        read_batch_csums_file(file_sum2, csum_length);
 
                        if ((s->sums[i].sum1 != file_sum1) ||
                        read_batch_csums_file(file_sum2, csum_length);
 
                        if ((s->sums[i].sum1 != file_sum1) ||
-                           (memcmp
-                            (s->sums[i].sum2, file_sum2,
-                             csum_length) != 0)) {
+                           (memcmp(s->sums[i].sum2, file_sum2, csum_length)
+                               != 0)) {
                                *checksums_match = 0;
                        }
                }               /*  end for  */
        }
                                *checksums_match = 0;
                        }
                }               /*  end for  */
        }
-
 }
 
 void write_batch_delta_file(char *buff, int bytes_to_write)
 {
        static int fdb_delta_open = 1;
 }
 
 void write_batch_delta_file(char *buff, int bytes_to_write)
 {
        static int fdb_delta_open = 1;
+       char filename[MAXPATHLEN];
 
        if (fdb_delta_open) {
                /* Set up file extension */
 
        if (fdb_delta_open) {
                /* Set up file extension */
-               strcat(rsync_delta_file, batch_file_ext);
+               strlcpy(filename, batch_prefix, sizeof(filename));
+               strlcat(filename, rsync_delta_file, sizeof(filename));
 
 
-               /* Open batch delta file for writing; create it if it doesn't exist */
-               fdb_delta =
-                   do_open(rsync_delta_file, O_WRONLY | O_CREAT | O_TRUNC,
+               /*
+                * Open batch delta file for writing;
+                * create it if it doesn't exist
+                */
+               fdb_delta = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
                            S_IREAD | S_IWRITE);
                if (fdb_delta == -1) {
                        rprintf(FERROR, "Batch file %s open error: %s\n",
                            S_IREAD | S_IWRITE);
                if (fdb_delta == -1) {
                        rprintf(FERROR, "Batch file %s open error: %s\n",
-                               rsync_delta_file, strerror(errno));
+                               filename, strerror(errno));
                        close(fdb_delta);
                        exit_cleanup(1);
                }
                        close(fdb_delta);
                        exit_cleanup(1);
                }
@@ -523,32 +520,33 @@ void write_batch_delta_file(char *buff, int bytes_to_write)
 
        if (write(fdb_delta, buff, bytes_to_write) == -1) {
                rprintf(FERROR, "Batch file %s write error: %s\n",
 
        if (write(fdb_delta, buff, bytes_to_write) == -1) {
                rprintf(FERROR, "Batch file %s write error: %s\n",
-                       rsync_delta_file, strerror(errno));
+                       filename, strerror(errno));
                close(fdb_delta);
                exit_cleanup(1);
        }
 }
                close(fdb_delta);
                exit_cleanup(1);
        }
 }
-void close_batch_delta_file()
+
+void close_batch_delta_file(void)
 {
        close(fdb_delta);
 {
        close(fdb_delta);
-
 }
 
 int read_batch_delta_file(char *buff, int len)
 {
        static int fdb_delta_open = 1;
        int bytes_read;
 }
 
 int read_batch_delta_file(char *buff, int len)
 {
        static int fdb_delta_open = 1;
        int bytes_read;
+       char filename[MAXPATHLEN];
 
        if (fdb_delta_open) {
 
        if (fdb_delta_open) {
-
-               /*  Set up file extension  */
-               strcat(rsync_delta_file, batch_file_ext);
+               /* Set up file extension */
+               strlcpy(filename, batch_prefix, sizeof(filename));
+               strlcat(filename, rsync_delta_file, sizeof(filename));
 
                /* Open batch flist file for reading */
 
                /* Open batch flist file for reading */
-               fdb_delta = do_open(rsync_delta_file, O_RDONLY, 0);
+               fdb_delta = do_open(filename, O_RDONLY, 0);
                if (fdb_delta == -1) {
                        rprintf(FERROR, "Batch file %s open error: %s\n",
                if (fdb_delta == -1) {
                        rprintf(FERROR, "Batch file %s open error: %s\n",
-                               rsync_delta_file, strerror(errno));
+                               filename, strerror(errno));
                        close(fdb_delta);
                        exit_cleanup(1);
                }
                        close(fdb_delta);
                        exit_cleanup(1);
                }
@@ -561,14 +559,14 @@ int read_batch_delta_file(char *buff, int len)
 
        if (bytes_read == -1) {
                rprintf(FERROR, "Batch file %s read error: %s\n",
 
        if (bytes_read == -1) {
                rprintf(FERROR, "Batch file %s read error: %s\n",
-                       rsync_delta_file, strerror(errno));
+                       filename, strerror(errno));
                close(fdb_delta);
                exit_cleanup(1);
        }
                close(fdb_delta);
                exit_cleanup(1);
        }
+
        return bytes_read;
 }
 
        return bytes_read;
 }
 
-
 void show_flist(int index, struct file_struct **fptr)
 {
        /*  for debugging    show_flist(flist->count, flist->files * */
 void show_flist(int index, struct file_struct **fptr)
 {
        /*  for debugging    show_flist(flist->count, flist->files * */
index fc1eca7..18d0414 100644 (file)
--- a/errcode.h
+++ b/errcode.h
@@ -26,6 +26,7 @@
 #define RERR_PROTOCOL   2       /* protocol incompatibility */
 #define RERR_FILESELECT 3       /* errors selecting input/output files, dirs */
 #define RERR_UNSUPPORTED 4       /* requested action not supported */
 #define RERR_PROTOCOL   2       /* protocol incompatibility */
 #define RERR_FILESELECT 3       /* errors selecting input/output files, dirs */
 #define RERR_UNSUPPORTED 4       /* requested action not supported */
+#define RERR_STARTCLIENT 5      /* error starting client-server protocol */
 
 #define RERR_SOCKETIO   10      /* error in socket IO */
 #define RERR_FILEIO     11      /* error in file IO */
 
 #define RERR_SOCKETIO   10      /* error in socket IO */
 #define RERR_FILEIO     11      /* error in file IO */
diff --git a/log.c b/log.c
index 045f031..f07b64b 100644 (file)
--- a/log.c
+++ b/log.c
@@ -41,6 +41,7 @@ struct {
        { RERR_PROTOCOL   , "protocol incompatibility" }, 
        { RERR_FILESELECT , "errors selecting input/output files, dirs" }, 
        { RERR_UNSUPPORTED, "requested action not supported" }, 
        { RERR_PROTOCOL   , "protocol incompatibility" }, 
        { RERR_FILESELECT , "errors selecting input/output files, dirs" }, 
        { RERR_UNSUPPORTED, "requested action not supported" }, 
+       { RERR_STARTCLIENT, "error starting client-server protocol" }, 
        { RERR_SOCKETIO   , "error in socket IO" }, 
        { RERR_FILEIO     , "error in file IO" }, 
        { RERR_STREAMIO   , "error in rsync protocol data stream" }, 
        { RERR_SOCKETIO   , "error in socket IO" }, 
        { RERR_FILEIO     , "error in file IO" }, 
        { RERR_STREAMIO   , "error in rsync protocol data stream" }, 
@@ -559,20 +560,16 @@ void log_exit(int code, const char *file, int line)
        }
 }
 
        }
 }
 
-
-
-
-/* log the incoming transfer of a file for interactive use, this
-   will be called at the end where the client was run 
-   
-   it i called when a file starts to be transferred
-*/
+/*
+ * Log the incoming transfer of a file for interactive use,
+ * this will be called at the end where the client was run.
+ * Called when a file starts to be transferred.
+ */
 void log_transfer(struct file_struct *file, const char *fname)
 {
        extern int verbose;
 
        if (!verbose) return;
 
 void log_transfer(struct file_struct *file, const char *fname)
 {
        extern int verbose;
 
        if (!verbose) return;
 
-       rprintf(FINFO,"%s\n", fname);
+       rprintf(FINFO, "%s\n", fname);
 }
 }
-
diff --git a/main.c b/main.c
index fa5ecc0..0ed7df3 100644 (file)
--- a/main.c
+++ b/main.c
@@ -177,7 +177,7 @@ static pid_t do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int
        extern int blocking_io;
        extern int read_batch;
 
        extern int blocking_io;
        extern int read_batch;
 
-       if (!read_batch && !local_server) { /* dw -- added read_batch */
+       if (!read_batch && !local_server) {
                if (!cmd)
                        cmd = getenv(RSYNC_RSH_ENV);
                if (!cmd)
                if (!cmd)
                        cmd = getenv(RSYNC_RSH_ENV);
                if (!cmd)
@@ -230,7 +230,7 @@ static pid_t do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int
 
        if (local_server) {
                if (read_batch)
 
        if (local_server) {
                if (read_batch)
-                   create_flist_from_batch();
+                   create_flist_from_batch(); /* sets batch_flist */
                ret = local_child(argc, args, f_in, f_out);
        } else {
                ret = piped_child(args,f_in,f_out);
                ret = local_child(argc, args, f_in, f_out);
        } else {
                ret = piped_child(args,f_in,f_out);
@@ -443,8 +443,8 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
        extern int am_daemon;
        extern int module_id;
        extern int am_sender;
        extern int am_daemon;
        extern int module_id;
        extern int am_sender;
-       extern int read_batch;   /* dw */
-       extern struct file_list *batch_flist;  /* dw */
+       extern int read_batch;
+       extern struct file_list *batch_flist;
 
        if (verbose > 2)
                rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
 
        if (verbose > 2)
                rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
@@ -470,7 +470,7 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
        if (delete_mode && !delete_excluded)
                recv_exclude_list(f_in);
 
        if (delete_mode && !delete_excluded)
                recv_exclude_list(f_in);
 
-       if (read_batch) /*  dw  */
+       if (read_batch)
            flist = batch_flist;
        else
            flist = recv_file_list(f_in);
            flist = batch_flist;
        else
            flist = recv_file_list(f_in);
@@ -497,7 +497,7 @@ void start_server(int f_in, int f_out, int argc, char *argv[])
        extern int cvs_exclude;
        extern int am_sender;
        extern int remote_version;
        extern int cvs_exclude;
        extern int am_sender;
        extern int remote_version;
-       extern int read_batch; /* dw */
+       extern int read_batch;
 
        setup_protocol(f_out, f_in);
 
 
        setup_protocol(f_out, f_in);
 
@@ -508,7 +508,7 @@ void start_server(int f_in, int f_out, int argc, char *argv[])
                io_start_multiplex_out(f_out);
 
        if (am_sender) {
                io_start_multiplex_out(f_out);
 
        if (am_sender) {
-               if (!read_batch) { /* dw */
+               if (!read_batch) {
                    recv_exclude_list(f_in);
                    if (cvs_exclude)
                        add_cvs_excludes();
                    recv_exclude_list(f_in);
                    if (cvs_exclude)
                        add_cvs_excludes();
@@ -527,19 +527,19 @@ void start_server(int f_in, int f_out, int argc, char *argv[])
  */
 int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
 {
  */
 int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
 {
-       struct file_list *flist;
+       struct file_list *flist = NULL;
        int status = 0, status2 = 0;
        char *local_name = NULL;
        extern int am_sender;
        extern int remote_version;
        extern pid_t cleanup_child_pid;
        int status = 0, status2 = 0;
        char *local_name = NULL;
        extern int am_sender;
        extern int remote_version;
        extern pid_t cleanup_child_pid;
-       extern int write_batch; /* dw */
-       extern int read_batch; /* dw */
-       extern struct file_list *batch_flist; /*  dw */
+       extern int write_batch;
+       extern int read_batch;
+       extern struct file_list *batch_flist;
 
        cleanup_child_pid = pid;
        if (read_batch)
 
        cleanup_child_pid = pid;
        if (read_batch)
-           flist = batch_flist;  /* dw */
+           flist = batch_flist;
 
        set_nonblocking(f_in);
        set_nonblocking(f_out);
 
        set_nonblocking(f_in);
        set_nonblocking(f_out);
@@ -582,7 +582,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
                list_only = 1;
        }
        
                list_only = 1;
        }
        
-       if (!write_batch) /* dw */
+       if (!write_batch)
            send_exclude_list(f_out);
        
        flist = recv_file_list(f_in);
            send_exclude_list(f_out);
        
        flist = recv_file_list(f_in);
@@ -658,6 +658,7 @@ static int start_client(int argc, char *argv[])
        extern char *shell_cmd;
        extern int rsync_port;
        extern int whole_file;
        extern char *shell_cmd;
        extern int rsync_port;
        extern int whole_file;
+       extern int write_batch;
        extern int read_batch;
        int rc;
 
        extern int read_batch;
        int rc;
 
@@ -685,7 +686,7 @@ static int start_client(int argc, char *argv[])
                return start_socket_client(host, path, argc-1, argv+1);
        }
 
                return start_socket_client(host, path, argc-1, argv+1);
        }
 
-       if (!read_batch) { /* dw */
+       if (!read_batch) {
            p = find_colon(argv[0]);
 
        if (p) {
            p = find_colon(argv[0]);
 
        if (p) {
@@ -711,8 +712,11 @@ static int start_client(int argc, char *argv[])
                p = find_colon(argv[argc-1]);
                if (!p) {
                        local_server = 1;
                p = find_colon(argv[argc-1]);
                if (!p) {
                        local_server = 1;
-                       /* disable "rsync algorithm" when both sides local */
-                       if (whole_file == -1)
+                       /*
+                        * disable "rsync algorithm" when both sides local,
+                        * except when creating a batch update
+                        */
+                       if (!write_batch && whole_file == -1)
                                whole_file = 1;
                } else if (p[1] == ':') {
                        *p = 0;
                                whole_file = 1;
                } else if (p[1] == ':') {
                        *p = 0;
@@ -735,9 +739,9 @@ static int start_client(int argc, char *argv[])
                argc--;
        }
        } else {
                argc--;
        }
        } else {
-           am_sender = 1;  /*  dw */
-           local_server = 1;  /* dw */
-           shell_path = argv[argc-1];  /* dw */
+           am_sender = 1;
+           local_server = 1;
+           shell_path = argv[argc-1];
        }
 
        if (shell_machine) {
        }
 
        if (shell_machine) {
@@ -802,13 +806,11 @@ int main(int argc,char *argv[])
        extern int am_daemon;
        extern int am_server;
        int ret;
        extern int am_daemon;
        extern int am_server;
        int ret;
-       extern int read_batch;   /*  dw */
-       extern int write_batch;  /*  dw */
-       extern char *batch_ext;   /*  dw */
-       int orig_argc;  /* dw */
+       extern int write_batch;
+       int orig_argc;
        char **orig_argv;
 
        char **orig_argv;
 
-       orig_argc = argc;   /* dw */
+       orig_argc = argc;
        orig_argv = argv;
 
        signal(SIGUSR1, sigusr1_handler);
        orig_argv = argv;
 
        signal(SIGUSR1, sigusr1_handler);
@@ -847,15 +849,10 @@ int main(int argc,char *argv[])
           that implement getcwd that way "pwd" can't be found after chroot. */
        push_dir(NULL,0);
 
           that implement getcwd that way "pwd" can't be found after chroot. */
        push_dir(NULL,0);
 
-       if (write_batch) { /* dw */
-           create_batch_file_ext();
+       if (write_batch && !am_server) {
            write_batch_argvs_file(orig_argc, orig_argv);
        }
 
            write_batch_argvs_file(orig_argc, orig_argv);
        }
 
-       if (read_batch) { /* dw */
-           set_batch_file_ext(batch_ext);
-       }
-
        if (am_daemon) {
                return daemon_main();
        }
        if (am_daemon) {
                return daemon_main();
        }
@@ -882,7 +879,9 @@ int main(int argc,char *argv[])
        }
 
        ret = start_client(argc, argv);
        }
 
        ret = start_client(argc, argv);
-       exit_cleanup(ret);
+       if (ret == -1) 
+           exit_cleanup(RERR_STARTCLIENT);
+       else
+           exit_cleanup(ret);
        return ret;
 }
        return ret;
 }
-
index 98673cc..6a73e3c 100644 (file)
--- a/options.c
+++ b/options.c
@@ -87,9 +87,8 @@ int default_af_hint = AF_INET;        /* Must use IPv4 */
  * or under Unix process-monitors. **/
 int no_detach = 0;
 
  * or under Unix process-monitors. **/
 int no_detach = 0;
 
-
-int read_batch=0;
-int write_batch=0;
+int write_batch = 0;
+int read_batch = 0;
 
 char *backup_suffix = BACKUP_SUFFIX;
 char *tmpdir = NULL;
 
 char *backup_suffix = BACKUP_SUFFIX;
 char *tmpdir = NULL;
@@ -107,7 +106,7 @@ int quiet = 0;
 int always_checksum = 0;
 int list_only = 0;
 
 int always_checksum = 0;
 int list_only = 0;
 
-char *batch_ext = NULL;
+char *batch_prefix = NULL;
 
 static int modify_window_set;
 
 
 static int modify_window_set;
 
@@ -244,8 +243,8 @@ void usage(enum logcode F)
   rprintf(F,"     --log-format=FORMAT     log file transfers using specified format\n");  
   rprintf(F,"     --password-file=FILE    get password from FILE\n");
   rprintf(F,"     --bwlimit=KBPS          limit I/O bandwidth, KBytes per second\n");
   rprintf(F,"     --log-format=FORMAT     log file transfers using specified format\n");  
   rprintf(F,"     --password-file=FILE    get password from FILE\n");
   rprintf(F,"     --bwlimit=KBPS          limit I/O bandwidth, KBytes per second\n");
-  rprintf(F,"     --read-batch=EXT        read batch file\n");
-  rprintf(F,"     --write-batch           write batch file\n");
+  rprintf(F,"     --write-batch=PREFIX    write batch fileset starting with PREFIX\n");
+  rprintf(F,"     --read-batch=PREFIX     read batch fileset starting with PREFIX\n");
   rprintf(F," -h, --help                  show this help screen\n");
 #ifdef INET6
   rprintf(F," -4                          prefer IPv4\n");
   rprintf(F," -h, --help                  show this help screen\n");
 #ifdef INET6
   rprintf(F," -4                          prefer IPv4\n");
@@ -339,8 +338,8 @@ static struct poptOption long_options[] = {
   {"address",          0,  POPT_ARG_STRING, &bind_address, 0},
   {"backup-dir",       0,  POPT_ARG_STRING, &backup_dir},
   {"hard-links",      'H', POPT_ARG_NONE,   &preserve_hard_links},
   {"address",          0,  POPT_ARG_STRING, &bind_address, 0},
   {"backup-dir",       0,  POPT_ARG_STRING, &backup_dir},
   {"hard-links",      'H', POPT_ARG_NONE,   &preserve_hard_links},
-  {"read-batch",       0,  POPT_ARG_STRING, &batch_ext, OPT_READ_BATCH},
-  {"write-batch",      0,  POPT_ARG_NONE,   &write_batch},
+  {"read-batch",       0,  POPT_ARG_STRING, &batch_prefix, OPT_READ_BATCH},
+  {"write-batch",      0,  POPT_ARG_STRING, &batch_prefix, OPT_WRITE_BATCH},
 #ifdef INET6
   {0,                '4', POPT_ARG_VAL,    &default_af_hint,   AF_INET },
   {0,                '6', POPT_ARG_VAL,    &default_af_hint,   AF_INET6 },
 #ifdef INET6
   {0,                '4', POPT_ARG_VAL,    &default_af_hint,   AF_INET },
   {0,                '6', POPT_ARG_VAL,    &default_af_hint,   AF_INET6 },
@@ -523,8 +522,13 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
                        keep_partial = 1;
                        break;
 
                        keep_partial = 1;
                        break;
 
+               case OPT_WRITE_BATCH:
+                       /* popt stores the filename in batch_prefix for us */
+                       write_batch = 1;
+                       break;
+
                case OPT_READ_BATCH:
                case OPT_READ_BATCH:
-                       /* The filename is stored in batch_ext for us by popt */
+                       /* popt stores the filename in batch_prefix for us */
                        read_batch = 1;
                        break;
 
                        read_batch = 1;
                        break;
 
@@ -540,6 +544,22 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
                }
        }
 
                }
        }
 
+       if (write_batch && read_batch) {
+           snprintf(err_buf,sizeof(err_buf),
+               "write-batch and read-batch can not be used together\n");
+           rprintf(FERROR,"ERROR: write-batch and read-batch"
+               " can not be used together\n");
+           return 0;
+       }
+
+       if (do_compression && (write_batch || read_batch)) {
+           snprintf(err_buf,sizeof(err_buf),
+               "compress can not be used with write-batch or read-batch\n");
+           rprintf(FERROR,"ERROR: compress can not be used with"
+               "  write-batch or read-batch\n");
+           return 0;
+       }
+
         *argv = poptGetArgs(pc);
         if (*argv)
                 *argc = count_args(*argv);
         *argv = poptGetArgs(pc);
         if (*argv)
                 *argc = count_args(*argv);
@@ -561,8 +581,8 @@ void server_options(char **args,int *argc)
        static char mdelete[30];
        static char mwindow[30];
        static char bw[50];
        static char mdelete[30];
        static char mwindow[30];
        static char bw[50];
-       static char fext[20];
-       static char wbatch[14];
+       /* Leave room for ``--(write|read)-batch='' */
+       static char fext[MAXPATHLEN + 15];
 
        int i, x;
 
 
        int i, x;
 
@@ -644,13 +664,14 @@ void server_options(char **args,int *argc)
                args[ac++] = mdelete;
        }    
        
                args[ac++] = mdelete;
        }    
        
-       if (write_batch) {
-               snprintf(wbatch,sizeof(wbatch),"--write-batch");
-               args[ac++] = wbatch;
-       }
-
-       if (batch_ext != NULL) {
-               snprintf(fext,sizeof(fext),"--read-batch=%s",batch_ext);
+       if (batch_prefix != NULL) {
+               char *fmt = "";
+               if (write_batch)
+                   fmt = "--write-batch=%s";
+               else
+               if (read_batch)
+                   fmt = "--read-batch=%s";
+               snprintf(fext,sizeof(fext),fmt,batch_prefix);
                args[ac++] = fext;
        }
 
                args[ac++] = fext;
        }
 
index 035a352..6282e63 100644 (file)
--- a/rsync.yo
+++ b/rsync.yo
@@ -280,8 +280,8 @@ verb(
      --log-format=FORMAT     log file transfers using specified format
      --password-file=FILE    get password from FILE
      --bwlimit=KBPS          limit I/O bandwidth, KBytes per second
      --log-format=FORMAT     log file transfers using specified format
      --password-file=FILE    get password from FILE
      --bwlimit=KBPS          limit I/O bandwidth, KBytes per second
-     --read-batch=FILE       read batch file
-     --write-batch           write batch file
+     --read-batch=PREFIX     read batch fileset starting with PREFIX
+     --write-batch=PREFIX    write batch fileset starting with PREFIX
  -h, --help                  show this help screen
 
 
  -h, --help                  show this help screen
 
 
@@ -706,10 +706,13 @@ transfer was too fast, it will wait before sending the next data block. The
 result is an average transfer rate equalling the specified limit. A value
 of zero specifies no limit.
 
 result is an average transfer rate equalling the specified limit. A value
 of zero specifies no limit.
 
-dit(bf(--read-batch)) Apply a previously generated change batch.
+dit(bf(--write-batch=PREFIX)) Generate a set of files that can be
+transferred as a batch update. Each filename in the set starts with
+PREFIX. See the "BATCH MODE" section for details.
 
 
-dit(bf(--write-batch)) Generate a set of files that can be transferred
-as a batch update.
+dit(bf(--read-batch=PREFIX)) Apply a previously generated change batch,
+using the fileset whose filenames start with PREFIX. See the "BATCH
+MODE" section for details.
 
 enddit()
 
 
 enddit()
 
@@ -804,26 +807,83 @@ itemize(
 manpagesection(BATCH MODE)
 
 bf(Note:) Batch mode should be considered experimental in this version
 manpagesection(BATCH MODE)
 
 bf(Note:) Batch mode should be considered experimental in this version
-of rsync.  The interface or behaviour may change before it stabilizes.
+of rsync. The interface or behaviour may change before it stabilizes.
+
+Batch mode can be used to apply the same set of updates to many
+identical systems. Suppose one has a tree which is replicated on a
+number of hosts.  Now suppose some changes have been made to this
+source tree and those changes need to be propagated to the other
+hosts. In order to do this using batch mode, rsync is run with the
+write-batch option to apply the changes made to the source tree to one
+of the destination trees.  The write-batch option causes the rsync
+client to store the information needed to repeat this operation against
+other destination trees in a batch update fileset (see below).  The
+filename of each file in the fileset starts with a prefix specified by
+the user as an argument to the write-batch option.  This fileset is
+then copied to each remote host, where rsync is run with the read-batch
+option, again specifying the same prefix, and the destination tree.
+Rsync updates the destination tree using the information stored in the
+batch update fileset.
+
+The fileset consists of 4 files:
 
 
-The following call generates 4 files that encapsulate the information
-for synchronizing the contents of bf(target_dir) with the updates found in
-bf(src_dir)
-
-quote(
-$ rsync --write-batch [other rsync options here] \nl()
-           /somewhere/src_dir /somewhere/target_dir
+itemize(
+it() bf(<prefix>.rsync_argvs) command-line arguments
+it() bf(<prefix>.rsync_flist) rsync internal file metadata
+it() bf(<prefix>.rsync_csums) rsync checksums
+it() bf(<prefix>.rsync_delta) data blocks for file update & change
 )
 
 )
 
-The generated files are labeled with a common timestamp:
+The .rsync_argvs file contains a command-line suitable for updating a
+destination tree using that batch update fileset. It can be executed
+using a Bourne(-like) shell, optionally passing in an alternate
+destination tree pathname which is then used instead of the original
+path. This is useful when the destination tree path differs from the
+original destination tree path.
 
 
-itemize(
-it() bf(rsync_argvs.<timestamp>) command-line arguments
-it() bf(rsync_flist.<timestamp>) rsync internal file metadata
-it() bf(rsync_csums.<timestamp>) rsync checksums
-it() bf(rsync_delta.<timestamp>) data blocks for file update & change
+Generating the batch update fileset once saves having to perform the
+file status, checksum and data block generation more than once when
+updating multiple destination trees. Multicast transport protocols can
+be used to transfer the batch update files in parallel to many hosts at
+once, instead of sending the same data to every host individually.
+
+Example:
+
+verb(
+$ rsync --write_batch=pfx -a /source/dir/ /adest/dir/
+$ rcp pfx.rsync_* remote:
+$ rsh remote rsync --read_batch=pfx -a /bdest/dir/
+# or alternatively
+$ rsh remote ./pfx.rsync_argvs /bdest/dir/
 )
 
 )
 
+In this example, rsync is used to update /adest/dir/ with /source/dir/
+and the information to repeat this operation is stored in the files
+pfx.rsync_*. These files are then copied to the machine named "remote".
+Rsync is then invoked on "remote" to update /bdest/dir/ the same way as
+/adest/dir/. The last line shows the rsync_argvs file being used to
+invoke rsync.
+
+Caveats:
+
+The read-batch option expects the destination tree it is meant to update
+to be identical to the destination tree that was used to create the
+batch update fileset.  When a difference between the destination trees
+is encountered the update will fail at that point, leaving the
+destination tree in a partially updated state. In that case, rsync can
+be used in its regular (non-batch) mode of operation to fix up the
+destination tree.
+
+The rsync version used on all destinations should be identical to the
+one used on the original destination.
+
+The -z/--compress option does not work in batch mode and yields a usage
+error. A separate compression tool can be used instead to reduce the
+size of the batch update files for transport to the destination.
+
+The -n/--dryrun option does not work in batch mode and yields a runtime
+error.
+
 See bf(http://www.ils.unc.edu/i2dsi/unc_rsync+.html) for papers and technical
 reports.
 
 See bf(http://www.ils.unc.edu/i2dsi/unc_rsync+.html) for papers and technical
 reports.