Document the improved "refuse options" syntax.
[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");
dfa32483 262 rprintf(F," -B, --block-size=SIZE checksum blocking size (default %d)\n",BLOCK_SIZE);
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
WD
441 struct poptOption *op;
442 char *cp;
06a50542 443 int match_short, is_wild;
27ed20f7
WD
444
445 while (1) {
06a50542
WD
446 while (*bp == ' ') bp++;
447 if (!*bp)
448 break;
27ed20f7
WD
449 if ((cp = strchr(bp, ' ')) != NULL)
450 *cp= '\0';
06a50542
WD
451 /* If they specify "delete", reject all delete options. */
452 if (strcmp(bp, "delete") == 0)
453 bp = "delete*";
454 match_short = !bp[1] && *bp != '*';
455 is_wild = !match_short && strpbrk(bp, "*?[") != NULL;
55afbb52
WD
456 for (op = long_options; ; op++) {
457 if (!op->longName) {
458 rprintf(FLOG,
06a50542 459 "No match for refuse-options string \"%s\"\n",
55afbb52
WD
460 bp);
461 break;
462 }
06a50542
WD
463 if (match_short ? *bp == op->shortName
464 : wildmatch(bp, op->longName)) {
465 op->val = (op - long_options) + OPT_REFUSED_BASE;
466 if (!is_wild)
467 break;
27ed20f7 468 }
cd8185f2 469 }
27ed20f7
WD
470 if (!cp)
471 break;
472 *cp = ' ';
473 bp = cp + 1;
cd8185f2 474 }
cd8185f2
AT
475}
476
477
2855f61f
MP
478static int count_args(char const **argv)
479{
dfa32483 480 int i = 0;
2855f61f 481
dfa32483
WD
482 while (argv[i] != NULL)
483 i++;
484
485 return i;
2855f61f
MP
486}
487
488
dafe63ca
MP
489/**
490 * Process command line arguments. Called on both local and remote.
491 *
492 * @retval 1 if all options are OK; with globals set to appropriate
493 * values
494 *
495 * @retval 0 on error, with err_buf containing an explanation
496 **/
2855f61f 497int parse_arguments(int *argc, const char ***argv, int frommain)
7a6421fa 498{
d853783f 499 int opt;
cd8185f2 500 char *ref = lp_refuse_options(module_id);
7be73df4 501 const char *arg;
dfa32483 502 poptContext pc;
d853783f 503
27ed20f7
WD
504 if (ref && *ref)
505 set_refuse_options(ref);
506
dfa32483 507 /* TODO: Call poptReadDefaultConfig; handle errors. */
cd8185f2 508
dfa32483
WD
509 /* The context leaks in case of an error, but if there's a
510 * problem we always exit anyhow. */
511 pc = poptGetContext(RSYNC_NAME, *argc, *argv, long_options, 0);
2855f61f
MP
512
513 while ((opt = poptGetNextOpt(pc)) != -1) {
dfa32483
WD
514 /* most options are handled automatically by popt;
515 * only special cases are returned and listed here. */
2855f61f 516
d853783f
AT
517 switch (opt) {
518 case OPT_VERSION:
dfa32483 519 print_rsync_version(FINFO);
d853783f 520 exit_cleanup(0);
dfa32483 521
5b56cc19 522 case OPT_MODIFY_WINDOW:
dfa32483
WD
523 /* The value has already been set by popt, but
524 * we need to remember that we're using a
525 * non-default setting. */
5b56cc19
AT
526 modify_window_set = 1;
527 break;
1de50993
WD
528
529 case OPT_DELETE_AFTER:
530 delete_after = 1;
531 delete_mode = 1;
532 break;
533
b33b791e
DD
534 case OPT_DELETE_EXCLUDED:
535 delete_excluded = 1;
536 delete_mode = 1;
537 break;
538
d853783f 539 case OPT_EXCLUDE:
fa0c1939
WD
540 if (am_server || sanitize_paths)
541 return 0; /* Impossible... */
357406ec 542 add_exclude(&exclude_list, poptGetOptArg(pc), 0);
d853783f
AT
543 break;
544
545 case OPT_INCLUDE:
fa0c1939
WD
546 if (am_server || sanitize_paths)
547 return 0; /* Impossible... */
8645af1d 548 add_exclude(&exclude_list, poptGetOptArg(pc),
357406ec 549 XFLG_DEF_INCLUDE);
d853783f
AT
550 break;
551
552 case OPT_EXCLUDE_FROM:
fa0c1939
WD
553 if (am_server || sanitize_paths)
554 return 0; /* Impossible... */
7be73df4 555 arg = poptGetOptArg(pc);
7be73df4 556 add_exclude_file(&exclude_list, arg,
357406ec 557 XFLG_FATAL_ERRORS);
d853783f
AT
558 break;
559
93695764 560 case OPT_INCLUDE_FROM:
fa0c1939
WD
561 if (am_server || sanitize_paths)
562 return 0; /* Impossible... */
7be73df4 563 arg = poptGetOptArg(pc);
7be73df4 564 add_exclude_file(&exclude_list, arg,
357406ec 565 XFLG_FATAL_ERRORS | XFLG_DEF_INCLUDE);
93695764
DD
566 break;
567
d853783f
AT
568 case 'h':
569 usage(FINFO);
570 exit_cleanup(0);
571
d853783f
AT
572 case 'v':
573 verbose++;
574 break;
7a6421fa 575
b86f0cef 576 case 'q':
f98c60bf
WD
577 if (frommain)
578 quiet++;
b86f0cef
DD
579 break;
580
d853783f
AT
581 case OPT_SENDER:
582 if (!am_server) {
583 usage(FERROR);
65417579 584 exit_cleanup(RERR_SYNTAX);
d853783f
AT
585 }
586 am_sender = 1;
587 break;
588
d9fcc198
AT
589 case 'P':
590 do_progress = 1;
591 keep_partial = 1;
592 break;
593
088aac85 594 case OPT_WRITE_BATCH:
9b3318b0 595 /* batch_name is already set */
088aac85
DD
596 write_batch = 1;
597 break;
598
76f79ba7 599 case OPT_READ_BATCH:
9b3318b0 600 /* batch_name is already set */
6902ed17
MP
601 read_batch = 1;
602 break;
ea5164d1 603
99218d82
WD
604 case OPT_TIMEOUT:
605 if (io_timeout && io_timeout < select_timeout)
606 select_timeout = io_timeout;
607 break;
608
59c95e42
DD
609 case OPT_LINK_DEST:
610#if HAVE_LINK
59c95e42
DD
611 link_dest = 1;
612 break;
613#else
d175d7e1 614 snprintf(err_buf, sizeof err_buf,
dfa32483 615 "hard links are not supported on this %s\n",
59c95e42 616 am_server ? "server" : "client");
59c95e42
DD
617 return 0;
618#endif
619
d853783f 620 default:
55afbb52 621 /* A large opt value means that set_refuse_options()
c67d1386
WD
622 * turned this option off (opt-BASE is its index). */
623 if (opt >= OPT_REFUSED_BASE) {
624 struct poptOption *op =
625 &long_options[opt-OPT_REFUSED_BASE];
27ed20f7
WD
626 int n = snprintf(err_buf, sizeof err_buf,
627 "This server does not support --%s\n",
628 op->longName) - 1;
629 if (op->shortName) {
630 snprintf(err_buf+n, sizeof err_buf-n,
631 " (-%c)\n", op->shortName);
632 }
633 } else {
634 snprintf(err_buf, sizeof err_buf,
635 "%s%s: %s\n",
636 am_server ? "on remote machine: " : "",
637 poptBadOption(pc, POPT_BADOPTION_NOALIAS),
638 poptStrerror(opt));
639 }
dfa32483 640 return 0;
d853783f 641 }
7a6421fa 642 }
2855f61f 643
e1add893 644#if !SUPPORT_LINKS
54e87b4b 645 if (preserve_links && !am_sender) {
e1add893
WD
646 snprintf(err_buf, sizeof err_buf,
647 "symlinks are not supported on this %s\n",
648 am_server ? "server" : "client");
e1add893
WD
649 return 0;
650 }
651#endif
652
653#if !SUPPORT_HARD_LINKS
654 if (preserve_hard_links) {
655 snprintf(err_buf, sizeof err_buf,
656 "hard links are not supported on this %s\n",
657 am_server ? "server" : "client");
e1add893
WD
658 return 0;
659 }
660#endif
661
de584c65
WD
662 if (block_size > MAX_MAP_SIZE) {
663 rprintf(FINFO, "limiting block-size to %d bytes\n",
664 MAX_MAP_SIZE);
665 block_size = MAX_MAP_SIZE;
666 }
667
088aac85 668 if (write_batch && read_batch) {
c3ea0990 669 snprintf(err_buf, sizeof err_buf,
36119893 670 "--write-batch and --read-batch can not be used together\n");
c3ea0990 671 return 0;
088aac85 672 }
94327ff0
WD
673 if (write_batch || read_batch) {
674 if (dry_run) {
c3ea0990 675 snprintf(err_buf, sizeof err_buf,
94327ff0
WD
676 "--%s-batch cannot be used with --dry_run (-n)\n",
677 write_batch ? "write" : "read");
c3ea0990 678 return 0;
94327ff0
WD
679 }
680 if (am_server) {
681 rprintf(FINFO,
682 "ignoring --%s-batch option sent to server\n",
683 write_batch ? "write" : "read");
684 /* We don't actually exit_cleanup(), so that we can
685 * still service older version clients that still send
686 * batch args to server. */
687 read_batch = write_batch = 0;
688 batch_name = NULL;
689 }
b9f592fb 690 }
36119893 691 if (read_batch && files_from) {
c3ea0990 692 snprintf(err_buf, sizeof err_buf,
36119893 693 "--read-batch cannot be used with --files-from\n");
c3ea0990 694 return 0;
36119893 695 }
9b3318b0 696 if (batch_name && strlen(batch_name) > MAX_BATCH_NAME_LEN) {
c3ea0990 697 snprintf(err_buf, sizeof err_buf,
9b3318b0
WD
698 "the batch-file name must be %d characters or less.\n",
699 MAX_BATCH_NAME_LEN);
c3ea0990 700 return 0;
beb93684 701 }
088aac85 702
ce58b1b4 703 if (tmpdir && strlen(tmpdir) >= MAXPATHLEN - 10) {
c3ea0990
WD
704 snprintf(err_buf, sizeof err_buf,
705 "the --temp-dir path is WAY too long.\n");
706 return 0;
ce58b1b4
WD
707 }
708
dfa32483 709 if (archive_mode) {
ea5164d1
WD
710 if (!files_from)
711 recurse = 1;
dfa32483
WD
712#if SUPPORT_LINKS
713 preserve_links = 1;
714#endif
715 preserve_perms = 1;
716 preserve_times = 1;
717 preserve_gid = 1;
718 preserve_uid = 1;
719 preserve_devices = 1;
720 }
721
ea5164d1
WD
722 if (relative_paths < 0)
723 relative_paths = files_from? 1 : 0;
724
7be73df4
WD
725 *argv = poptGetArgs(pc);
726 if (*argv)
727 *argc = count_args(*argv);
728 else
729 *argc = 0;
730
731 if (sanitize_paths) {
732 int i;
733 for (i = *argc; i-- > 0; )
734 (*argv)[i] = alloc_sanitize_path((*argv)[i], NULL);
735 if (tmpdir)
736 tmpdir = alloc_sanitize_path(tmpdir, curr_dir);
a7260c40
WD
737 if (partial_dir)
738 partial_dir = alloc_sanitize_path(partial_dir, curr_dir);
7be73df4
WD
739 if (compare_dest)
740 compare_dest = alloc_sanitize_path(compare_dest, curr_dir);
7be73df4
WD
741 if (backup_dir)
742 backup_dir = alloc_sanitize_path(backup_dir, curr_dir);
743 if (files_from)
744 files_from = alloc_sanitize_path(files_from, curr_dir);
745 }
c3ea0990
WD
746 if (server_exclude_list.head && !am_sender) {
747 struct exclude_list_struct *elp = &server_exclude_list;
748 if (tmpdir) {
749 clean_fname(tmpdir);
750 if (check_exclude(elp, tmpdir, 1) < 0)
751 goto options_rejected;
752 }
753 if (partial_dir) {
754 clean_fname(partial_dir);
755 if (check_exclude(elp, partial_dir, 1) < 0)
756 goto options_rejected;
757 }
758 if (compare_dest) {
759 clean_fname(compare_dest);
760 if (check_exclude(elp, compare_dest, 1) < 0)
761 goto options_rejected;
762 }
763 if (backup_dir) {
764 clean_fname(backup_dir);
765 if (check_exclude(elp, backup_dir, 1) < 0)
766 goto options_rejected;
767 }
768 }
769 if (server_exclude_list.head && files_from) {
770 clean_fname(files_from);
771 if (check_exclude(&server_exclude_list, files_from, 0) < 0) {
772 options_rejected:
773 snprintf(err_buf, sizeof err_buf,
774 "Your options have been rejected by the server.\n");
775 return 0;
776 }
777 }
7be73df4 778
5df1fcf2
WD
779 if (daemon_opt) {
780 daemon_opt = 0;
781 am_daemon = 1;
782 return 1;
783 }
784
d175d7e1 785 if (!backup_suffix)
e0391f81 786 backup_suffix = backup_dir ? "" : BACKUP_SUFFIX;
d175d7e1 787 backup_suffix_len = strlen(backup_suffix);
80ddadb7 788 if (strchr(backup_suffix, '/') != NULL) {
c3ea0990
WD
789 snprintf(err_buf, sizeof err_buf,
790 "--suffix cannot contain slashes: %s\n",
80ddadb7 791 backup_suffix);
c3ea0990 792 return 0;
80ddadb7 793 }
e0391f81
WD
794 if (backup_dir) {
795 backup_dir_len = strlcpy(backup_dir_buf, backup_dir, sizeof backup_dir_buf);
796 backup_dir_remainder = sizeof backup_dir_buf - backup_dir_len;
797 if (backup_dir_remainder < 32) {
c3ea0990
WD
798 snprintf(err_buf, sizeof err_buf,
799 "the --backup-dir path is WAY too long.\n");
800 return 0;
e0391f81
WD
801 }
802 if (backup_dir_buf[backup_dir_len - 1] != '/') {
803 backup_dir_buf[backup_dir_len++] = '/';
804 backup_dir_buf[backup_dir_len] = '\0';
805 }
8dcf9335 806 if (verbose > 1 && !am_sender)
e0391f81 807 rprintf(FINFO, "backup_dir is %s\n", backup_dir_buf);
8dcf9335 808 } else if (!backup_suffix_len && (!am_server || !am_sender)) {
c3ea0990 809 snprintf(err_buf, sizeof err_buf,
d175d7e1 810 "--suffix cannot be a null string without --backup-dir\n");
c3ea0990 811 return 0;
d175d7e1
WD
812 }
813
e2559dbe
S
814 if (do_progress && !verbose)
815 verbose = 1;
816
3c74c3a3
WD
817 if (bwlimit) {
818 bwlimit_writemax = (size_t)bwlimit * 128;
819 if (bwlimit_writemax < 512)
820 bwlimit_writemax = 512;
821 }
822
a3221d2a
WD
823 if (inplace) {
824#if HAVE_FTRUNCATE
a7260c40
WD
825 if (partial_dir) {
826 snprintf(err_buf, sizeof err_buf,
827 "--inplace cannot be used with --partial-dir\n");
828 return 0;
829 }
a3221d2a
WD
830 keep_partial = 0;
831#else
832 snprintf(err_buf, sizeof err_buf,
51bd4f0f 833 "--inplace is not supported on this %s\n",
a3221d2a
WD
834 am_server ? "server" : "client");
835 return 0;
836#endif
a7260c40
WD
837 } else if (partial_dir) {
838 if (strcmp(partial_dir, ".") == 0)
839 partial_dir = NULL;
840 keep_partial = 1;
a3221d2a
WD
841 }
842
ea5164d1
WD
843 if (files_from) {
844 char *colon;
c3ea0990 845 if (*argc > 2 || (!am_daemon && *argc == 1)) {
ea5164d1
WD
846 usage(FERROR);
847 exit_cleanup(RERR_SYNTAX);
848 }
63596e1c 849 if (strcmp(files_from, "-") == 0) {
ea5164d1 850 filesfrom_fd = 0;
63596e1c
WD
851 if (am_server)
852 remote_filesfrom_file = "-";
853 }
ea5164d1
WD
854 else if ((colon = find_colon(files_from)) != 0) {
855 if (am_server) {
856 usage(FERROR);
857 exit_cleanup(RERR_SYNTAX);
858 }
859 remote_filesfrom_file = colon+1 + (colon[1] == ':');
860 if (strcmp(remote_filesfrom_file, "-") == 0) {
c3ea0990
WD
861 snprintf(err_buf, sizeof err_buf,
862 "Invalid --files-from remote filename\n");
863 return 0;
ea5164d1
WD
864 }
865 } else {
ea5164d1
WD
866 filesfrom_fd = open(files_from, O_RDONLY|O_BINARY);
867 if (filesfrom_fd < 0) {
c3ea0990
WD
868 snprintf(err_buf, sizeof err_buf,
869 "failed to open files-from file %s: %s\n",
870 files_from, strerror(errno));
871 return 0;
ea5164d1
WD
872 }
873 }
874 }
875
b11ed3b1 876 return 1;
7a6421fa
AT
877}
878
879
dafe63ca
MP
880/**
881 * Construct a filtered list of options to pass through from the
882 * client to the server.
883 *
884 * This involves setting options that will tell the server how to
885 * behave, and also filtering out options that are processed only
886 * locally.
887 **/
7a6421fa
AT
888void server_options(char **args,int *argc)
889{
d853783f
AT
890 int ac = *argc;
891 static char argstr[50];
f98c60bf 892 char *arg;
ef5d23eb 893
d853783f
AT
894 int i, x;
895
93689aa5
DD
896 if (blocking_io == -1)
897 blocking_io = 0;
898
d853783f
AT
899 args[ac++] = "--server";
900
1312d9fc
WD
901 if (daemon_over_rsh) {
902 args[ac++] = "--daemon";
903 *argc = ac;
904 /* if we're passing --daemon, we're done */
905 return;
906 }
907
d853783f
AT
908 if (!am_sender)
909 args[ac++] = "--sender";
910
911 x = 1;
912 argstr[0] = '-';
f98c60bf 913 for (i = 0; i < verbose; i++)
d853783f 914 argstr[x++] = 'v';
f0b36a48 915
b86f0cef 916 /* the -q option is intentionally left out */
d853783f
AT
917 if (make_backups)
918 argstr[x++] = 'b';
919 if (update_only)
920 argstr[x++] = 'u';
921 if (dry_run)
922 argstr[x++] = 'n';
923 if (preserve_links)
924 argstr[x++] = 'l';
925 if (copy_links)
926 argstr[x++] = 'L';
716e73d4
WD
927 if (keep_dirlinks && am_sender)
928 argstr[x++] = 'K';
1bfbf40b 929
dfa32483 930 if (whole_file > 0)
d853783f 931 argstr[x++] = 'W';
bceec82f
MP
932 /* We don't need to send --no-whole-file, because it's the
933 * default for remote transfers, and in any case old versions
934 * of rsync will not understand it. */
dfa32483 935
d853783f
AT
936 if (preserve_hard_links)
937 argstr[x++] = 'H';
938 if (preserve_uid)
939 argstr[x++] = 'o';
940 if (preserve_gid)
941 argstr[x++] = 'g';
942 if (preserve_devices)
943 argstr[x++] = 'D';
944 if (preserve_times)
945 argstr[x++] = 't';
946 if (preserve_perms)
947 argstr[x++] = 'p';
948 if (recurse)
949 argstr[x++] = 'r';
950 if (always_checksum)
951 argstr[x++] = 'c';
952 if (cvs_exclude)
953 argstr[x++] = 'C';
954 if (ignore_times)
955 argstr[x++] = 'I';
956 if (relative_paths)
957 argstr[x++] = 'R';
958 if (one_file_system)
959 argstr[x++] = 'x';
960 if (sparse_files)
961 argstr[x++] = 'S';
962 if (do_compression)
963 argstr[x++] = 'z';
f0b36a48 964
dfa32483 965 /* this is a complete hack - blame Rusty
f0b36a48
AT
966
967 this is a hack to make the list_only (remote file list)
968 more useful */
dfa32483 969 if (list_only && !recurse)
f0b36a48
AT
970 argstr[x++] = 'r';
971
d853783f
AT
972 argstr[x] = 0;
973
f98c60bf
WD
974 if (x != 1)
975 args[ac++] = argstr;
d853783f 976
195bd906 977 if (block_size) {
f98c60bf
WD
978 if (asprintf(&arg, "-B%u", block_size) < 0)
979 goto oom;
980 args[ac++] = arg;
dfa32483 981 }
d853783f 982
0b73ca12 983 if (max_delete && am_sender) {
f98c60bf
WD
984 if (asprintf(&arg, "--max-delete=%d", max_delete) < 0)
985 goto oom;
986 args[ac++] = arg;
dfa32483
WD
987 }
988
d853783f 989 if (io_timeout) {
f98c60bf
WD
990 if (asprintf(&arg, "--timeout=%d", io_timeout) < 0)
991 goto oom;
992 args[ac++] = arg;
dfa32483 993 }
d853783f 994
ef5d23eb 995 if (bwlimit) {
f98c60bf
WD
996 if (asprintf(&arg, "--bwlimit=%d", bwlimit) < 0)
997 goto oom;
998 args[ac++] = arg;
ef5d23eb
DD
999 }
1000
d175d7e1
WD
1001 if (backup_dir) {
1002 args[ac++] = "--backup-dir";
1003 args[ac++] = backup_dir;
1004 }
1005
1006 /* Only send --suffix if it specifies a non-default value. */
f98c60bf 1007 if (strcmp(backup_suffix, backup_dir ? "" : BACKUP_SUFFIX) != 0) {
191e40da 1008 /* We use the following syntax to avoid weirdness with '~'. */
f98c60bf
WD
1009 if (asprintf(&arg, "--suffix=%s", backup_suffix) < 0)
1010 goto oom;
1011 args[ac++] = arg;
d853783f
AT
1012 }
1013
06a50542
WD
1014 if (am_sender) {
1015 if (delete_excluded)
1016 args[ac++] = "--delete-excluded";
1017 else if (delete_mode
1018 && (!delete_after || protocol_version < 27))
1019 args[ac++] = "--delete";
1020
1021 if (delete_after)
1022 args[ac++] = "--delete-after";
1023
1024 if (force_delete)
1025 args[ac++] = "--force";
1026 }
b33b791e 1027
f83f0548
AT
1028 if (size_only)
1029 args[ac++] = "--size-only";
1030
5b56cc19 1031 if (modify_window_set) {
f98c60bf
WD
1032 if (asprintf(&arg, "--modify-window=%d", modify_window) < 0)
1033 goto oom;
1034 args[ac++] = arg;
5b56cc19
AT
1035 }
1036
c8d895de 1037 if (checksum_seed) {
221ddb94 1038 if (asprintf(&arg, "--checksum-seed=%d", checksum_seed) < 0)
c8d895de
WD
1039 goto oom;
1040 args[ac++] = arg;
1041 }
1042
a7260c40
WD
1043 if (partial_dir && am_sender) {
1044 args[ac++] = "--partial-dir";
1045 args[ac++] = partial_dir;
1046 } else if (keep_partial)
d853783f
AT
1047 args[ac++] = "--partial";
1048
ef55c686
AT
1049 if (ignore_errors)
1050 args[ac++] = "--ignore-errors";
1051
b5313607
DD
1052 if (copy_unsafe_links)
1053 args[ac++] = "--copy-unsafe-links";
1054
d853783f
AT
1055 if (safe_symlinks)
1056 args[ac++] = "--safe-links";
1057
1058 if (numeric_ids)
1059 args[ac++] = "--numeric-ids";
1060
0b73ca12 1061 if (only_existing && am_sender)
1347d512
AT
1062 args[ac++] = "--existing";
1063
dfa32483 1064 if (opt_ignore_existing && am_sender)
3d6feada
MP
1065 args[ac++] = "--ignore-existing";
1066
a3221d2a
WD
1067 if (inplace)
1068 args[ac++] = "--inplace";
1069
d853783f
AT
1070 if (tmpdir) {
1071 args[ac++] = "--temp-dir";
1072 args[ac++] = tmpdir;
1073 }
1074
375a4556
DD
1075 if (compare_dest && am_sender) {
1076 /* the server only needs this option if it is not the sender,
1077 * and it may be an older version that doesn't know this
1078 * option, so don't send it if client is the sender.
1079 */
59c95e42 1080 args[ac++] = link_dest ? "--link-dest" : "--compare-dest";
375a4556
DD
1081 args[ac++] = compare_dest;
1082 }
1083
ea5164d1
WD
1084 if (files_from && (!am_sender || remote_filesfrom_file)) {
1085 if (remote_filesfrom_file) {
1086 args[ac++] = "--files-from";
1087 args[ac++] = remote_filesfrom_file;
1088 if (eol_nulls)
1089 args[ac++] = "--from0";
1090 } else {
1091 args[ac++] = "--files-from=-";
1092 args[ac++] = "--from0";
1093 }
1094 }
1095
d853783f 1096 *argc = ac;
f98c60bf
WD
1097 return;
1098
1099 oom:
1100 out_of_memory("server_options");
7a6421fa
AT
1101}
1102
ea5164d1
WD
1103/**
1104 * Return the position of a ':' IF it is not part of a filename (i.e. as
1105 * long as it doesn't occur after a slash.
1106 */
1107char *find_colon(char *s)
1108{
1109 char *p, *p2;
1110
1111 p = strchr(s,':');
f98c60bf
WD
1112 if (!p)
1113 return NULL;
ea5164d1
WD
1114
1115 /* now check to see if there is a / in the string before the : - if there is then
1116 discard the colon on the assumption that the : is part of a filename */
1117 p2 = strchr(s,'/');
f98c60bf
WD
1118 if (p2 && p2 < p)
1119 return NULL;
ea5164d1
WD
1120
1121 return p;
1122}