Improved the test a little.
[rsync/rsync.git] / options.c
CommitLineData
7a24c346 1/* -*- c-file-style: "linux" -*-
dfa32483 2 *
dafe63ca
MP
3 * Copyright (C) 1998-2001 by Andrew Tridgell <tridge@samba.org>
4 * Copyright (C) 2000, 2001, 2002 by Martin Pool <mbp@samba.org>
dfa32483 5 *
dafe63ca
MP
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
dfa32483 10 *
dafe63ca
MP
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
dfa32483 15 *
dafe63ca
MP
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
7a6421fa 20
7a6421fa 21#include "rsync.h"
2855f61f 22#include "popt.h"
7a6421fa 23
7be73df4 24extern int sanitize_paths;
99218d82 25extern int select_timeout;
7be73df4 26extern char curr_dir[MAXPATHLEN];
bf6dcd17 27extern struct exclude_list_struct exclude_list;
8645af1d 28
7a6421fa 29int make_backups = 0;
1bfbf40b
MP
30
31/**
dfa32483 32 * If 1, send the whole file as literal data rather than trying to
dafe63ca 33 * create an incremental diff.
1bfbf40b 34 *
dfa32483 35 * If -1, then look at whether we're local or remote and go by that.
dafe63ca
MP
36 *
37 * @sa disable_deltas_p()
1bfbf40b 38 **/
dfa32483 39int whole_file = -1;
1bfbf40b 40
dfa32483 41int archive_mode = 0;
716e73d4 42int keep_dirlinks = 0;
7a6421fa
AT
43int copy_links = 0;
44int preserve_links = 0;
45int preserve_hard_links = 0;
46int preserve_perms = 0;
47int preserve_devices = 0;
48int preserve_uid = 0;
49int preserve_gid = 0;
50int preserve_times = 0;
51int update_only = 0;
52int cvs_exclude = 0;
a5c11139
WD
53int dry_run = 0;
54int local_server = 0;
55int ignore_times = 0;
56int delete_mode = 0;
57int delete_excluded = 0;
58int one_file_system = 0;
4f3e9a0f 59int protocol_version = PROTOCOL_VERSION;
a5c11139
WD
60int sparse_files = 0;
61int do_compression = 0;
62int am_root = 0;
63int orig_umask = 0;
ea5164d1
WD
64int relative_paths = -1;
65int implied_dirs = 1;
7a6421fa
AT
66int numeric_ids = 0;
67int force_delete = 0;
68int io_timeout = 0;
7a6421fa
AT
69int read_only = 0;
70int module_id = -1;
71int am_server = 0;
30ce7e8a 72int am_sender = 0;
4337c8f8 73int am_generator = 0;
ea5164d1
WD
74char *files_from = NULL;
75int filesfrom_fd = -1;
76char *remote_filesfrom_file = NULL;
77int eol_nulls = 0;
7a6421fa 78int recurse = 0;
1312d9fc
WD
79int am_daemon = 0;
80int daemon_over_rsh = 0;
a5c11139
WD
81int do_stats = 0;
82int do_progress = 0;
83int keep_partial = 0;
84int safe_symlinks = 0;
85int copy_unsafe_links = 0;
86int size_only = 0;
87int bwlimit = 0;
3c74c3a3 88size_t bwlimit_writemax = 0;
a5c11139
WD
89int delete_after = 0;
90int only_existing = 0;
91int opt_ignore_existing = 0;
92int max_delete = 0;
93int ignore_errors = 0;
94int modify_window = 0;
95int blocking_io = -1;
2289bf64 96int checksum_seed = 0;
a3221d2a 97int inplace = 0;
da9d12f5 98unsigned int block_size = 0;
7a6421fa 99
b35d0d8e 100
13e29995 101/** Network address family. **/
6ab6d4bf 102#ifdef INET6
13e29995 103int default_af_hint = 0; /* Any protocol */
6ab6d4bf 104#else
13e29995 105int default_af_hint = AF_INET; /* Must use IPv4 */
6ab6d4bf 106#endif
06963d0f 107
13e29995
MP
108/** Do not go into the background when run as --daemon. Good
109 * for debugging and required for running as a service on W32,
110 * or under Unix process-monitors. **/
111int no_detach = 0;
112
088aac85
DD
113int write_batch = 0;
114int read_batch = 0;
d175d7e1
WD
115int backup_dir_len = 0;
116int backup_suffix_len;
e0391f81 117unsigned int backup_dir_remainder;
6902ed17 118
d175d7e1 119char *backup_suffix = NULL;
7a6421fa 120char *tmpdir = NULL;
375a4556 121char *compare_dest = NULL;
30e8c8e1 122char *config_file = NULL;
7a6421fa 123char *shell_cmd = NULL;
b6062654 124char *log_format = NULL;
65575e96 125char *password_file = NULL;
41bd28fe 126char *rsync_path = RSYNC_PATH;
66203a98 127char *backup_dir = NULL;
e0391f81 128char backup_dir_buf[MAXPATHLEN];
7a6421fa 129int rsync_port = RSYNC_PORT;
59c95e42 130int link_dest = 0;
7a6421fa
AT
131
132int verbose = 0;
b86f0cef 133int quiet = 0;
7a6421fa 134int always_checksum = 0;
f7632fc6 135int list_only = 0;
7a6421fa 136
9b3318b0
WD
137#define MAX_BATCH_NAME_LEN 256 /* Must be less than MAXPATHLEN-13 */
138char *batch_name = NULL;
6902ed17 139
e1add893 140static int daemon_opt; /* sets am_daemon after option error-reporting */
5b56cc19
AT
141static int modify_window_set;
142
06963d0f 143/** Local address to bind. As a character string because it's
fdf57ede 144 * interpreted by the IPv6 layer: should be a numeric IP4 or IP6
06963d0f
MP
145 * address, or a hostname. **/
146char *bind_address;
5c9730a4 147
7a24c346 148
27a12348 149static void print_rsync_version(enum logcode f)
7a24c346 150{
dfa32483 151 char const *got_socketpair = "no ";
a3221d2a 152 char const *have_inplace = "no ";
dfa32483
WD
153 char const *hardlinks = "no ";
154 char const *links = "no ";
a358449a 155 char const *ipv6 = "no ";
736a6a29 156 STRUCT_STAT *dumstat;
0c80cd8e
MP
157
158#ifdef HAVE_SOCKETPAIR
dfa32483 159 got_socketpair = "";
0c80cd8e 160#endif
2855f61f 161
a3221d2a
WD
162#if HAVE_FTRUNCATE
163 have_inplace = "";
164#endif
165
2855f61f 166#if SUPPORT_HARD_LINKS
dfa32483 167 hardlinks = "";
2855f61f
MP
168#endif
169
170#if SUPPORT_LINKS
dfa32483 171 links = "";
2855f61f
MP
172#endif
173
a358449a
MP
174#if INET6
175 ipv6 = "";
dfa32483 176#endif
a358449a 177
dfa32483
WD
178 rprintf(f, "%s version %s protocol version %d\n",
179 RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION);
180 rprintf(f,
45ddbf62 181 "Copyright (C) 1996-2004 by Andrew Tridgell and others\n");
3b4b1984 182 rprintf(f, "<http://rsync.samba.org/>\n");
dfa32483
WD
183 rprintf(f, "Capabilities: %d-bit files, %ssocketpairs, "
184 "%shard links, %ssymlinks, batchfiles, \n",
a5c11139 185 (int) (sizeof (OFF_T) * 8),
dfa32483 186 got_socketpair, hardlinks, links);
2855f61f 187
736a6a29
MP
188 /* Note that this field may not have type ino_t. It depends
189 * on the complicated interaction between largefile feature
190 * macros. */
a3221d2a
WD
191 rprintf(f, " %sinplace, %sIPv6, %d-bit system inums, %d-bit internal inums\n",
192 have_inplace, ipv6,
a5c11139 193 (int) (sizeof dumstat->st_ino * 8),
5f381268 194 (int) (sizeof (uint64) * 8));
fc0302cf
MP
195#ifdef MAINTAINER_MODE
196 rprintf(f, " panic action: \"%s\"\n",
197 get_panic_action());
198#endif
736a6a29 199
7a24c346 200#ifdef NO_INT64
dfa32483 201 rprintf(f, "WARNING: no 64-bit integers on this platform!\n");
7a24c346 202#endif
7b329a2d
MP
203
204 rprintf(f,
205"\n"
206"rsync comes with ABSOLUTELY NO WARRANTY. This is free software, and you\n"
207"are welcome to redistribute it under certain conditions. See the GNU\n"
208"General Public Licence for details.\n"
209 );
7a24c346
MP
210}
211
212
0f3203c3 213void usage(enum logcode F)
7a6421fa 214{
2855f61f 215 print_rsync_version(F);
704f908e 216
3ff984d7 217 rprintf(F,"\nrsync is a file transfer program capable of efficient remote update\nvia a fast differencing algorithm.\n\n");
704f908e 218
9ef53907 219 rprintf(F,"Usage: rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST\n");
704f908e 220 rprintf(F," or rsync [OPTION]... [USER@]HOST:SRC DEST\n");
9ef53907 221 rprintf(F," or rsync [OPTION]... SRC [SRC]... DEST\n");
14d43f1f 222 rprintf(F," or rsync [OPTION]... [USER@]HOST::SRC [DEST]\n");
9ef53907 223 rprintf(F," or rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST\n");
14d43f1f 224 rprintf(F," or rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST]\n");
eaa4c150 225 rprintf(F," or rsync [OPTION]... SRC [SRC]... rsync://[USER@]HOST[:PORT]/DEST\n");
9ef53907
DD
226 rprintf(F,"SRC on single-colon remote HOST will be expanded by remote shell\n");
227 rprintf(F,"SRC on server remote HOST may contain shell wildcards or multiple\n");
228 rprintf(F," sources separated by space as long as they have same top-level\n");
704f908e
AT
229 rprintf(F,"\nOptions\n");
230 rprintf(F," -v, --verbose increase verbosity\n");
b86f0cef 231 rprintf(F," -q, --quiet decrease verbosity\n");
704f908e 232 rprintf(F," -c, --checksum always checksum\n");
06891710 233 rprintf(F," -a, --archive archive mode, equivalent to -rlptgoD\n");
704f908e
AT
234 rprintf(F," -r, --recursive recurse into directories\n");
235 rprintf(F," -R, --relative use relative path names\n");
ea5164d1
WD
236 rprintf(F," --no-relative turn off --relative\n");
237 rprintf(F," --no-implied-dirs don't send implied dirs with -R\n");
6839140e 238 rprintf(F," -b, --backup make backups (see --suffix & --backup-dir)\n");
e20c5e95 239 rprintf(F," --backup-dir make backups into this directory\n");
6839140e 240 rprintf(F," --suffix=SUFFIX backup suffix (default %s w/o --backup-dir)\n",BACKUP_SUFFIX);
704f908e 241 rprintf(F," -u, --update update only (don't overwrite newer files)\n");
a3221d2a 242 rprintf(F," --inplace update the destination file inplace (see man page)\n");
716e73d4 243 rprintf(F," -K, --keep-dirlinks treat symlinked dir on receiver as dir\n");
13e29995 244 rprintf(F," -l, --links copy symlinks as symlinks\n");
06d76beb
WD
245 rprintf(F," -L, --copy-links copy the referent of all symlinks\n");
246 rprintf(F," --copy-unsafe-links copy the referent of \"unsafe\" symlinks\n");
247 rprintf(F," --safe-links ignore \"unsafe\" symlinks\n");
704f908e
AT
248 rprintf(F," -H, --hard-links preserve hard links\n");
249 rprintf(F," -p, --perms preserve permissions\n");
250 rprintf(F," -o, --owner preserve owner (root only)\n");
251 rprintf(F," -g, --group preserve group\n");
252 rprintf(F," -D, --devices preserve devices (root only)\n");
dfa32483 253 rprintf(F," -t, --times preserve times\n");
704f908e
AT
254 rprintf(F," -S, --sparse handle sparse files efficiently\n");
255 rprintf(F," -n, --dry-run show what would have been transferred\n");
256 rprintf(F," -W, --whole-file copy whole files, no incremental checks\n");
93689aa5 257 rprintf(F," --no-whole-file turn off --whole-file\n");
704f908e 258 rprintf(F," -x, --one-file-system don't cross filesystem boundaries\n");
dfa32483 259 rprintf(F," -B, --block-size=SIZE checksum blocking size (default %d)\n",BLOCK_SIZE);
54170a08 260 rprintf(F," -e, --rsh=COMMAND specify the remote shell\n");
704f908e 261 rprintf(F," --rsync-path=PATH specify path to rsync on the remote machine\n");
1347d512 262 rprintf(F," --existing only update files that already exist\n");
6839140e 263 rprintf(F," --ignore-existing ignore files that already exist on receiving side\n");
704f908e 264 rprintf(F," --delete delete files that don't exist on the sending side\n");
b33b791e 265 rprintf(F," --delete-excluded also delete excluded files on the receiving side\n");
ad1a09a5 266 rprintf(F," --delete-after receiver deletes after transferring, not before\n");
db2b5cb7 267 rprintf(F," --ignore-errors delete even if there are I/O errors\n");
0b73ca12 268 rprintf(F," --max-delete=NUM don't delete more than NUM files\n");
c95da96a 269 rprintf(F," --partial keep partially transferred files\n");
704f908e
AT
270 rprintf(F," --force force deletion of directories even if not empty\n");
271 rprintf(F," --numeric-ids don't map uid/gid values by user/group name\n");
db2b5cb7 272 rprintf(F," --timeout=TIME set I/O timeout in seconds\n");
6839140e
WD
273 rprintf(F," -I, --ignore-times turn off mod time & file size quick check\n");
274 rprintf(F," --size-only ignore mod time for quick check (use size)\n");
275 rprintf(F," --modify-window=NUM compare mod times with reduced accuracy\n");
704f908e 276 rprintf(F," -T --temp-dir=DIR create temporary files in directory DIR\n");
375a4556 277 rprintf(F," --compare-dest=DIR also compare destination files relative to DIR\n");
8294b00c 278 rprintf(F," --link-dest=DIR create hardlinks to DIR for unchanged files\n");
d9fcc198 279 rprintf(F," -P equivalent to --partial --progress\n");
704f908e 280 rprintf(F," -z, --compress compress file data\n");
ea5164d1 281 rprintf(F," -C, --cvs-exclude auto ignore files in the same way CVS does\n");
2acf81eb 282 rprintf(F," --exclude=PATTERN exclude files matching PATTERN\n");
858fb9eb 283 rprintf(F," --exclude-from=FILE exclude patterns listed in FILE\n");
2acf81eb 284 rprintf(F," --include=PATTERN don't exclude files matching PATTERN\n");
858fb9eb 285 rprintf(F," --include-from=FILE don't exclude patterns listed in FILE\n");
ea5164d1 286 rprintf(F," --files-from=FILE read FILE for list of source-file names\n");
6839140e 287 rprintf(F," -0 --from0 all *-from file lists are delimited by nulls\n");
dfa32483 288 rprintf(F," --version print version number\n");
db2b5cb7 289 rprintf(F," --daemon run as an rsync daemon\n");
dfa32483
WD
290 rprintf(F," --no-detach do not detach from the parent\n");
291 rprintf(F," --address=ADDRESS bind to the specified address\n");
292 rprintf(F," --config=FILE specify alternate rsyncd.conf file\n");
704f908e 293 rprintf(F," --port=PORT specify alternate rsyncd port number\n");
db2b5cb7 294 rprintf(F," --blocking-io use blocking I/O for the remote shell\n");
dfa32483
WD
295 rprintf(F," --no-blocking-io turn off --blocking-io\n");
296 rprintf(F," --stats give some file transfer stats\n");
297 rprintf(F," --progress show progress during transfer\n");
298 rprintf(F," --log-format=FORMAT log file transfers using specified format\n");
65575e96 299 rprintf(F," --password-file=FILE get password from FILE\n");
ef5d23eb 300 rprintf(F," --bwlimit=KBPS limit I/O bandwidth, KBytes per second\n");
9b3318b0
WD
301 rprintf(F," --write-batch=FILE write a batch to FILE\n");
302 rprintf(F," --read-batch=FILE read a batch from FILE\n");
c8d895de 303 rprintf(F," --checksum-seed=NUM set block/file checksum seed\n");
06963d0f 304#ifdef INET6
3dd22903
WD
305 rprintf(F," -4 --ipv4 prefer IPv4\n");
306 rprintf(F," -6 --ipv6 prefer IPv6\n");
06963d0f 307#endif
3dd22903 308 rprintf(F," -h, --help show this help screen\n");
7a6421fa
AT
309
310 rprintf(F,"\n");
b72f24c7
AT
311
312 rprintf(F,"\nPlease see the rsync(1) and rsyncd.conf(5) man pages for full documentation\n");
2855f61f 313 rprintf(F,"See http://rsync.samba.org/ for updates, bug reports, and answers\n");
7a6421fa
AT
314}
315
1f3d6cdd
WD
316enum {OPT_VERSION = 1000, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
317 OPT_DELETE_AFTER, OPT_DELETE_EXCLUDED, OPT_LINK_DEST,
318 OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW,
99218d82 319 OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_TIMEOUT,
c67d1386 320 OPT_REFUSED_BASE = 9000};
7a6421fa 321
2855f61f
MP
322static struct poptOption long_options[] = {
323 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
dfa32483 324 {"version", 0, POPT_ARG_NONE, 0, OPT_VERSION, 0, 0},
d175d7e1 325 {"suffix", 0, POPT_ARG_STRING, &backup_suffix, 0, 0, 0 },
3dd22903
WD
326 {"rsync-path", 0, POPT_ARG_STRING, &rsync_path, 0, 0, 0 },
327 {"password-file", 0, POPT_ARG_STRING, &password_file, 0, 0, 0 },
afb6e945
WD
328 {"ignore-times", 'I', POPT_ARG_NONE, &ignore_times, 0, 0, 0 },
329 {"size-only", 0, POPT_ARG_NONE, &size_only, 0, 0, 0 },
8b54f004 330 {"modify-window", 0, POPT_ARG_INT, &modify_window, OPT_MODIFY_WINDOW, 0, 0 },
afb6e945
WD
331 {"one-file-system", 'x', POPT_ARG_NONE, &one_file_system, 0, 0, 0 },
332 {"delete", 0, POPT_ARG_NONE, &delete_mode, 0, 0, 0 },
333 {"existing", 0, POPT_ARG_NONE, &only_existing, 0, 0, 0 },
334 {"ignore-existing", 0, POPT_ARG_NONE, &opt_ignore_existing, 0, 0, 0 },
1de50993 335 {"delete-after", 0, POPT_ARG_NONE, 0, OPT_DELETE_AFTER, 0, 0 },
8b54f004 336 {"delete-excluded", 0, POPT_ARG_NONE, 0, OPT_DELETE_EXCLUDED, 0, 0 },
afb6e945
WD
337 {"force", 0, POPT_ARG_NONE, &force_delete, 0, 0, 0 },
338 {"numeric-ids", 0, POPT_ARG_NONE, &numeric_ids, 0, 0, 0 },
8b54f004
MP
339 {"exclude", 0, POPT_ARG_STRING, 0, OPT_EXCLUDE, 0, 0 },
340 {"include", 0, POPT_ARG_STRING, 0, OPT_INCLUDE, 0, 0 },
341 {"exclude-from", 0, POPT_ARG_STRING, 0, OPT_EXCLUDE_FROM, 0, 0 },
342 {"include-from", 0, POPT_ARG_STRING, 0, OPT_INCLUDE_FROM, 0, 0 },
afb6e945 343 {"safe-links", 0, POPT_ARG_NONE, &safe_symlinks, 0, 0, 0 },
8b54f004 344 {"help", 'h', POPT_ARG_NONE, 0, 'h', 0, 0 },
afb6e945
WD
345 {"backup", 'b', POPT_ARG_NONE, &make_backups, 0, 0, 0 },
346 {"dry-run", 'n', POPT_ARG_NONE, &dry_run, 0, 0, 0 },
347 {"sparse", 'S', POPT_ARG_NONE, &sparse_files, 0, 0, 0 },
348 {"cvs-exclude", 'C', POPT_ARG_NONE, &cvs_exclude, 0, 0, 0 },
349 {"update", 'u', POPT_ARG_NONE, &update_only, 0, 0, 0 },
a3221d2a 350 {"inplace", 0, POPT_ARG_NONE, &inplace, 0, 0, 0 },
716e73d4 351 {"keep-dirlinks", 'K', POPT_ARG_NONE, &keep_dirlinks, 0, 0, 0 },
afb6e945
WD
352 {"links", 'l', POPT_ARG_NONE, &preserve_links, 0, 0, 0 },
353 {"copy-links", 'L', POPT_ARG_NONE, &copy_links, 0, 0, 0 },
354 {"whole-file", 'W', POPT_ARG_VAL, &whole_file, 1, 0, 0 },
355 {"no-whole-file", 0, POPT_ARG_VAL, &whole_file, 0, 0, 0 },
356 {"copy-unsafe-links", 0, POPT_ARG_NONE, &copy_unsafe_links, 0, 0, 0 },
357 {"perms", 'p', POPT_ARG_NONE, &preserve_perms, 0, 0, 0 },
358 {"owner", 'o', POPT_ARG_NONE, &preserve_uid, 0, 0, 0 },
359 {"group", 'g', POPT_ARG_NONE, &preserve_gid, 0, 0, 0 },
360 {"devices", 'D', POPT_ARG_NONE, &preserve_devices, 0, 0, 0 },
361 {"times", 't', POPT_ARG_NONE, &preserve_times, 0, 0, 0 },
362 {"checksum", 'c', POPT_ARG_NONE, &always_checksum, 0, 0, 0 },
8b54f004
MP
363 {"verbose", 'v', POPT_ARG_NONE, 0, 'v', 0, 0 },
364 {"quiet", 'q', POPT_ARG_NONE, 0, 'q', 0, 0 },
dfa32483 365 {"archive", 'a', POPT_ARG_NONE, &archive_mode, 0, 0, 0 },
afb6e945 366 {"server", 0, POPT_ARG_NONE, &am_server, 0, 0, 0 },
dfa32483 367 {"sender", 0, POPT_ARG_NONE, 0, OPT_SENDER, 0, 0 },
afb6e945 368 {"recursive", 'r', POPT_ARG_NONE, &recurse, 0, 0, 0 },
ea5164d1
WD
369 {"relative", 'R', POPT_ARG_VAL, &relative_paths, 1, 0, 0 },
370 {"no-relative", 0, POPT_ARG_VAL, &relative_paths, 0, 0, 0 },
afb6e945
WD
371 {"rsh", 'e', POPT_ARG_STRING, &shell_cmd, 0, 0, 0 },
372 {"block-size", 'B', POPT_ARG_INT, &block_size, 0, 0, 0 },
373 {"max-delete", 0, POPT_ARG_INT, &max_delete, 0, 0, 0 },
99218d82 374 {"timeout", 0, POPT_ARG_INT, &io_timeout, OPT_TIMEOUT, 0, 0 },
afb6e945
WD
375 {"temp-dir", 'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
376 {"compare-dest", 0, POPT_ARG_STRING, &compare_dest, 0, 0, 0 },
7be73df4 377 {"link-dest", 0, POPT_ARG_STRING, &compare_dest, OPT_LINK_DEST, 0, 0 },
2855f61f 378 /* TODO: Should this take an optional int giving the compression level? */
afb6e945 379 {"compress", 'z', POPT_ARG_NONE, &do_compression, 0, 0, 0 },
e1add893 380 {"daemon", 0, POPT_ARG_NONE, &daemon_opt, 0, 0, 0 },
afb6e945
WD
381 {"no-detach", 0, POPT_ARG_NONE, &no_detach, 0, 0, 0 },
382 {"stats", 0, POPT_ARG_NONE, &do_stats, 0, 0, 0 },
383 {"progress", 0, POPT_ARG_NONE, &do_progress, 0, 0, 0 },
384 {"partial", 0, POPT_ARG_NONE, &keep_partial, 0, 0, 0 },
385 {"ignore-errors", 0, POPT_ARG_NONE, &ignore_errors, 0, 0, 0 },
386 {"blocking-io", 0, POPT_ARG_VAL, &blocking_io, 1, 0, 0 },
387 {"no-blocking-io", 0, POPT_ARG_VAL, &blocking_io, 0, 0, 0 },
dfa32483 388 {0, 'P', POPT_ARG_NONE, 0, 'P', 0, 0 },
afb6e945
WD
389 {"config", 0, POPT_ARG_STRING, &config_file, 0, 0, 0 },
390 {"port", 0, POPT_ARG_INT, &rsync_port, 0, 0, 0 },
391 {"log-format", 0, POPT_ARG_STRING, &log_format, 0, 0, 0 },
392 {"bwlimit", 0, POPT_ARG_INT, &bwlimit, 0, 0, 0 },
8b54f004 393 {"address", 0, POPT_ARG_STRING, &bind_address, 0, 0, 0 },
afb6e945
WD
394 {"backup-dir", 0, POPT_ARG_STRING, &backup_dir, 0, 0, 0 },
395 {"hard-links", 'H', POPT_ARG_NONE, &preserve_hard_links, 0, 0, 0 },
9b3318b0
WD
396 {"read-batch", 0, POPT_ARG_STRING, &batch_name, OPT_READ_BATCH, 0, 0 },
397 {"write-batch", 0, POPT_ARG_STRING, &batch_name, OPT_WRITE_BATCH, 0, 0 },
ea5164d1
WD
398 {"files-from", 0, POPT_ARG_STRING, &files_from, 0, 0, 0 },
399 {"from0", '0', POPT_ARG_NONE, &eol_nulls, 0, 0, 0},
400 {"no-implied-dirs", 0, POPT_ARG_VAL, &implied_dirs, 0, 0, 0 },
4f3e9a0f 401 {"protocol", 0, POPT_ARG_INT, &protocol_version, 0, 0, 0 },
c8d895de 402 {"checksum-seed", 0, POPT_ARG_INT, &checksum_seed, 0, 0, 0 },
06963d0f 403#ifdef INET6
3dd22903
WD
404 {"ipv4", '4', POPT_ARG_VAL, &default_af_hint, AF_INET, 0, 0 },
405 {"ipv6", '6', POPT_ARG_VAL, &default_af_hint, AF_INET6, 0, 0 },
06963d0f 406#endif
8b54f004 407 {0,0,0,0, 0, 0, 0}
2855f61f 408};
7a6421fa 409
06963d0f 410
e51094b7 411static char err_buf[200];
cd8185f2 412
2855f61f 413
dafe63ca
MP
414/**
415 * Store the option error message, if any, so that we can log the
416 * connection attempt (which requires parsing the options), and then
417 * show the error later on.
418 **/
cd8185f2
AT
419void option_error(void)
420{
e51094b7
WD
421 if (!err_buf[0]) {
422 strcpy(err_buf, "Error parsing options: "
423 "option may be supported on client but not on server?\n");
cd8185f2 424 }
e51094b7 425
e51094b7 426 rprintf(FERROR, RSYNC_NAME ": %s", err_buf);
cd8185f2
AT
427}
428
dafe63ca
MP
429
430/**
27ed20f7
WD
431 * Tweak the option table to disable all options that the rsyncd.conf
432 * file has told us to refuse.
dafe63ca 433 **/
27ed20f7 434static void set_refuse_options(char *bp)
cd8185f2 435{
27ed20f7
WD
436 struct poptOption *op;
437 char *cp;
438
439 while (1) {
440 if ((cp = strchr(bp, ' ')) != NULL)
441 *cp= '\0';
55afbb52
WD
442 for (op = long_options; ; op++) {
443 if (!op->longName) {
444 rprintf(FLOG,
445 "Unknown option %s in \"refuse options\" setting\n",
446 bp);
447 break;
448 }
27ed20f7 449 if (strcmp(bp, op->longName) == 0) {
c67d1386 450 op->val = (op - long_options)+OPT_REFUSED_BASE;
27ed20f7
WD
451 break;
452 }
cd8185f2 453 }
27ed20f7
WD
454 if (!cp)
455 break;
456 *cp = ' ';
457 bp = cp + 1;
cd8185f2 458 }
cd8185f2
AT
459}
460
461
2855f61f
MP
462static int count_args(char const **argv)
463{
dfa32483 464 int i = 0;
2855f61f 465
dfa32483
WD
466 while (argv[i] != NULL)
467 i++;
468
469 return i;
2855f61f
MP
470}
471
472
dafe63ca
MP
473/**
474 * Process command line arguments. Called on both local and remote.
475 *
476 * @retval 1 if all options are OK; with globals set to appropriate
477 * values
478 *
479 * @retval 0 on error, with err_buf containing an explanation
480 **/
2855f61f 481int parse_arguments(int *argc, const char ***argv, int frommain)
7a6421fa 482{
d853783f 483 int opt;
cd8185f2 484 char *ref = lp_refuse_options(module_id);
7be73df4 485 const char *arg;
dfa32483 486 poptContext pc;
d853783f 487
27ed20f7
WD
488 if (ref && *ref)
489 set_refuse_options(ref);
490
dfa32483 491 /* TODO: Call poptReadDefaultConfig; handle errors. */
cd8185f2 492
dfa32483
WD
493 /* The context leaks in case of an error, but if there's a
494 * problem we always exit anyhow. */
495 pc = poptGetContext(RSYNC_NAME, *argc, *argv, long_options, 0);
2855f61f
MP
496
497 while ((opt = poptGetNextOpt(pc)) != -1) {
dfa32483
WD
498 /* most options are handled automatically by popt;
499 * only special cases are returned and listed here. */
2855f61f 500
d853783f
AT
501 switch (opt) {
502 case OPT_VERSION:
dfa32483 503 print_rsync_version(FINFO);
d853783f 504 exit_cleanup(0);
dfa32483 505
5b56cc19 506 case OPT_MODIFY_WINDOW:
dfa32483
WD
507 /* The value has already been set by popt, but
508 * we need to remember that we're using a
509 * non-default setting. */
5b56cc19
AT
510 modify_window_set = 1;
511 break;
1de50993
WD
512
513 case OPT_DELETE_AFTER:
514 delete_after = 1;
515 delete_mode = 1;
516 break;
517
b33b791e
DD
518 case OPT_DELETE_EXCLUDED:
519 delete_excluded = 1;
520 delete_mode = 1;
521 break;
522
d853783f 523 case OPT_EXCLUDE:
fa0c1939
WD
524 if (am_server || sanitize_paths)
525 return 0; /* Impossible... */
357406ec 526 add_exclude(&exclude_list, poptGetOptArg(pc), 0);
d853783f
AT
527 break;
528
529 case OPT_INCLUDE:
fa0c1939
WD
530 if (am_server || sanitize_paths)
531 return 0; /* Impossible... */
8645af1d 532 add_exclude(&exclude_list, poptGetOptArg(pc),
357406ec 533 XFLG_DEF_INCLUDE);
d853783f
AT
534 break;
535
536 case OPT_EXCLUDE_FROM:
fa0c1939
WD
537 if (am_server || sanitize_paths)
538 return 0; /* Impossible... */
7be73df4 539 arg = poptGetOptArg(pc);
7be73df4 540 add_exclude_file(&exclude_list, arg,
357406ec 541 XFLG_FATAL_ERRORS);
d853783f
AT
542 break;
543
93695764 544 case OPT_INCLUDE_FROM:
fa0c1939
WD
545 if (am_server || sanitize_paths)
546 return 0; /* Impossible... */
7be73df4 547 arg = poptGetOptArg(pc);
7be73df4 548 add_exclude_file(&exclude_list, arg,
357406ec 549 XFLG_FATAL_ERRORS | XFLG_DEF_INCLUDE);
93695764
DD
550 break;
551
d853783f
AT
552 case 'h':
553 usage(FINFO);
554 exit_cleanup(0);
555
d853783f
AT
556 case 'v':
557 verbose++;
558 break;
7a6421fa 559
b86f0cef 560 case 'q':
f98c60bf
WD
561 if (frommain)
562 quiet++;
b86f0cef
DD
563 break;
564
d853783f
AT
565 case OPT_SENDER:
566 if (!am_server) {
567 usage(FERROR);
65417579 568 exit_cleanup(RERR_SYNTAX);
d853783f
AT
569 }
570 am_sender = 1;
571 break;
572
d9fcc198
AT
573 case 'P':
574 do_progress = 1;
575 keep_partial = 1;
576 break;
577
088aac85 578 case OPT_WRITE_BATCH:
9b3318b0 579 /* batch_name is already set */
088aac85
DD
580 write_batch = 1;
581 break;
582
76f79ba7 583 case OPT_READ_BATCH:
9b3318b0 584 /* batch_name is already set */
6902ed17
MP
585 read_batch = 1;
586 break;
ea5164d1 587
99218d82
WD
588 case OPT_TIMEOUT:
589 if (io_timeout && io_timeout < select_timeout)
590 select_timeout = io_timeout;
591 break;
592
59c95e42
DD
593 case OPT_LINK_DEST:
594#if HAVE_LINK
59c95e42
DD
595 link_dest = 1;
596 break;
597#else
d175d7e1 598 snprintf(err_buf, sizeof err_buf,
dfa32483 599 "hard links are not supported on this %s\n",
59c95e42 600 am_server ? "server" : "client");
59c95e42
DD
601 return 0;
602#endif
603
d853783f 604 default:
55afbb52 605 /* A large opt value means that set_refuse_options()
c67d1386
WD
606 * turned this option off (opt-BASE is its index). */
607 if (opt >= OPT_REFUSED_BASE) {
608 struct poptOption *op =
609 &long_options[opt-OPT_REFUSED_BASE];
27ed20f7
WD
610 int n = snprintf(err_buf, sizeof err_buf,
611 "This server does not support --%s\n",
612 op->longName) - 1;
613 if (op->shortName) {
614 snprintf(err_buf+n, sizeof err_buf-n,
615 " (-%c)\n", op->shortName);
616 }
617 } else {
618 snprintf(err_buf, sizeof err_buf,
619 "%s%s: %s\n",
620 am_server ? "on remote machine: " : "",
621 poptBadOption(pc, POPT_BADOPTION_NOALIAS),
622 poptStrerror(opt));
623 }
dfa32483 624 return 0;
d853783f 625 }
7a6421fa 626 }
2855f61f 627
e1add893 628#if !SUPPORT_LINKS
54e87b4b 629 if (preserve_links && !am_sender) {
e1add893
WD
630 snprintf(err_buf, sizeof err_buf,
631 "symlinks are not supported on this %s\n",
632 am_server ? "server" : "client");
e1add893
WD
633 return 0;
634 }
635#endif
636
637#if !SUPPORT_HARD_LINKS
638 if (preserve_hard_links) {
639 snprintf(err_buf, sizeof err_buf,
640 "hard links are not supported on this %s\n",
641 am_server ? "server" : "client");
e1add893
WD
642 return 0;
643 }
644#endif
645
de584c65
WD
646 if (block_size > MAX_MAP_SIZE) {
647 rprintf(FINFO, "limiting block-size to %d bytes\n",
648 MAX_MAP_SIZE);
649 block_size = MAX_MAP_SIZE;
650 }
651
088aac85 652 if (write_batch && read_batch) {
d175d7e1
WD
653 rprintf(FERROR,
654 "write-batch and read-batch can not be used together\n");
655 exit_cleanup(RERR_SYNTAX);
088aac85 656 }
94327ff0
WD
657 if (write_batch || read_batch) {
658 if (dry_run) {
659 rprintf(FERROR,
660 "--%s-batch cannot be used with --dry_run (-n)\n",
661 write_batch ? "write" : "read");
662 exit_cleanup(RERR_SYNTAX);
663 }
664 if (am_server) {
665 rprintf(FINFO,
666 "ignoring --%s-batch option sent to server\n",
667 write_batch ? "write" : "read");
668 /* We don't actually exit_cleanup(), so that we can
669 * still service older version clients that still send
670 * batch args to server. */
671 read_batch = write_batch = 0;
672 batch_name = NULL;
673 }
b9f592fb 674 }
9b3318b0 675 if (batch_name && strlen(batch_name) > MAX_BATCH_NAME_LEN) {
beb93684 676 rprintf(FERROR,
9b3318b0
WD
677 "the batch-file name must be %d characters or less.\n",
678 MAX_BATCH_NAME_LEN);
beb93684
WD
679 exit_cleanup(RERR_SYNTAX);
680 }
088aac85 681
ce58b1b4
WD
682 if (tmpdir && strlen(tmpdir) >= MAXPATHLEN - 10) {
683 rprintf(FERROR, "the --temp-dir path is WAY too long.\n");
684 exit_cleanup(RERR_SYNTAX);
685 }
686
dfa32483 687 if (archive_mode) {
ea5164d1
WD
688 if (!files_from)
689 recurse = 1;
dfa32483
WD
690#if SUPPORT_LINKS
691 preserve_links = 1;
692#endif
693 preserve_perms = 1;
694 preserve_times = 1;
695 preserve_gid = 1;
696 preserve_uid = 1;
697 preserve_devices = 1;
698 }
699
ea5164d1
WD
700 if (relative_paths < 0)
701 relative_paths = files_from? 1 : 0;
702
7be73df4
WD
703 *argv = poptGetArgs(pc);
704 if (*argv)
705 *argc = count_args(*argv);
706 else
707 *argc = 0;
708
709 if (sanitize_paths) {
710 int i;
711 for (i = *argc; i-- > 0; )
712 (*argv)[i] = alloc_sanitize_path((*argv)[i], NULL);
713 if (tmpdir)
714 tmpdir = alloc_sanitize_path(tmpdir, curr_dir);
715 if (compare_dest)
716 compare_dest = alloc_sanitize_path(compare_dest, curr_dir);
7be73df4
WD
717 if (backup_dir)
718 backup_dir = alloc_sanitize_path(backup_dir, curr_dir);
719 if (files_from)
720 files_from = alloc_sanitize_path(files_from, curr_dir);
721 }
722
5df1fcf2
WD
723 if (daemon_opt) {
724 daemon_opt = 0;
725 am_daemon = 1;
726 return 1;
727 }
728
d175d7e1 729 if (!backup_suffix)
e0391f81 730 backup_suffix = backup_dir ? "" : BACKUP_SUFFIX;
d175d7e1 731 backup_suffix_len = strlen(backup_suffix);
80ddadb7
WD
732 if (strchr(backup_suffix, '/') != NULL) {
733 rprintf(FERROR, "--suffix cannot contain slashes: %s\n",
734 backup_suffix);
735 exit_cleanup(RERR_SYNTAX);
736 }
e0391f81
WD
737 if (backup_dir) {
738 backup_dir_len = strlcpy(backup_dir_buf, backup_dir, sizeof backup_dir_buf);
739 backup_dir_remainder = sizeof backup_dir_buf - backup_dir_len;
740 if (backup_dir_remainder < 32) {
741 rprintf(FERROR, "the --backup-dir path is WAY too long.\n");
742 exit_cleanup(RERR_SYNTAX);
743 }
744 if (backup_dir_buf[backup_dir_len - 1] != '/') {
745 backup_dir_buf[backup_dir_len++] = '/';
746 backup_dir_buf[backup_dir_len] = '\0';
747 }
8dcf9335 748 if (verbose > 1 && !am_sender)
e0391f81 749 rprintf(FINFO, "backup_dir is %s\n", backup_dir_buf);
8dcf9335 750 } else if (!backup_suffix_len && (!am_server || !am_sender)) {
d175d7e1
WD
751 rprintf(FERROR,
752 "--suffix cannot be a null string without --backup-dir\n");
753 exit_cleanup(RERR_SYNTAX);
754 }
755
e2559dbe
S
756 if (do_progress && !verbose)
757 verbose = 1;
758
3c74c3a3
WD
759 if (bwlimit) {
760 bwlimit_writemax = (size_t)bwlimit * 128;
761 if (bwlimit_writemax < 512)
762 bwlimit_writemax = 512;
763 }
764
a3221d2a
WD
765 if (inplace) {
766#if HAVE_FTRUNCATE
767 keep_partial = 0;
768#else
769 snprintf(err_buf, sizeof err_buf,
51bd4f0f 770 "--inplace is not supported on this %s\n",
a3221d2a
WD
771 am_server ? "server" : "client");
772 return 0;
773#endif
774 }
775
ea5164d1
WD
776 if (files_from) {
777 char *colon;
3e89da86 778 if (*argc != 2 && !(am_server && am_sender && *argc == 1)) {
ea5164d1
WD
779 usage(FERROR);
780 exit_cleanup(RERR_SYNTAX);
781 }
63596e1c 782 if (strcmp(files_from, "-") == 0) {
ea5164d1 783 filesfrom_fd = 0;
63596e1c
WD
784 if (am_server)
785 remote_filesfrom_file = "-";
786 }
ea5164d1
WD
787 else if ((colon = find_colon(files_from)) != 0) {
788 if (am_server) {
789 usage(FERROR);
790 exit_cleanup(RERR_SYNTAX);
791 }
792 remote_filesfrom_file = colon+1 + (colon[1] == ':');
793 if (strcmp(remote_filesfrom_file, "-") == 0) {
794 rprintf(FERROR, "Invalid --files-from remote filename\n");
795 exit_cleanup(RERR_SYNTAX);
796 }
797 } else {
ea5164d1
WD
798 filesfrom_fd = open(files_from, O_RDONLY|O_BINARY);
799 if (filesfrom_fd < 0) {
800 rsyserr(FERROR, errno,
801 "failed to open files-from file %s",
802 files_from);
803 exit_cleanup(RERR_FILEIO);
804 }
805 }
806 }
807
b11ed3b1 808 return 1;
7a6421fa
AT
809}
810
811
dafe63ca
MP
812/**
813 * Construct a filtered list of options to pass through from the
814 * client to the server.
815 *
816 * This involves setting options that will tell the server how to
817 * behave, and also filtering out options that are processed only
818 * locally.
819 **/
7a6421fa
AT
820void server_options(char **args,int *argc)
821{
d853783f
AT
822 int ac = *argc;
823 static char argstr[50];
f98c60bf 824 char *arg;
ef5d23eb 825
d853783f
AT
826 int i, x;
827
93689aa5
DD
828 if (blocking_io == -1)
829 blocking_io = 0;
830
d853783f
AT
831 args[ac++] = "--server";
832
1312d9fc
WD
833 if (daemon_over_rsh) {
834 args[ac++] = "--daemon";
835 *argc = ac;
836 /* if we're passing --daemon, we're done */
837 return;
838 }
839
d853783f
AT
840 if (!am_sender)
841 args[ac++] = "--sender";
842
843 x = 1;
844 argstr[0] = '-';
f98c60bf 845 for (i = 0; i < verbose; i++)
d853783f 846 argstr[x++] = 'v';
f0b36a48 847
b86f0cef 848 /* the -q option is intentionally left out */
d853783f
AT
849 if (make_backups)
850 argstr[x++] = 'b';
851 if (update_only)
852 argstr[x++] = 'u';
853 if (dry_run)
854 argstr[x++] = 'n';
855 if (preserve_links)
856 argstr[x++] = 'l';
857 if (copy_links)
858 argstr[x++] = 'L';
716e73d4
WD
859 if (keep_dirlinks && am_sender)
860 argstr[x++] = 'K';
1bfbf40b 861
dfa32483 862 if (whole_file > 0)
d853783f 863 argstr[x++] = 'W';
bceec82f
MP
864 /* We don't need to send --no-whole-file, because it's the
865 * default for remote transfers, and in any case old versions
866 * of rsync will not understand it. */
dfa32483 867
d853783f
AT
868 if (preserve_hard_links)
869 argstr[x++] = 'H';
870 if (preserve_uid)
871 argstr[x++] = 'o';
872 if (preserve_gid)
873 argstr[x++] = 'g';
874 if (preserve_devices)
875 argstr[x++] = 'D';
876 if (preserve_times)
877 argstr[x++] = 't';
878 if (preserve_perms)
879 argstr[x++] = 'p';
880 if (recurse)
881 argstr[x++] = 'r';
882 if (always_checksum)
883 argstr[x++] = 'c';
884 if (cvs_exclude)
885 argstr[x++] = 'C';
886 if (ignore_times)
887 argstr[x++] = 'I';
888 if (relative_paths)
889 argstr[x++] = 'R';
890 if (one_file_system)
891 argstr[x++] = 'x';
892 if (sparse_files)
893 argstr[x++] = 'S';
894 if (do_compression)
895 argstr[x++] = 'z';
f0b36a48 896
dfa32483 897 /* this is a complete hack - blame Rusty
f0b36a48
AT
898
899 this is a hack to make the list_only (remote file list)
900 more useful */
dfa32483 901 if (list_only && !recurse)
f0b36a48
AT
902 argstr[x++] = 'r';
903
d853783f
AT
904 argstr[x] = 0;
905
f98c60bf
WD
906 if (x != 1)
907 args[ac++] = argstr;
d853783f 908
195bd906 909 if (block_size) {
f98c60bf
WD
910 if (asprintf(&arg, "-B%u", block_size) < 0)
911 goto oom;
912 args[ac++] = arg;
dfa32483 913 }
d853783f 914
0b73ca12 915 if (max_delete && am_sender) {
f98c60bf
WD
916 if (asprintf(&arg, "--max-delete=%d", max_delete) < 0)
917 goto oom;
918 args[ac++] = arg;
dfa32483
WD
919 }
920
d853783f 921 if (io_timeout) {
f98c60bf
WD
922 if (asprintf(&arg, "--timeout=%d", io_timeout) < 0)
923 goto oom;
924 args[ac++] = arg;
dfa32483 925 }
d853783f 926
ef5d23eb 927 if (bwlimit) {
f98c60bf
WD
928 if (asprintf(&arg, "--bwlimit=%d", bwlimit) < 0)
929 goto oom;
930 args[ac++] = arg;
ef5d23eb
DD
931 }
932
d175d7e1
WD
933 if (backup_dir) {
934 args[ac++] = "--backup-dir";
935 args[ac++] = backup_dir;
936 }
937
938 /* Only send --suffix if it specifies a non-default value. */
f98c60bf 939 if (strcmp(backup_suffix, backup_dir ? "" : BACKUP_SUFFIX) != 0) {
191e40da 940 /* We use the following syntax to avoid weirdness with '~'. */
f98c60bf
WD
941 if (asprintf(&arg, "--suffix=%s", backup_suffix) < 0)
942 goto oom;
943 args[ac++] = arg;
d853783f
AT
944 }
945
b33b791e
DD
946 if (delete_excluded)
947 args[ac++] = "--delete-excluded";
f98c60bf
WD
948 else if (delete_mode)
949 args[ac++] = "--delete";
b33b791e 950
f83f0548
AT
951 if (size_only)
952 args[ac++] = "--size-only";
953
5b56cc19 954 if (modify_window_set) {
f98c60bf
WD
955 if (asprintf(&arg, "--modify-window=%d", modify_window) < 0)
956 goto oom;
957 args[ac++] = arg;
5b56cc19
AT
958 }
959
c8d895de 960 if (checksum_seed) {
221ddb94 961 if (asprintf(&arg, "--checksum-seed=%d", checksum_seed) < 0)
c8d895de
WD
962 goto oom;
963 args[ac++] = arg;
964 }
965
d853783f
AT
966 if (keep_partial)
967 args[ac++] = "--partial";
968
969 if (force_delete)
970 args[ac++] = "--force";
971
57df171b
AT
972 if (delete_after)
973 args[ac++] = "--delete-after";
974
ef55c686
AT
975 if (ignore_errors)
976 args[ac++] = "--ignore-errors";
977
b5313607
DD
978 if (copy_unsafe_links)
979 args[ac++] = "--copy-unsafe-links";
980
d853783f
AT
981 if (safe_symlinks)
982 args[ac++] = "--safe-links";
983
984 if (numeric_ids)
985 args[ac++] = "--numeric-ids";
986
0b73ca12 987 if (only_existing && am_sender)
1347d512
AT
988 args[ac++] = "--existing";
989
dfa32483 990 if (opt_ignore_existing && am_sender)
3d6feada
MP
991 args[ac++] = "--ignore-existing";
992
a3221d2a
WD
993 if (inplace)
994 args[ac++] = "--inplace";
995
d853783f
AT
996 if (tmpdir) {
997 args[ac++] = "--temp-dir";
998 args[ac++] = tmpdir;
999 }
1000
375a4556
DD
1001 if (compare_dest && am_sender) {
1002 /* the server only needs this option if it is not the sender,
1003 * and it may be an older version that doesn't know this
1004 * option, so don't send it if client is the sender.
1005 */
59c95e42 1006 args[ac++] = link_dest ? "--link-dest" : "--compare-dest";
375a4556
DD
1007 args[ac++] = compare_dest;
1008 }
1009
ea5164d1
WD
1010 if (files_from && (!am_sender || remote_filesfrom_file)) {
1011 if (remote_filesfrom_file) {
1012 args[ac++] = "--files-from";
1013 args[ac++] = remote_filesfrom_file;
1014 if (eol_nulls)
1015 args[ac++] = "--from0";
1016 } else {
1017 args[ac++] = "--files-from=-";
1018 args[ac++] = "--from0";
1019 }
1020 }
1021
d853783f 1022 *argc = ac;
f98c60bf
WD
1023 return;
1024
1025 oom:
1026 out_of_memory("server_options");
7a6421fa
AT
1027}
1028
ea5164d1
WD
1029/**
1030 * Return the position of a ':' IF it is not part of a filename (i.e. as
1031 * long as it doesn't occur after a slash.
1032 */
1033char *find_colon(char *s)
1034{
1035 char *p, *p2;
1036
1037 p = strchr(s,':');
f98c60bf
WD
1038 if (!p)
1039 return NULL;
ea5164d1
WD
1040
1041 /* now check to see if there is a / in the string before the : - if there is then
1042 discard the colon on the assumption that the : is part of a filename */
1043 p2 = strchr(s,'/');
f98c60bf
WD
1044 if (p2 && p2 < p)
1045 return NULL;
ea5164d1
WD
1046
1047 return p;
1048}