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