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