patch to rsync to add options for pre- and post-transfer commands

David S. Ahern dahern at avaya.com
Sat Jun 7 06:21:20 EST 2003


In case others find this of value, I wrote a patch to rsync 2.5.6 to 
give rsync in --daemon mode the ability to run a pre-transfer and 
post-transfer command. These options handle our need to prepare a server 
to receive files and to do some processing after receiving files.

The options for /etc/rsyncd.conf are
	pretransfer script = /some/command/to/run
         posttransfer script = /some/other/command

The commands are exec'd (not run through system() or popen()) and the 
inputs are the list of files (and directories) that are being synched 
(from struct file_list *flist).

If the pretransfer script fails the synch is stopped.

-- 
david ahern
-------------- next part --------------
Only in rsync-2.5.6: config.h
Only in rsync-2.5.6: config.log
Only in rsync-2.5.6: config.status
Common subdirectories: rsync-2.5.6.orig/doc and rsync-2.5.6/doc
diff --exclude='*.o' -b --context rsync-2.5.6.orig/errcode.h rsync-2.5.6/errcode.h
*** rsync-2.5.6.orig/errcode.h	2002-04-08 23:29:26.000000000 -0600
--- rsync-2.5.6/errcode.h	2003-04-28 20:32:40.000000000 -0600
***************
*** 35,40 ****
--- 35,44 ----
  #define RERR_MESSAGEIO  13      /* errors with program diagnostics */
  #define RERR_IPC        14      /* error in IPC code */
  
+ #define RERR_PRESCRIPT  17      /* error running pre-transfer script */
+ #define RERR_POSTSCRIPT 18      /* error running post-transfer script */
+ #define RERR_SCRIPT     19      /* system error running transfer script */
+ 
  #define RERR_SIGNAL     20      /* status returned when sent SIGUSR1, SIGINT */
  #define RERR_WAITCHILD  21      /* some error returned by waitpid() */
  #define RERR_MALLOC     22      /* error allocating core memory buffers */
Common subdirectories: rsync-2.5.6.orig/lib and rsync-2.5.6/lib
diff --exclude='*.o' -b --context rsync-2.5.6.orig/loadparm.c rsync-2.5.6/loadparm.c
*** rsync-2.5.6.orig/loadparm.c	2002-08-30 17:27:26.000000000 -0600
--- rsync-2.5.6/loadparm.c	2003-04-27 20:25:42.000000000 -0600
***************
*** 140,145 ****
--- 140,147 ----
  	int timeout;
  	int max_connections;
  	BOOL ignore_nonreadable;
+ 	char *prescript;
+ 	char *postscript;
  } service;
  
  
***************
*** 180,186 ****
  	"*.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz",    /* dont compress */
  	0,        /* timeout */
  	0,        /* max connections */
! 	False     /* ignore nonreadable */
  };
  
  
--- 182,191 ----
  	"*.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz",    /* dont compress */
  	0,        /* timeout */
  	0,        /* max connections */
! 	False,    /* ignore nonreadable */
! 
! 	NULL,     /* pre-transfer script */
! 	NULL,     /* post-transfer script */
  };
  
  
***************
*** 295,300 ****
--- 300,307 ----
    {"log format",       P_STRING,  P_LOCAL,  &sDefault.log_format,  NULL,   0},
    {"refuse options",   P_STRING,  P_LOCAL,  &sDefault.refuse_options,NULL, 0},
    {"dont compress",    P_STRING,  P_LOCAL,  &sDefault.dont_compress,NULL,  0},
+   {"pretransfer script",    P_STRING,  P_LOCAL,  &sDefault.prescript,NULL,  0},
+   {"posttransfer script",   P_STRING,  P_LOCAL,  &sDefault.postscript,NULL,  0},
    {NULL,               P_BOOL,    P_NONE,   NULL,                  NULL,   0}
  };
  
***************
*** 374,379 ****
--- 381,388 ----
  FN_LOCAL_STRING(lp_dont_compress, dont_compress)
  FN_LOCAL_INTEGER(lp_timeout, timeout)
  FN_LOCAL_INTEGER(lp_max_connections, max_connections)
+ FN_LOCAL_STRING(lp_prescript, prescript)
+ FN_LOCAL_STRING(lp_postscript, postscript)
  
  /* local prototypes */
  static int    strwicmp( char *psz1, char *psz2 );
diff --exclude='*.o' -b --context rsync-2.5.6.orig/log.c rsync-2.5.6/log.c
*** rsync-2.5.6.orig/log.c	2002-12-24 00:42:04.000000000 -0700
--- rsync-2.5.6/log.c	2003-04-28 09:32:31.000000000 -0600
***************
*** 49,54 ****
--- 49,56 ----
  	{ RERR_STREAMIO   , "error in rsync protocol data stream" }, 
  	{ RERR_MESSAGEIO  , "errors with program diagnostics" }, 
  	{ RERR_IPC        , "error in IPC code" }, 
+ 	{ RERR_PRESCRIPT  , "error running pre-transfer script" }, 
+ 	{ RERR_POSTSCRIPT , "error running post-transfer script" }, 
  	{ RERR_SIGNAL     , "received SIGUSR1 or SIGINT" }, 
  	{ RERR_WAITCHILD  , "some error returned by waitpid()" }, 
  	{ RERR_MALLOC     , "error allocating core memory buffers" }, 
diff --exclude='*.o' -b --context rsync-2.5.6.orig/main.c rsync-2.5.6/main.c
*** rsync-2.5.6.orig/main.c	2003-01-27 22:05:53.000000000 -0700
--- rsync-2.5.6/main.c	2003-05-19 14:18:32.000000000 -0600
***************
*** 69,75 ****
           * message describing the purpose of the child.  Also indicate
           * this to the caller so that thhey know something went
           * wrong.  */
! 	*status = WEXITSTATUS(*status);
  }
  
  static void report(int f)
--- 69,75 ----
           * message describing the purpose of the child.  Also indicate
           * this to the caller so that thhey know something went
           * wrong.  */
! 	if (WIFEXITED(*status) != 0) *status = WEXITSTATUS(*status);
  }
  
  static void report(int f)
***************
*** 384,389 ****
--- 384,486 ----
  }
  
  
+ static int run_xfer_script(const char *script, const struct file_list *flist, const char *name)
+ {
+ 	int status;
+ 	pid_t cmd;
+ 
+ 	cmd = fork();
+ 	switch (cmd) {
+ 		case 0:   /* child */
+ 		{
+ 			char **pargv;
+ 			char *fname;
+ 			int i, j;
+ 
+ 			pargv = (char **) malloc((flist->count + 2)*sizeof(char *));
+ 			if (pargv == NULL) {
+ 				rprintf(FERROR,"ERROR: malloc for argv failed: %s\n",
+ 		                strerror(errno));
+ 				return(RERR_MALLOC);
+ 			}
+ 
+ 			/* first arg is basename of command to be run */
+ 			pargv[0] = basename(script);
+ 
+ 			/* add file list */
+ 			j = 1;
+ 			for (i = 0; i < flist->count; ++i)
+ 			{
+ 				/* get full path to file; need to make a copy
+ 				 * because f_name uses a static buffer
+ 				 */
+ 				fname = f_name(flist->files[i]);
+ 				if (fname == NULL) continue;
+ 
+ 				pargv[j] = strdup(fname);
+ 				if (pargv[j] == NULL) {
+ 					rprintf(FERROR,"ERROR: strdup of file name %s failed: %s\n",
+ 					        fname, strerror(errno));
+ 					return(RERR_MALLOC);
+ 				} 
+ 				j++;
+ 			}
+ 			pargv[j] = NULL;
+ 
+ 			execv(script, pargv);
+ 			rprintf(FERROR,"ERROR: exec on %s script failed: %s\n",
+ 					name, strerror(errno));
+ 			exit(RERR_SCRIPT);
+ 			break;
+ 		}
+ 
+ 		case -1:
+ 			rprintf(FERROR,"ERROR: fork for %s script failed: %s\n",
+ 					name, strerror(errno));
+ 			return(RERR_SCRIPT);
+ 			break;
+ 	
+ 		default:
+ 			status = -1;
+ 			wait_process(cmd, &status);
+ 			if ( (verbose > 1) || (status != 0) ) {
+ 				rprintf(FINFO,"%s script exited with %d status\n",
+ 				        name, status);
+ 			}
+ 	}
+ 
+ 	return(status);
+ }
+ 
+ 
+ static int run_prescript(const struct file_list *flist)
+ {
+ 	extern int module_id;
+ 	const char *prescript = lp_prescript(module_id);
+ 	
+ 	if ( (prescript == NULL) || (*prescript == '\0') ) return(0);
+ 	if (verbose > 1) {
+ 		rprintf(FINFO,"running pre-transfer script: %s\n", prescript);
+ 	}
+ 
+ 	return(run_xfer_script(prescript, flist, "pre-transfer"));
+ }
+ 
+ 
+ static int run_postscript(const struct file_list *flist)
+ {
+ 	extern int module_id;
+ 	const char *postscript = lp_postscript(module_id);
+ 
+ 	if ( (postscript == NULL) || (*postscript == '\0') ) return(0);
+ 	if (verbose > 1) {
+ 		rprintf(FINFO,"running post-transfer script: %s\n", postscript);
+ 	}
+ 
+ 	return(run_xfer_script(postscript, flist, "post-transfer"));
+ }
+ 
+ 
  static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
  {
  	int pid;
***************
*** 416,421 ****
--- 513,522 ----
  		exit_cleanup(RERR_SOCKETIO);
  	}
    
+ 	if (run_prescript(flist) != 0) {
+ 		exit_cleanup(RERR_PRESCRIPT);
+ 	}
+ 
  	io_flush();
  
  	if ((pid=do_fork()) == 0) {
***************
*** 464,469 ****
--- 565,575 ----
  	io_set_error_fd(-1);
  	kill(pid, SIGUSR2);
  	wait_process(pid, &status);
+ 
+ 	if (run_postscript(flist) != 0) {
+ 		exit_cleanup(RERR_POSTSCRIPT);
+ 	}
+ 
  	return status;
  }
  
Only in rsync-2.5.6: main.c.ver1
Only in rsync-2.5.6: Makefile
Common subdirectories: rsync-2.5.6.orig/packaging and rsync-2.5.6/packaging
Common subdirectories: rsync-2.5.6.orig/patches and rsync-2.5.6/patches
Common subdirectories: rsync-2.5.6.orig/popt and rsync-2.5.6/popt
diff --exclude='*.o' -b --context rsync-2.5.6.orig/proto.h rsync-2.5.6/proto.h
*** rsync-2.5.6.orig/proto.h	2003-01-26 20:35:09.000000000 -0700
--- rsync-2.5.6/proto.h	2003-04-27 11:34:53.000000000 -0600
***************
*** 151,156 ****
--- 151,158 ----
  BOOL lp_load(char *pszFname, int globals_only);
  int lp_numservices(void);
  int lp_number(char *name);
+ char *lp_prescript(int );
+ char *lp_postscript(int );
  void err_list_push(void);
  void log_init(void);
  void log_open(void);
Only in rsync-2.5.6: rsync
Only in rsync-2.5.6: rsync_script.patch
Only in rsync-2.5.6: shconfig
diff --exclude='*.o' -b --context rsync-2.5.6.orig/socket.c rsync-2.5.6/socket.c
*** rsync-2.5.6.orig/socket.c	2003-01-26 20:35:09.000000000 -0700
--- rsync-2.5.6/socket.c	2003-05-19 14:22:41.000000000 -0600
***************
*** 419,426 ****
  
  		if (fd == -1) continue;
  
  		signal(SIGCHLD, SIG_IGN);
! 
  		/* we shouldn't have any children left hanging around
  		   but I have had reports that on Digital Unix zombies
  		   are produced, so this ensures that they are reaped */
--- 419,432 ----
  
  		if (fd == -1) continue;
  
+ #if 0
+ 		/* This resets the signal handler set in main.c!
+ 		 * which means after the first accept, wait_process
+ 		 * does not work as intended. I get the impression
+ 		 * this was a haphazard "fix", so comment it out.
+ 		 */
  		signal(SIGCHLD, SIG_IGN);
! #endif
  		/* we shouldn't have any children left hanging around
  		   but I have had reports that on Digital Unix zombies
  		   are produced, so this ensures that they are reaped */
Only in rsync-2.5.6: tags
Common subdirectories: rsync-2.5.6.orig/testhelp and rsync-2.5.6/testhelp
Common subdirectories: rsync-2.5.6.orig/testsuite and rsync-2.5.6/testsuite
Common subdirectories: rsync-2.5.6.orig/zlib and rsync-2.5.6/zlib


More information about the rsync mailing list