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