Latest version of the batch mode cleanup patch

Jos Backus josb at cncdsl.com
Thu Feb 7 06:55:29 EST 2002


Here's the latest version of the batch mode cleanup patch.

Index: batch.c
===================================================================
RCS file: /cvsroot/rsync/batch.c,v
retrieving revision 1.12
diff -u -r1.12 batch.c
--- batch.c	24 Jan 2002 08:09:46 -0000	1.12
+++ batch.c	6 Feb 2002 19:47:57 -0000
@@ -8,55 +8,38 @@
 #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;
 
-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);
-}
-
-void set_batch_file_ext(char *ext)
-{
-	strcpy(batch_file_ext, 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";
+
+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)
 {
+	char filename[MAXPATHLEN];
 
 	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",
-				rsync_flist_file, strerror(errno));
+				filename, strerror(errno));
 			close(fdb);
 			exit_cleanup(1);
 		}
@@ -67,12 +50,11 @@
 
 	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);
 	}
 
-
 	if (fdb_close) {
 		close(fdb);
 	}
@@ -110,7 +92,6 @@
 		}
 		write_char_bufs(fptr[i]->sum);
 	}
-
 }
 
 void write_char_bufs(char *buf)
@@ -118,11 +99,8 @@
 	/* 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));
 
@@ -137,36 +115,52 @@
 {
 	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",
-			rsync_argvs_file, strerror(errno));
+			filename, strerror(errno));
 		close(fdb);
 		exit_cleanup(1);
 	}
 	buff[0] = '\0';
+
 	/* 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
 		 */
-		if (!strcmp(argv[i], "--write-batch")) {
+		if (!strncmp(argv[i], "--write-batch",
+			strlen("--write-batch"))) {
 			/* 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));
 		}
 
@@ -177,14 +171,14 @@
 	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);
 }
 
-struct file_list *create_flist_from_batch()
+struct file_list *create_flist_from_batch(void)
 {
 	unsigned char flags;
 
@@ -201,7 +195,7 @@
 	    (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()) {
@@ -231,23 +225,23 @@
 	}
 
 	return batch_flist;
-
 }
 
 int read_batch_flist_file(char *buff, int len)
 {
 	int bytes_read;
+	char filename[MAXPATHLEN];
 
 	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 */
-		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",
-				rsync_flist_file, strerror(errno));
+				filename, strerror(errno));
 			close(fdb);
 			exit_cleanup(1);
 		}
@@ -256,17 +250,17 @@
 
 	/* 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",
-			rsync_flist_file, strerror(errno));
+			filename, strerror(errno));
 		close(fdb);
 		exit_cleanup(1);
-	}
-	if (bytes_read == 0) {	/* EOF */
+		break;
+	    case 0:	/* EOF */
 		close(fdb);
 	}
+
 	return bytes_read;
 }
 
@@ -293,8 +287,12 @@
 		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));
@@ -356,20 +354,23 @@
 
 void write_batch_csums_file(void *buff, int bytes_to_write)
 {
-
 	static int fdb_open = 1;
+	char filename[MAXPATHLEN];
 
 	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",
-				rsync_csums_file, strerror(errno));
+				filename, strerror(errno));
 			close(fdb);
 			exit_cleanup(1);
 		}
@@ -380,16 +381,15 @@
 
 	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);
 	}
 }
 
-void close_batch_csums_file()
+void close_batch_csums_file(void)
 {
 	close(fdb);
-
 }
 
 void write_batch_csum_info(int *flist_entry, int flist_count,
@@ -405,10 +405,7 @@
 
 	/* 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++) {
@@ -417,8 +414,7 @@
 			    && (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 @@
 {
 	static int fdb_open = 1;
 	int bytes_read;
+	char filename[MAXPATHLEN];
 
 	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 */
-		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",
-				rsync_csums_file, strerror(errno));
+				filename, strerror(errno));
 			close(fdb);
 			exit_cleanup(1);
 		}
@@ -450,14 +447,14 @@
 
 	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);
 	}
+
 	return bytes_read;
 }
 
-
 void read_batch_csum_info(int flist_entry, struct sum_struct *s,
 			  int *checksums_match)
 {
@@ -468,11 +465,9 @@
 	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) {
-		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);
@@ -488,31 +483,33 @@
 			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  */
 	}
-
 }
 
 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 */
-		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",
-				rsync_delta_file, strerror(errno));
+				filename, strerror(errno));
 			close(fdb_delta);
 			exit_cleanup(1);
 		}
@@ -523,32 +520,33 @@
 
 	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);
 	}
 }
-void close_batch_delta_file()
+
+void close_batch_delta_file(void)
 {
 	close(fdb_delta);
-
 }
 
 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) {
-
-		/*  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 */
-		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",
-				rsync_delta_file, strerror(errno));
+				filename, strerror(errno));
 			close(fdb_delta);
 			exit_cleanup(1);
 		}
@@ -561,13 +559,13 @@
 
 	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);
 	}
+
 	return bytes_read;
 }
-
 
 void show_flist(int index, struct file_struct **fptr)
 {
Index: log.c
===================================================================
RCS file: /cvsroot/rsync/log.c,v
retrieving revision 1.56
diff -u -r1.56 log.c
--- log.c	24 Jan 2002 02:41:38 -0000	1.56
+++ log.c	6 Feb 2002 19:48:04 -0000
@@ -559,20 +559,16 @@
 	}
 }
 
-
-
-
-/* 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;
 
-	rprintf(FINFO,"%s\n", fname);
+	rprintf(FINFO, "%s\n", fname);
 }
-
Index: main.c
===================================================================
RCS file: /cvsroot/rsync/main.c,v
retrieving revision 1.139
diff -u -r1.139 main.c
--- main.c	5 Feb 2002 23:05:32 -0000	1.139
+++ main.c	6 Feb 2002 19:48:04 -0000
@@ -177,7 +177,7 @@
 	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)
@@ -230,7 +230,7 @@
 
 	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);
@@ -443,8 +443,8 @@
 	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());
@@ -470,7 +470,7 @@
 	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);
@@ -497,7 +497,7 @@
 	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);
 
@@ -508,7 +508,7 @@
 		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();
@@ -527,19 +527,19 @@
  */
 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;
-	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)
-	    flist = batch_flist;  /* dw */
+	    flist = batch_flist;
 
 	set_nonblocking(f_in);
 	set_nonblocking(f_out);
@@ -582,7 +582,7 @@
 		list_only = 1;
 	}
 	
-	if (!write_batch) /* dw */
+	if (!write_batch)
 	    send_exclude_list(f_out);
 	
 	flist = recv_file_list(f_in);
@@ -658,6 +658,7 @@
 	extern char *shell_cmd;
 	extern int rsync_port;
 	extern int whole_file;
+	extern int write_batch;
 	extern int read_batch;
 	int rc;
 
@@ -685,7 +686,7 @@
 		return start_socket_client(host, path, argc-1, argv+1);
 	}
 
-	if (!read_batch) { /* dw */
+	if (!read_batch) {
 	    p = find_colon(argv[0]);
 
 	if (p) {
@@ -711,8 +712,11 @@
 		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;
@@ -735,9 +739,9 @@
 		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) {
@@ -802,13 +806,11 @@
 	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;
 
-	orig_argc = argc;   /* dw */
+	orig_argc = argc;
 	orig_argv = argv;
 
 	signal(SIGUSR1, sigusr1_handler);
@@ -847,15 +849,10 @@
 	   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);
 	}
 
-	if (read_batch) { /* dw */
-	    set_batch_file_ext(batch_ext);
-	}
-
 	if (am_daemon) {
 		return daemon_main();
 	}
@@ -885,4 +882,3 @@
 	exit_cleanup(ret);
 	return ret;
 }
-
Index: options.c
===================================================================
RCS file: /cvsroot/rsync/options.c,v
retrieving revision 1.78
diff -u -r1.78 options.c
--- options.c	5 Feb 2002 23:05:32 -0000	1.78
+++ options.c	6 Feb 2002 19:48:05 -0000
@@ -87,9 +87,8 @@
  * 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;
@@ -107,7 +106,7 @@
 int always_checksum = 0;
 int list_only = 0;
 
-char *batch_ext = NULL;
+char *batch_prefix = NULL;
 
 static int modify_window_set;
 
@@ -244,8 +243,8 @@
   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");
@@ -339,8 +338,8 @@
   {"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 },
@@ -523,8 +522,13 @@
 			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:
-			/* The filename is stored in batch_ext for us by popt */
+			/* popt stores the filename in batch_prefix for us */
 			read_batch = 1;
 			break;
 
@@ -540,6 +544,22 @@
 		}
 	}
 
+	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);
@@ -561,8 +581,8 @@
 	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;
 
@@ -644,13 +664,14 @@
 		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;
 	}
 
Index: proto.h
===================================================================
RCS file: /cvsroot/rsync/proto.h,v
retrieving revision 1.140
diff -u -r1.140 proto.h
--- proto.h	25 Jan 2002 23:07:33 -0000	1.140
+++ proto.h	6 Feb 2002 19:48:05 -0000
@@ -4,25 +4,23 @@
 char *auth_server(int fd, int module, char *addr, char *leader);
 void auth_client(int fd, char *user, char *challenge);
 int make_backup(char *fname);
-void create_batch_file_ext();
-void set_batch_file_ext(char *ext);
 void write_batch_flist_file(char *buff, int bytes_to_write);
 void write_batch_flist_info(int flist_count, struct file_struct **fptr);
 void write_char_bufs(char *buf);
 void write_batch_argvs_file(int argc, char *argv[]);
-struct file_list *create_flist_from_batch();
+struct file_list *create_flist_from_batch(void);
 int read_batch_flist_file(char *buff, int len);
 unsigned char read_batch_flags();
 void read_batch_flist_info(struct file_struct **fptr);
 void write_batch_csums_file(void *buff, int bytes_to_write);
-void close_batch_csums_file();
+void close_batch_csums_file(void);
 void write_batch_csum_info(int *flist_entry, int flist_count,
 			   struct sum_struct *s);
 int read_batch_csums_file(char *buff, int len);
 void read_batch_csum_info(int flist_entry, struct sum_struct *s,
 			  int *checksums_match);
 void write_batch_delta_file(char *buff, int bytes_to_write);
-void close_batch_delta_file();
+void close_batch_delta_file(void);
 int read_batch_delta_file(char *buff, int len);
 void show_flist(int index, struct file_struct **fptr);
 void show_argvs(int argc, char *argv[]);
Index: rsync.1
===================================================================
RCS file: /cvsroot/rsync/rsync.1,v
retrieving revision 1.109
diff -u -r1.109 rsync.1
--- rsync.1	5 Feb 2002 23:05:32 -0000	1.109
+++ rsync.1	6 Feb 2002 19:48:06 -0000
@@ -308,8 +308,8 @@
      --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
+     --write-batch=PREFIX    write batch fileset starting with PREFIX
+     --read-batch=PREFIX     read batch fileset starting with PREFIX
  -h, --help                  show this help screen
 
 
@@ -809,12 +809,14 @@
 result is an average transfer rate equalling the specified limit\&. A value
 of zero specifies no limit\&.
 .IP 
-.IP "\fB--read-batch\fP" 
-Apply a previously generated change batch\&.
-.IP 
-.IP "\fB--write-batch\fP" 
-Generate a set of files that can be transferred
-as a batch update\&.
+.IP "\fB--write-batch=PREFIX\fP" 
+Generate a set of files that can be transferred as a batch update\&. Each
+filename in the set starts with \fBPREFIX\fP. See the "BATCH MODE" section
+for details.
+.IP 
+.IP "\fB--read-batch=PREFIX\fP" 
+Apply a previously generated change batch, using the fileset whose filenames
+start with \fBPREFIX\fP\&. See the "BATCH MODE" section for details.
 .IP 
 .PP 
 .SH "EXCLUDE PATTERNS" 
@@ -921,29 +923,86 @@
 \fBNote:\fP Batch mode should be considered experimental in this version
 of rsync\&.  The interface or behaviour may change before it stabilizes\&.
 .PP 
-The following call generates 4 files that encapsulate the information
-for synchronizing the contents of \fBtarget_dir\fP with the updates found in
-\fBsrc_dir\fP
-.PP 
+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\&.
+.PP
+The fileset consists of 4 files:
+.IP o 
+<prefix>\fB.rsync_argvs\fP command-line arguments
+.IP o 
+<prefix>\fB.rsync_flist\fP rsync internal file metadata
+.IP o 
+<prefix>\fB.rsync_csums\fP rsync checksums
+.IP o 
+<prefix>\fB.rsync_delta\fP data blocks for file update & change
+.PP
+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\&.
+.PP
+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\&.
+.PP
+Example:
+.PP
 .RS 
-$ rsync --write-batch [other rsync options here] \e
-.br 
-/somewhere/src_dir /somewhere/target_dir
+.nf
+$ rsync --write_batch=pfx -a /source/dir/ /adest/dir/
+$ rcp pfx.rsync_* remote:
+$ rsh remote rsync --read_batch=pfx -a /bdest/dir/
+# or even
+$ rsh remote ./pfx.rsync_argvs /bdest/dir/
+.fi
 .RE 
+.PP
+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_{argvs,flist,csums,delta}\&. 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\&.
+.PP
+\fBCaveats\fP:
+.IP o
+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\&.
+.IP o
+The rsync version used on all destinations should be identical to the
+one used on the original destination\&.
+.IP o
+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\&.
+.IP o
+The -n/--dryrun option does not work in batch mode and yields a runtime
+error\&.
 .PP 
-The generated files are labeled with a common timestamp:
-.PP 
-.IP o 
-\fBrsync_argvs\&.<timestamp>\fP command-line arguments
-.IP o 
-\fBrsync_flist\&.<timestamp>\fP rsync internal file metadata
-.IP o 
-\fBrsync_csums\&.<timestamp>\fP rsync checksums
-.IP o 
-\fBrsync_delta\&.<timestamp>\fP data blocks for file update & change
-.PP 
-See \fBhttp://www\&.ils\&.unc\&.edu/i2dsi/unc_rsync+\&.html\fP for papers and technical
-reports\&.
+See \fBhttp://www\&.ils\&.unc\&.edu/i2dsi/unc_rsync+\&.html\fP for
+papers and technical reports\&.
 .PP 
 .SH "SYMBOLIC LINKS" 
 .PP 
Index: rsync.yo
===================================================================
RCS file: /cvsroot/rsync/rsync.yo,v
retrieving revision 1.94
diff -u -r1.94 rsync.yo
--- rsync.yo	5 Feb 2002 23:05:33 -0000	1.94
+++ rsync.yo	6 Feb 2002 19:48:07 -0000
@@ -280,8 +280,8 @@
      --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
 
 
@@ -706,10 +706,13 @@
 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)) Generate a set of files that can be transferred
-as a batch update.
+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(--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()
 
@@ -804,25 +807,82 @@
 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.
 
-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)
+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.
 
-quote(
-$ rsync --write-batch [other rsync options here] \nl()
-           /somewhere/src_dir /somewhere/target_dir
+The fileset consists of 4 files:
+
+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.
+
+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.
 
-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
+Example:
+
+quote(
+$ rsync --write_batch=pfx -a /source/dir/ /adest/dir/
+$ rcp pfx.rsync_* remote:
+$ rsh remote rsync --read_batch=pfx -a /bdest/dir/
+# or even
+$ 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_{argvs,flist,csums,delta}. 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.

-- 
Jos Backus                 _/  _/_/_/        Santa Clara, CA
                          _/  _/   _/
                         _/  _/_/_/             
                    _/  _/  _/    _/
josb at cncdsl.com     _/_/   _/_/_/            use Std::Disclaimer;




More information about the rsync mailing list