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