From: Wayne Davison Date: Sat, 5 Jul 2008 15:30:16 +0000 (-0700) Subject: Added the --remote-option=OPT (-M OPT) option. X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/commitdiff_plain/7a2eca415b0d7f40618dd67aa30bafef810b3724 Added the --remote-option=OPT (-M OPT) option. --- diff --git a/NEWS b/NEWS index 70af495f..5e92e72e 100644 --- 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: diff --git a/options.c b/options.c index 0ac5bfd9..a79c5537 100644 --- 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 5f79edef..f32d63e6 100644 --- 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 || diff --git a/rsync.yo b/rsync.yo index 2838e0de..33773129 100644 --- 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.