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
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
-- 
To unsubscribe or change options: http://lists.samba.org/mailman/listinfo/rsync
Before posting, read: http://www.catb.org/~esr/faqs/smart-questions.html

Reply via email to