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