Added the --remote-option=OPT (-M OPT) option.

This commit is contained in:
Wayne Davison
2008-07-05 08:30:16 -07:00
parent 854411909b
commit 7a2eca415b
4 changed files with 99 additions and 10 deletions

3
NEWS
View File

@@ -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:

View File

@@ -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;

11
pipe.c
View File

@@ -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 ||

View File

@@ -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.