The patches for 3.0.1pre1.
[rsync/rsync-patches.git] / remote-option.diff
CommitLineData
c0c7984e
WD
1This patch implements a new --remote-option (-M) option that allows the
2user to override certain settings on the remote system. For instance, it
3is now easier to pass -M--fake-super or "-M --log-file=/tmp/foo" instead of
4kluging up an --rsync-path setting. This also solves the case where we
5want local --one-file-system (-x) but not remote ("-x -M--no-x"), or visa
6versa ("-M-x").
7
8To use this patch, run these commands for a successful build:
9
10 patch -p1 <patches/remote-option.diff
11 ./configure (optional if already run)
12 make
13
14diff --git a/options.c b/options.c
15--- a/options.c
16+++ b/options.c
17@@ -174,6 +174,10 @@ int link_dest = 0;
18 int basis_dir_cnt = 0;
19 char *dest_option = NULL;
20
21+#define MAX_REMOTE_ARGS (MAX_SERVER_ARGS/2)
22+int remote_option_cnt = 0;
23+const char *remote_options[MAX_SERVER_ARGS+1] = { "ARG0" };
24+
25 int verbose = 0;
26 int quiet = 0;
27 int output_motd = 1;
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,20 @@ int parse_arguments(int *argc_p, const char ***argv_p)
45 }
46 break;
47
48+ case 'M':
49+ arg = poptGetOptArg(pc);
50+ if (*arg != '-') {
51+ snprintf(err_buf, sizeof err_buf,
52+ "Remote option must start with a dash: %s\n", arg);
53+ return 0;
54+ }
55+ if (remote_option_cnt >= MAX_REMOTE_ARGS) {
56+ rprintf(FERROR, "too many remote options specified.\n");
57+ exit_cleanup(RERR_SYNTAX);
58+ }
59+ remote_options[++remote_option_cnt] = arg;
60+ break;
61+
62 case OPT_WRITE_BATCH:
63 /* batch_name is already set */
64 write_batch = 1;
65@@ -1826,6 +1846,11 @@ void server_options(char **args, int *argc_p)
66 #endif
67 argstr[x] = '\0';
68
69+ if (x > (int)sizeof argstr) { /* Not possible... */
70+ rprintf(FERROR, "argstr overflow in server_options().\n");
71+ exit_cleanup(RERR_MALLOC);
72+ }
73+
74 args[ac++] = argstr;
75
76 #ifdef ICONV_OPTION
77@@ -2048,6 +2073,21 @@ void server_options(char **args, int *argc_p)
78 else if (remove_source_files)
79 args[ac++] = "--remove-sent-files";
80
81+ if (ac > MAX_SERVER_ARGS) { /* Not possible... */
82+ rprintf(FERROR, "argc overflow in server_options().\n");
83+ exit_cleanup(RERR_MALLOC);
84+ }
85+
86+ if (remote_option_cnt) {
87+ int j;
88+ if (ac + remote_option_cnt > MAX_SERVER_ARGS) {
89+ rprintf(FERROR, "too many remote options specified.\n");
90+ exit_cleanup(RERR_SYNTAX);
91+ }
92+ for (j = 1; j <= remote_option_cnt; j++)
93+ args[ac++] = (char*)remote_options[j];
94+ }
95+
96 *argc_p = ac;
97 return;
98
99diff --git a/pipe.c b/pipe.c
100--- a/pipe.c
101+++ b/pipe.c
102@@ -22,12 +22,15 @@
103
104 #include "rsync.h"
105
106+extern int am_root;
107 extern int am_sender;
108 extern int am_server;
109 extern int blocking_io;
110 extern int filesfrom_fd;
111 extern mode_t orig_umask;
112 extern char *logfile_name;
113+extern int remote_option_cnt;
114+extern const char *remote_options[];
115 extern struct chmod_mode_struct *chmod_modes;
116
117 /**
118@@ -139,6 +142,18 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
119 logfile_close();
120 }
121
122+ if (am_root < 0)
123+ am_root = 0;
124+
125+ if (remote_option_cnt) {
126+ int rc = remote_option_cnt + 1;
127+ const char **rv = remote_options;
128+ if (!parse_arguments(&rc, &rv)) {
129+ option_error();
130+ exit_cleanup(RERR_SYNTAX);
131+ }
132+ }
133+
134 if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
135 close(to_child_pipe[1]) < 0 ||
136 close(from_child_pipe[0]) < 0 ||
137diff --git a/rsync.yo b/rsync.yo
138--- a/rsync.yo
139+++ b/rsync.yo
140@@ -412,6 +412,7 @@ to the detailed description below for a complete description. verb(
141 --progress show progress during transfer
142 -P same as --partial --progress
143 -i, --itemize-changes output a change-summary for all updates
144+ -M, --remote-option=OPTION send OPTION to the remote side only
145 --out-format=FORMAT output updates using the specified FORMAT
146 --log-file=FILE log what we're doing to the specified FILE
147 --log-file-format=FMT log updates using the specified FMT
148@@ -1020,16 +1021,13 @@ This is a good way to backup data without using a super-user, and to store
149 ACLs from incompatible systems.
150
151 The bf(--fake-super) option only affects the side where the option is used.
152-To affect the remote side of a remote-shell connection, specify an rsync
153-path:
154+To affect the remote side of a remote-shell connection, use the
155+bf(--remote-option) (bf(-M)) option:
156
157-quote(tt( rsync -av --rsync-path="rsync --fake-super" /src/ host:/dest/))
158+quote(tt( rsync -av -M--fake-super /src/ host:/dest/))
159
160-Since there is only one "side" in a local copy, this option affects both
161-the sending and receiving of files. You'll need to specify a copy using
162-"localhost" if you need to avoid this, possibly using the "lsh" shell
163-script (from the support directory) as a substitute for an actual remote
164-shell (see bf(--rsh)).
165+For a local copy, this option affects only the source. Specify a
166+bf(--remote-option) to affect the destination.
167
168 This option is overridden by both bf(--super) and bf(--no-super).
169
170@@ -1275,6 +1273,36 @@ machine for use with the bf(--relative) option. For instance:
171
172 quote(tt( rsync -avR --rsync-path="cd /a/b && rsync" host:c/d /e/))
173
174+dit(bf(-M, --remote-option=OPTION)) This option is used for more advanced
175+situations where you want certain effects to be limited to one side of the
176+transfer only. For instance, if you want to pass bf(--log-file=FILE) and
177+bf(--fake-super) to the remote system, specify it like this:
178+
179+quote(tt( rsync -av -M --log-file=foo -M--fake-super src/ dest/))
180+
181+If you want to have an option affect only the local side of a transfer when
182+it normally affects both sides, send its negation to the remote side. Like
183+this:
184+
185+quote(tt( rsync -av -x -M--no-x src/ dest/))
186+
187+Be cautious using this, as it is possible to toggle an option that will cause
188+rsync to have a different idea about what data to expect next over the socket,
189+and that will make it fail in a cryptic fashion.
190+
191+Note that it is best to use a separate bf(--remote-option) for each option you
192+want to pass. This makes your useage compatible with the bf(--preserve-spaces)
193+option. If that option is off, any spaces in your remote options will be split
194+by the remote shell unless you take steps to protect them.
195+
196+When performing a local transfer, the "local" side is the sender and the
197+"remote" side is the receiver.
198+
199+Note some versions of the popt option-parsing library have a bug in them that
200+prevents you from using an adjacent arg with an equal in it next to a short
201+option letter (e.g. tt(-M--log-file=/tmp/foo). If this bug affects your
202+version of popt, you can use the version of popt that is included with rsync.
203+
204 dit(bf(-C, --cvs-exclude)) This is a useful shorthand for excluding a
205 broad range of files that you often don't want to transfer between
206 systems. It uses a similar algorithm to CVS to determine if
207@@ -1746,7 +1774,7 @@ option if you wish to override this.
208 Here's a example command that requests the remote side to log what is
209 happening:
210
211-verb( rsync -av --rsync-path="rsync --log-file=/tmp/rlog" src/ dest/)
212+verb( rsync -av --remote-option=--log-file=/tmp/rlog src/ dest/)
213
214 This is very useful if you need to debug why a connection is closing
215 unexpectedly.
216diff --git a/testsuite/chown.test b/testsuite/chown.test
217--- a/testsuite/chown.test
218+++ b/testsuite/chown.test
219@@ -16,7 +16,7 @@
220 case $0 in
221 *fake*)
222 $RSYNC --version | grep ", xattrs" >/dev/null || test_skipped "Rsync needs xattrs for fake device tests"
223- RSYNC="$RSYNC --fake-super"
224+ RSYNC="$RSYNC --fake-super -M--fake-super"
225 TLS_ARGS=--fake-super
226 case "`xattr 2>&1`" in
227 *--list:*)
228diff --git a/testsuite/devices.test b/testsuite/devices.test
229--- a/testsuite/devices.test
230+++ b/testsuite/devices.test
231@@ -17,7 +17,7 @@ outfile="$scratchdir/rsync.out"
232 case $0 in
233 *fake*)
234 $RSYNC --version | grep ", xattrs" >/dev/null || test_skipped "Rsync needs xattrs for fake device tests"
235- RSYNC="$RSYNC --fake-super"
236+ RSYNC="$RSYNC --fake-super -M--fake-super"
237 TLS_ARGS=--fake-super
238 case "`xattr 2>&1`" in
239 *--list:*)