Added the --remote-option=OPT (-M OPT) option.
authorWayne Davison <wayned@samba.org>
Sat, 5 Jul 2008 15:30:16 +0000 (08:30 -0700)
committerWayne Davison <wayned@samba.org>
Sat, 5 Jul 2008 15:31:16 +0000 (08:31 -0700)
NEWS
options.c
pipe.c
rsync.yo

diff --git a/NEWS b/NEWS
index 70af495..5e92e72 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -9,7 +9,8 @@ Changes since 3.0.3:
 
   ENHANCEMENTS:
 
-    - ...
+    - Added the --remote-option=OPT (-M OPT) command-line option that is useful
+      for things like sending a remote --log-file=FILE or --fake-super option.
 
   DEVELOPER RELATED:
 
index 0ac5bfd..a79c553 100644 (file)
--- a/options.c
+++ b/options.c
@@ -174,6 +174,10 @@ int link_dest = 0;
 int basis_dir_cnt = 0;
 char *dest_option = NULL;
 
+static int remote_option_alloc = 0;
+int remote_option_cnt = 0;
+const char **remote_options = NULL;
+
 int verbose = 0;
 int quiet = 0;
 int output_motd = 1;
@@ -387,6 +391,7 @@ void usage(enum logcode F)
   rprintf(F,"     --timeout=SECONDS       set I/O timeout in seconds\n");
   rprintf(F,"     --contimeout=SECONDS    set daemon connection timeout in seconds\n");
   rprintf(F," -I, --ignore-times          don't skip files that match in size and mod-time\n");
+  rprintf(F," -M, --remote-option=OPTION  send OPTION to the remote side only\n");
   rprintf(F,"     --size-only             skip files that match in size\n");
   rprintf(F,"     --modify-window=NUM     compare mod-times with reduced accuracy\n");
   rprintf(F," -T, --temp-dir=DIR          create temporary files in directory DIR\n");
@@ -645,6 +650,7 @@ static struct poptOption long_options[] = {
   {"password-file",    0,  POPT_ARG_STRING, &password_file, 0, 0, 0 },
   {"blocking-io",      0,  POPT_ARG_VAL,    &blocking_io, 1, 0, 0 },
   {"no-blocking-io",   0,  POPT_ARG_VAL,    &blocking_io, 0, 0, 0 },
+  {"remote-option",   'M', POPT_ARG_STRING, 0, 'M', 0, 0 },
   {"protocol",         0,  POPT_ARG_INT,    &protocol_version, 0, 0, 0 },
   {"checksum-seed",    0,  POPT_ARG_INT,    &checksum_seed, 0, 0, 0 },
   {"server",           0,  POPT_ARG_NONE,   0, OPT_SERVER, 0, 0 },
@@ -1140,6 +1146,26 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                        }
                        break;
 
+               case 'M':
+                       arg = poptGetOptArg(pc);
+                       if (*arg != '-') {
+                               snprintf(err_buf, sizeof err_buf,
+                                       "Remote option must start with a dash: %s\n", arg);
+                               return 0;
+                       }
+                       if (remote_option_cnt+2 >= remote_option_alloc) {
+                               remote_option_alloc += 16;
+                               remote_options = realloc_array(remote_options,
+                                                       const char *, remote_option_alloc);
+                               if (!remote_options)
+                                       out_of_memory("parse_arguments");
+                               if (!remote_option_cnt)
+                                       remote_options[0] = "ARG0";
+                       }
+                       remote_options[++remote_option_cnt] = arg;
+                       remote_options[remote_option_cnt+1] = NULL;
+                       break;
+
                case OPT_WRITE_BATCH:
                        /* batch_name is already set */
                        write_batch = 1;
@@ -1830,6 +1856,11 @@ void server_options(char **args, int *argc_p)
 #endif
        argstr[x] = '\0';
 
+       if (x > (int)sizeof argstr) { /* Not possible... */
+               rprintf(FERROR, "argstr overflow in server_options().\n");
+               exit_cleanup(RERR_MALLOC);
+       }
+
        args[ac++] = argstr;
 
 #ifdef ICONV_OPTION
@@ -2052,6 +2083,21 @@ void server_options(char **args, int *argc_p)
        else if (remove_source_files)
                args[ac++] = "--remove-sent-files";
 
+       if (ac > MAX_SERVER_ARGS) { /* Not possible... */
+               rprintf(FERROR, "argc overflow in server_options().\n");
+               exit_cleanup(RERR_MALLOC);
+       }
+
+       if (remote_option_cnt) {
+               int j;
+               if (ac + remote_option_cnt > MAX_SERVER_ARGS) {
+                       rprintf(FERROR, "too many remote options specified.\n");
+                       exit_cleanup(RERR_SYNTAX);
+               }
+               for (j = 1; j <= remote_option_cnt; j++)
+                       args[ac++] = (char*)remote_options[j];
+       }
+
        *argc_p = ac;
        return;
 
diff --git a/pipe.c b/pipe.c
index 5f79ede..f32d63e 100644 (file)
--- a/pipe.c
+++ b/pipe.c
@@ -28,6 +28,8 @@ extern int blocking_io;
 extern int filesfrom_fd;
 extern mode_t orig_umask;
 extern char *logfile_name;
+extern int remote_option_cnt;
+extern const char **remote_options;
 extern struct chmod_mode_struct *chmod_modes;
 
 /**
@@ -139,6 +141,15 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
                        logfile_close();
                }
 
+               if (remote_option_cnt) {
+                       int rc = remote_option_cnt + 1;
+                       const char **rv = remote_options;
+                       if (!parse_arguments(&rc, &rv)) {
+                               option_error();
+                               exit_cleanup(RERR_SYNTAX);
+                       }
+               }
+
                if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
                    close(to_child_pipe[1]) < 0 ||
                    close(from_child_pipe[0]) < 0 ||
index 2838e0d..3377312 100644 (file)
--- a/rsync.yo
+++ b/rsync.yo
@@ -412,6 +412,7 @@ to the detailed description below for a complete description.  verb(
      --progress              show progress during transfer
  -P                          same as --partial --progress
  -i, --itemize-changes       output a change-summary for all updates
+ -M, --remote-option=OPTION  send OPTION to the remote side only
      --out-format=FORMAT     output updates using the specified FORMAT
      --log-file=FILE         log what we're doing to the specified FILE
      --log-file-format=FMT   log updates using the specified FMT
@@ -1026,16 +1027,16 @@ This is a good way to backup data without using a super-user, and to store
 ACLs from incompatible systems.
 
 The bf(--fake-super) option only affects the side where the option is used.
-To affect the remote side of a remote-shell connection, specify an rsync
-path:
+To affect the remote side of a remote-shell connection, use the
+bf(--remote-option) (bf(-M)) option:
 
-quote(tt(  rsync -av --rsync-path="rsync --fake-super" /src/ host:/dest/))
+quote(tt(  rsync -av -M--fake-super /src/ host:/dest/))
 
-Since there is only one "side" in a local copy, this option affects both
-the sending and receiving of files.  You'll need to specify a copy using
-"localhost" if you need to avoid this, possibly using the "lsh" shell
-script (from the support directory) as a substitute for an actual remote
-shell (see bf(--rsh)).
+For a local copy, this option affects both the source and the destination.
+If you wish a local copy to enable this option just for the destination
+files, specify bf(-M--fake-super).  If you wish a local copy to enable
+this option just for the source files, combine bf(--fake-super) with
+bf(-M--super).
 
 This option is overridden by both bf(--super) and bf(--no-super).
 
@@ -1288,6 +1289,36 @@ machine for use with the bf(--relative) option.  For instance:
 
 quote(tt(    rsync -avR --rsync-path="cd /a/b && rsync" host:c/d /e/))
 
+dit(bf(-M, --remote-option=OPTION)) This option is used for more advanced
+situations where you want certain effects to be limited to one side of the
+transfer only.  For instance, if you want to pass bf(--log-file=FILE) and
+bf(--fake-super) to the remote system, specify it like this:
+
+quote(tt(    rsync -av -M --log-file=foo -M--fake-super src/ dest/))
+
+If you want to have an option affect only the local side of a transfer when
+it normally affects both sides, send its negation to the remote side.  Like
+this:
+
+quote(tt(    rsync -av -x -M--no-x src/ dest/))
+
+Be cautious using this, as it is possible to toggle an option that will cause
+rsync to have a different idea about what data to expect next over the socket,
+and that will make it fail in a cryptic fashion.
+
+Note that it is best to use a separate bf(--remote-option) for each option you
+want to pass.  This makes your useage compatible with the bf(--protect-args)
+option.  If that option is off, any spaces in your remote options will be split
+by the remote shell unless you take steps to protect them.
+
+When performing a local transfer, the "local" side is the sender and the
+"remote" side is the receiver.
+
+Note some versions of the popt option-parsing library have a bug in them that
+prevents you from using an adjacent arg with an equal in it next to a short
+option letter (e.g. tt(-M--log-file=/tmp/foo).  If this bug affects your
+version of popt, you can use the version of popt that is included with rsync.
+
 dit(bf(-C, --cvs-exclude)) This is a useful shorthand for excluding a
 broad range of files that you often don't want to transfer between
 systems. It uses a similar algorithm to CVS to determine if
@@ -1759,7 +1790,7 @@ option if you wish to override this.
 Here's a example command that requests the remote side to log what is
 happening:
 
-verb(  rsync -av --rsync-path="rsync --log-file=/tmp/rlog" src/ dest/)
+verb(  rsync -av --remote-option=--log-file=/tmp/rlog src/ dest/)
 
 This is very useful if you need to debug why a connection is closing
 unexpectedly.