1 This patch implements a new --remote-option (-M) option that allows the
2 user to override certain settings on the remote system. For instance, it
3 is now easier to pass -M--fake-super or "-M --log-file=/tmp/foo" instead of
4 kluging up an --rsync-path setting. This also solves the case where we
5 want local --one-file-system (-x) but not remote ("-x -M--no-x"), or visa
8 To use this patch, run these commands for a successful build:
10 patch -p1 <patches/remote-option.diff
11 ./configure (optional if already run)
14 diff --git a/options.c b/options.c
17 @@ -174,6 +174,10 @@ int link_dest = 0;
18 int basis_dir_cnt = 0;
19 char *dest_option = NULL;
21 +static int remote_option_alloc = 0;
22 +int remote_option_cnt = 0;
23 +const char **remote_options = NULL;
28 @@ -387,6 +391,7 @@ void usage(enum logcode F)
29 rprintf(F," --timeout=SECONDS set I/O timeout in seconds\n");
30 rprintf(F," --contimeout=SECONDS set daemon connection timeout in seconds\n");
31 rprintf(F," -I, --ignore-times don't skip files that match in size and mod-time\n");
32 + rprintf(F," -M, --remote-option=OPTION send OPTION to the remote side only\n");
33 rprintf(F," --size-only skip files that match in size\n");
34 rprintf(F," --modify-window=NUM compare mod-times with reduced accuracy\n");
35 rprintf(F," -T, --temp-dir=DIR create temporary files in directory DIR\n");
36 @@ -645,6 +650,7 @@ static struct poptOption long_options[] = {
37 {"password-file", 0, POPT_ARG_STRING, &password_file, 0, 0, 0 },
38 {"blocking-io", 0, POPT_ARG_VAL, &blocking_io, 1, 0, 0 },
39 {"no-blocking-io", 0, POPT_ARG_VAL, &blocking_io, 0, 0, 0 },
40 + {"remote-option", 'M', POPT_ARG_STRING, 0, 'M', 0, 0 },
41 {"protocol", 0, POPT_ARG_INT, &protocol_version, 0, 0, 0 },
42 {"checksum-seed", 0, POPT_ARG_INT, &checksum_seed, 0, 0, 0 },
43 {"server", 0, POPT_ARG_NONE, 0, OPT_SERVER, 0, 0 },
44 @@ -1140,6 +1146,26 @@ int parse_arguments(int *argc_p, const char ***argv_p)
49 + arg = poptGetOptArg(pc);
51 + snprintf(err_buf, sizeof err_buf,
52 + "Remote option must start with a dash: %s\n", arg);
55 + if (remote_option_cnt+3 > remote_option_alloc) {
56 + remote_option_alloc += 16;
57 + remote_options = realloc_array(remote_options,
58 + const char *, remote_option_alloc);
59 + if (!remote_options)
60 + out_of_memory("parse_arguments");
61 + if (!remote_option_cnt)
62 + remote_options[0] = "ARG0";
64 + remote_options[++remote_option_cnt] = arg;
65 + remote_options[remote_option_cnt+1] = NULL;
69 /* batch_name is already set */
71 @@ -1826,6 +1852,11 @@ void server_options(char **args, int *argc_p)
75 + if (x > (int)sizeof argstr) { /* Not possible... */
76 + rprintf(FERROR, "argstr overflow in server_options().\n");
77 + exit_cleanup(RERR_MALLOC);
83 @@ -2048,6 +2079,21 @@ void server_options(char **args, int *argc_p)
84 else if (remove_source_files)
85 args[ac++] = "--remove-sent-files";
87 + if (ac > MAX_SERVER_ARGS) { /* Not possible... */
88 + rprintf(FERROR, "argc overflow in server_options().\n");
89 + exit_cleanup(RERR_MALLOC);
92 + if (remote_option_cnt) {
94 + if (ac + remote_option_cnt > MAX_SERVER_ARGS) {
95 + rprintf(FERROR, "too many remote options specified.\n");
96 + exit_cleanup(RERR_SYNTAX);
98 + for (j = 1; j <= remote_option_cnt; j++)
99 + args[ac++] = (char*)remote_options[j];
105 diff --git a/pipe.c b/pipe.c
108 @@ -28,6 +28,8 @@ extern int blocking_io;
109 extern int filesfrom_fd;
110 extern mode_t orig_umask;
111 extern char *logfile_name;
112 +extern int remote_option_cnt;
113 +extern const char **remote_options;
114 extern struct chmod_mode_struct *chmod_modes;
117 @@ -139,6 +141,15 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
121 + if (remote_option_cnt) {
122 + int rc = remote_option_cnt + 1;
123 + const char **rv = remote_options;
124 + if (!parse_arguments(&rc, &rv)) {
126 + exit_cleanup(RERR_SYNTAX);
130 if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
131 close(to_child_pipe[1]) < 0 ||
132 close(from_child_pipe[0]) < 0 ||
133 diff --git a/rsync.yo b/rsync.yo
136 @@ -412,6 +412,7 @@ to the detailed description below for a complete description. verb(
137 --progress show progress during transfer
138 -P same as --partial --progress
139 -i, --itemize-changes output a change-summary for all updates
140 + -M, --remote-option=OPTION send OPTION to the remote side only
141 --out-format=FORMAT output updates using the specified FORMAT
142 --log-file=FILE log what we're doing to the specified FILE
143 --log-file-format=FMT log updates using the specified FMT
144 @@ -1020,16 +1021,16 @@ This is a good way to backup data without using a super-user, and to store
145 ACLs from incompatible systems.
147 The bf(--fake-super) option only affects the side where the option is used.
148 -To affect the remote side of a remote-shell connection, specify an rsync
150 +To affect the remote side of a remote-shell connection, use the
151 +bf(--remote-option) (bf(-M)) option:
153 -quote(tt( rsync -av --rsync-path="rsync --fake-super" /src/ host:/dest/))
154 +quote(tt( rsync -av -M--fake-super /src/ host:/dest/))
156 -Since there is only one "side" in a local copy, this option affects both
157 -the sending and receiving of files. You'll need to specify a copy using
158 -"localhost" if you need to avoid this, possibly using the "lsh" shell
159 -script (from the support directory) as a substitute for an actual remote
160 -shell (see bf(--rsh)).
161 +For a local copy, this option affects both the source and the destination.
162 +If you wish a local copy to enable this option just for the destination
163 +files, specify bf(-M--fake-super). If you wish a local copy to enable
164 +this option just for the source files, combine bf(--fake-super) with
167 This option is overridden by both bf(--super) and bf(--no-super).
169 @@ -1275,6 +1276,36 @@ machine for use with the bf(--relative) option. For instance:
171 quote(tt( rsync -avR --rsync-path="cd /a/b && rsync" host:c/d /e/))
173 +dit(bf(-M, --remote-option=OPTION)) This option is used for more advanced
174 +situations where you want certain effects to be limited to one side of the
175 +transfer only. For instance, if you want to pass bf(--log-file=FILE) and
176 +bf(--fake-super) to the remote system, specify it like this:
178 +quote(tt( rsync -av -M --log-file=foo -M--fake-super src/ dest/))
180 +If you want to have an option affect only the local side of a transfer when
181 +it normally affects both sides, send its negation to the remote side. Like
184 +quote(tt( rsync -av -x -M--no-x src/ dest/))
186 +Be cautious using this, as it is possible to toggle an option that will cause
187 +rsync to have a different idea about what data to expect next over the socket,
188 +and that will make it fail in a cryptic fashion.
190 +Note that it is best to use a separate bf(--remote-option) for each option you
191 +want to pass. This makes your useage compatible with the bf(--protect-args)
192 +option. If that option is off, any spaces in your remote options will be split
193 +by the remote shell unless you take steps to protect them.
195 +When performing a local transfer, the "local" side is the sender and the
196 +"remote" side is the receiver.
198 +Note some versions of the popt option-parsing library have a bug in them that
199 +prevents you from using an adjacent arg with an equal in it next to a short
200 +option letter (e.g. tt(-M--log-file=/tmp/foo). If this bug affects your
201 +version of popt, you can use the version of popt that is included with rsync.
203 dit(bf(-C, --cvs-exclude)) This is a useful shorthand for excluding a
204 broad range of files that you often don't want to transfer between
205 systems. It uses a similar algorithm to CVS to determine if
206 @@ -1746,7 +1777,7 @@ option if you wish to override this.
207 Here's a example command that requests the remote side to log what is
210 -verb( rsync -av --rsync-path="rsync --log-file=/tmp/rlog" src/ dest/)
211 +verb( rsync -av --remote-option=--log-file=/tmp/rlog src/ dest/)
213 This is very useful if you need to debug why a connection is closing