Updated to remove completed items and add a little more info for
[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
7bc90b30 24extern int module_id;
7be73df4 25extern int sanitize_paths;
99218d82 26extern int select_timeout;
7842418b
WD
27extern struct filter_list_struct filter_list;
28extern struct filter_list_struct server_filter_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;
20fb7b91 52int omit_dir_times = 0;
7a6421fa
AT
53int update_only = 0;
54int cvs_exclude = 0;
a5c11139 55int dry_run = 0;
a5c11139
WD
56int ignore_times = 0;
57int delete_mode = 0;
a51b3168 58int delete_during = 0;
51d48398
WD
59int delete_before = 0;
60int delete_after = 0;
a5c11139 61int delete_excluded = 0;
07c6ae7d 62int remove_sent_files = 0;
a5c11139 63int one_file_system = 0;
4f3e9a0f 64int protocol_version = PROTOCOL_VERSION;
a5c11139
WD
65int sparse_files = 0;
66int do_compression = 0;
67int am_root = 0;
68int orig_umask = 0;
ea5164d1
WD
69int relative_paths = -1;
70int implied_dirs = 1;
7a6421fa
AT
71int numeric_ids = 0;
72int force_delete = 0;
73int io_timeout = 0;
7a6421fa 74int am_server = 0;
f1d5ba40 75int am_sender = -1;
4337c8f8 76int am_generator = 0;
ea5164d1
WD
77char *files_from = NULL;
78int filesfrom_fd = -1;
79char *remote_filesfrom_file = NULL;
80int eol_nulls = 0;
7a6421fa 81int recurse = 0;
65e4cda0 82int xfer_dirs = 0;
1312d9fc
WD
83int am_daemon = 0;
84int daemon_over_rsh = 0;
a5c11139
WD
85int do_stats = 0;
86int do_progress = 0;
87int keep_partial = 0;
88int safe_symlinks = 0;
89int copy_unsafe_links = 0;
90int size_only = 0;
9fb08441 91int daemon_bwlimit = 0;
a5c11139 92int bwlimit = 0;
c4ed1487 93int fuzzy_basis = 0;
3c74c3a3 94size_t bwlimit_writemax = 0;
a5c11139
WD
95int only_existing = 0;
96int opt_ignore_existing = 0;
07c6ae7d 97int need_messages_from_generator = 0;
a5c11139 98int max_delete = 0;
7d5acf1d 99OFF_T max_size = 0;
a5c11139
WD
100int ignore_errors = 0;
101int modify_window = 0;
102int blocking_io = -1;
2289bf64 103int checksum_seed = 0;
a3221d2a 104int inplace = 0;
f06e7082 105int delay_updates = 0;
a06b419d 106long block_size = 0; /* "long" because popt can't set an int32. */
7a6421fa 107
b35d0d8e 108
13e29995 109/** Network address family. **/
4f5b0756 110#ifdef INET6
13e29995 111int default_af_hint = 0; /* Any protocol */
6ab6d4bf 112#else
13e29995 113int default_af_hint = AF_INET; /* Must use IPv4 */
6ab6d4bf 114#endif
06963d0f 115
13e29995
MP
116/** Do not go into the background when run as --daemon. Good
117 * for debugging and required for running as a service on W32,
118 * or under Unix process-monitors. **/
119int no_detach = 0;
120
088aac85
DD
121int write_batch = 0;
122int read_batch = 0;
d175d7e1
WD
123int backup_dir_len = 0;
124int backup_suffix_len;
e0391f81 125unsigned int backup_dir_remainder;
6902ed17 126
d175d7e1 127char *backup_suffix = NULL;
7a6421fa 128char *tmpdir = NULL;
a7260c40 129char *partial_dir = NULL;
e012f858 130char *basis_dir[MAX_BASIS_DIRS+1];
30e8c8e1 131char *config_file = NULL;
7a6421fa 132char *shell_cmd = NULL;
b6062654 133char *log_format = NULL;
65575e96 134char *password_file = NULL;
41bd28fe 135char *rsync_path = RSYNC_PATH;
66203a98 136char *backup_dir = NULL;
e0391f81 137char backup_dir_buf[MAXPATHLEN];
0c56b1ad 138int rsync_port = 0;
dfd7d541 139int compare_dest = 0;
e012f858 140int copy_dest = 0;
59c95e42 141int link_dest = 0;
ce0b384f 142int basis_dir_cnt = 0;
7a6421fa
AT
143
144int verbose = 0;
b86f0cef 145int quiet = 0;
b78296cb 146int itemize_changes = 0;
e7651884 147int log_before_transfer = 0;
684d7582 148int log_format_has_i = 0;
5c5e1598 149int log_format_has_o_or_i = 0;
7a6421fa 150int always_checksum = 0;
f7632fc6 151int list_only = 0;
7a6421fa 152
9b3318b0
WD
153#define MAX_BATCH_NAME_LEN 256 /* Must be less than MAXPATHLEN-13 */
154char *batch_name = NULL;
6902ed17 155
e1add893 156static int daemon_opt; /* sets am_daemon after option error-reporting */
aa4d3b4c 157static int F_option_cnt = 0;
5b56cc19 158static int modify_window_set;
702cd15c 159static int refused_delete, refused_archive_part;
3296f91b 160static int refused_partial, refused_progress, refused_delete_before;
12a79db2 161static char *dest_option = NULL;
7d5acf1d 162static char *max_size_arg;
3671987f 163static char partialdir_for_delayupdate[] = ".~tmp~";
5b56cc19 164
06963d0f 165/** Local address to bind. As a character string because it's
fdf57ede 166 * interpreted by the IPv6 layer: should be a numeric IP4 or IP6
06963d0f
MP
167 * address, or a hostname. **/
168char *bind_address;
5c9730a4 169
7a24c346 170
27a12348 171static void print_rsync_version(enum logcode f)
7a24c346 172{
dfa32483 173 char const *got_socketpair = "no ";
a3221d2a 174 char const *have_inplace = "no ";
dfa32483
WD
175 char const *hardlinks = "no ";
176 char const *links = "no ";
a358449a 177 char const *ipv6 = "no ";
736a6a29 178 STRUCT_STAT *dumstat;
0c80cd8e 179
4f5b0756 180#ifdef HAVE_SOCKETPAIR
dfa32483 181 got_socketpair = "";
0c80cd8e 182#endif
2855f61f 183
4f5b0756 184#ifdef HAVE_FTRUNCATE
a3221d2a
WD
185 have_inplace = "";
186#endif
187
4f5b0756 188#ifdef SUPPORT_HARD_LINKS
dfa32483 189 hardlinks = "";
2855f61f
MP
190#endif
191
4f5b0756 192#ifdef SUPPORT_LINKS
dfa32483 193 links = "";
2855f61f
MP
194#endif
195
4f5b0756 196#ifdef INET6
a358449a 197 ipv6 = "";
dfa32483 198#endif
a358449a 199
dfa32483
WD
200 rprintf(f, "%s version %s protocol version %d\n",
201 RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION);
202 rprintf(f,
72a90c75 203 "Copyright (C) 1996-2005 by Andrew Tridgell and others\n");
3b4b1984 204 rprintf(f, "<http://rsync.samba.org/>\n");
dfa32483
WD
205 rprintf(f, "Capabilities: %d-bit files, %ssocketpairs, "
206 "%shard links, %ssymlinks, batchfiles, \n",
a5c11139 207 (int) (sizeof (OFF_T) * 8),
dfa32483 208 got_socketpair, hardlinks, links);
2855f61f 209
736a6a29
MP
210 /* Note that this field may not have type ino_t. It depends
211 * on the complicated interaction between largefile feature
212 * macros. */
a3221d2a
WD
213 rprintf(f, " %sinplace, %sIPv6, %d-bit system inums, %d-bit internal inums\n",
214 have_inplace, ipv6,
a5c11139 215 (int) (sizeof dumstat->st_ino * 8),
1490812a 216 (int) (sizeof (int64) * 8));
fc0302cf
MP
217#ifdef MAINTAINER_MODE
218 rprintf(f, " panic action: \"%s\"\n",
219 get_panic_action());
220#endif
736a6a29 221
031fa9ad
WD
222#if SIZEOF_INT64 < 8
223 rprintf(f, "WARNING: no 64-bit integers on this platform!\n");
7a24c346 224#endif
c561edaa
WD
225 if (sizeof (int64) != SIZEOF_INT64) {
226 rprintf(f,
227 "WARNING: size mismatch in SIZEOF_INT64 define (%d != %d)\n",
228 (int) SIZEOF_INT64, (int) sizeof (int64));
229 }
7b329a2d
MP
230
231 rprintf(f,
232"\n"
233"rsync comes with ABSOLUTELY NO WARRANTY. This is free software, and you\n"
234"are welcome to redistribute it under certain conditions. See the GNU\n"
235"General Public Licence for details.\n"
236 );
7a24c346
MP
237}
238
239
0f3203c3 240void usage(enum logcode F)
7a6421fa 241{
2855f61f 242 print_rsync_version(F);
704f908e 243
3ff984d7 244 rprintf(F,"\nrsync is a file transfer program capable of efficient remote update\nvia a fast differencing algorithm.\n\n");
704f908e 245
9ef53907 246 rprintf(F,"Usage: rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST\n");
704f908e 247 rprintf(F," or rsync [OPTION]... [USER@]HOST:SRC DEST\n");
9ef53907 248 rprintf(F," or rsync [OPTION]... SRC [SRC]... DEST\n");
14d43f1f 249 rprintf(F," or rsync [OPTION]... [USER@]HOST::SRC [DEST]\n");
9ef53907 250 rprintf(F," or rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST\n");
14d43f1f 251 rprintf(F," or rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST]\n");
eaa4c150 252 rprintf(F," or rsync [OPTION]... SRC [SRC]... rsync://[USER@]HOST[:PORT]/DEST\n");
9ef53907
DD
253 rprintf(F,"SRC on single-colon remote HOST will be expanded by remote shell\n");
254 rprintf(F,"SRC on server remote HOST may contain shell wildcards or multiple\n");
255 rprintf(F," sources separated by space as long as they have same top-level\n");
704f908e
AT
256 rprintf(F,"\nOptions\n");
257 rprintf(F," -v, --verbose increase verbosity\n");
b3708acf
WD
258 rprintf(F," -q, --quiet suppress non-error messages\n");
259 rprintf(F," -c, --checksum skip based on checksum, not mod-time & size\n");
260 rprintf(F," -a, --archive archive mode; same as -rlptgoD (no -H)\n");
704f908e
AT
261 rprintf(F," -r, --recursive recurse into directories\n");
262 rprintf(F," -R, --relative use relative path names\n");
ea5164d1
WD
263 rprintf(F," --no-relative turn off --relative\n");
264 rprintf(F," --no-implied-dirs don't send implied dirs with -R\n");
6839140e 265 rprintf(F," -b, --backup make backups (see --suffix & --backup-dir)\n");
b3708acf
WD
266 rprintf(F," --backup-dir=DIR make backups into hierarchy based in DIR\n");
267 rprintf(F," --suffix=SUFFIX set backup suffix (default %s w/o --backup-dir)\n",BACKUP_SUFFIX);
268 rprintf(F," -u, --update skip files that are newer on the receiver\n");
4ce838e1 269 rprintf(F," --inplace update destination files in-place (SEE MAN PAGE)\n");
65e4cda0 270 rprintf(F," -d, --dirs transfer directories without recursing\n");
13e29995 271 rprintf(F," -l, --links copy symlinks as symlinks\n");
b3708acf
WD
272 rprintf(F," -L, --copy-links transform symlink into referent file/dir\n");
273 rprintf(F," --copy-unsafe-links only \"unsafe\" symlinks are transformed\n");
274 rprintf(F," --safe-links ignore symlinks that point outside the source tree\n");
704f908e 275 rprintf(F," -H, --hard-links preserve hard links\n");
65e4cda0 276 rprintf(F," -K, --keep-dirlinks treat symlinked dir on receiver as dir\n");
704f908e
AT
277 rprintf(F," -p, --perms preserve permissions\n");
278 rprintf(F," -o, --owner preserve owner (root only)\n");
279 rprintf(F," -g, --group preserve group\n");
280 rprintf(F," -D, --devices preserve devices (root only)\n");
dfa32483 281 rprintf(F," -t, --times preserve times\n");
20fb7b91 282 rprintf(F," -O, --omit-dir-times omit directories when preserving times\n");
704f908e
AT
283 rprintf(F," -S, --sparse handle sparse files efficiently\n");
284 rprintf(F," -n, --dry-run show what would have been transferred\n");
98bf61c8 285 rprintf(F," -W, --whole-file copy files whole (without rsync algorithm)\n");
b3708acf 286 rprintf(F," --no-whole-file always use incremental rsync algorithm\n");
704f908e 287 rprintf(F," -x, --one-file-system don't cross filesystem boundaries\n");
9cd339eb 288 rprintf(F," -B, --block-size=SIZE force a fixed checksum block-size\n");
b3708acf 289 rprintf(F," -e, --rsh=COMMAND specify the remote shell to use\n");
704f908e 290 rprintf(F," --rsync-path=PATH specify path to rsync on the remote machine\n");
b3708acf 291 rprintf(F," --existing only update files that already exist on receiver\n");
6839140e 292 rprintf(F," --ignore-existing ignore files that already exist on receiving side\n");
07c6ae7d 293 rprintf(F," --remove-sent-files sent files/symlinks are removed from sending side\n");
3359acb8 294 rprintf(F," --del an alias for --delete-during\n");
704f908e 295 rprintf(F," --delete delete files that don't exist on the sending side\n");
c6eb7fad 296 rprintf(F," --delete-before receiver deletes before transfer (default)\n");
3359acb8
WD
297 rprintf(F," --delete-during receiver deletes during transfer, not before\n");
298 rprintf(F," --delete-after receiver deletes after transfer, not before\n");
51d48398 299 rprintf(F," --delete-excluded also delete excluded files on the receiving side\n");
db2b5cb7 300 rprintf(F," --ignore-errors delete even if there are I/O errors\n");
51d48398 301 rprintf(F," --force force deletion of directories even if not empty\n");
0b73ca12 302 rprintf(F," --max-delete=NUM don't delete more than NUM files\n");
7d5acf1d 303 rprintf(F," --max-size=SIZE don't transfer any file larger than SIZE\n");
c95da96a 304 rprintf(F," --partial keep partially transferred files\n");
a7260c40 305 rprintf(F," --partial-dir=DIR put a partially transferred file into DIR\n");
b3708acf 306 rprintf(F," --delay-updates put all updated files into place at transfer's end\n");
704f908e 307 rprintf(F," --numeric-ids don't map uid/gid values by user/group name\n");
db2b5cb7 308 rprintf(F," --timeout=TIME set I/O timeout in seconds\n");
b3708acf
WD
309 rprintf(F," -I, --ignore-times don't skip files that match in size and mod-time\n");
310 rprintf(F," --size-only skip files that match in size\n");
311 rprintf(F," --modify-window=NUM compare mod-times with reduced accuracy\n");
4db88e5b 312 rprintf(F," -T, --temp-dir=DIR create temporary files in directory DIR\n");
c4ed1487 313 rprintf(F," -y, --fuzzy find similar file for basis if no dest file\n");
375a4556 314 rprintf(F," --compare-dest=DIR also compare destination files relative to DIR\n");
e012f858
WD
315 rprintf(F," --copy-dest=DIR ... and include copies of unchanged files\n");
316 rprintf(F," --link-dest=DIR hardlink to files in DIR when unchanged\n");
f924946e 317 rprintf(F," -z, --compress compress file data during the transfer\n");
b3708acf 318 rprintf(F," -C, --cvs-exclude auto-ignore files the same way CVS does\n");
aa4d3b4c 319 rprintf(F," -f, --filter=RULE add a file-filtering RULE\n");
9c71f56a 320 rprintf(F," -F same as --filter='dir-merge /.rsync-filter'\n");
aa4d3b4c 321 rprintf(F," repeated: --filter='- .rsync-filter'\n");
2acf81eb 322 rprintf(F," --exclude=PATTERN exclude files matching PATTERN\n");
b3708acf 323 rprintf(F," --exclude-from=FILE read exclude patterns from FILE\n");
2acf81eb 324 rprintf(F," --include=PATTERN don't exclude files matching PATTERN\n");
b3708acf
WD
325 rprintf(F," --include-from=FILE read include patterns from FILE\n");
326 rprintf(F," --files-from=FILE read list of source-file names from FILE\n");
4db88e5b 327 rprintf(F," -0, --from0 all *-from file lists are delimited by nulls\n");
dfa32483 328 rprintf(F," --version print version number\n");
b4713295 329 rprintf(F," --port=PORT specify double-colon alternate port number\n");
db2b5cb7 330 rprintf(F," --blocking-io use blocking I/O for the remote shell\n");
b3708acf
WD
331 rprintf(F," --no-blocking-io turn off blocking I/O when it is the default\n");
332 rprintf(F," --stats give some file-transfer stats\n");
dfa32483 333 rprintf(F," --progress show progress during transfer\n");
b3708acf 334 rprintf(F," -P same as --partial --progress\n");
b78296cb 335 rprintf(F," -i, --itemize-changes output a change-summary for all updates\n");
b3708acf
WD
336 rprintf(F," --log-format=FORMAT log file-transfers using specified format\n");
337 rprintf(F," --password-file=FILE read password from FILE\n");
65e4cda0 338 rprintf(F," --list-only list the files instead of copying them\n");
b3708acf
WD
339 rprintf(F," --bwlimit=KBPS limit I/O bandwidth; KBytes per second\n");
340 rprintf(F," --write-batch=FILE write a batched update to FILE\n");
341 rprintf(F," --read-batch=FILE read a batched update from FILE\n");
4f5b0756 342#ifdef INET6
4db88e5b
WD
343 rprintf(F," -4, --ipv4 prefer IPv4\n");
344 rprintf(F," -6, --ipv6 prefer IPv6\n");
06963d0f 345#endif
3dd22903 346 rprintf(F," -h, --help show this help screen\n");
7a6421fa 347
3ac7f5d4
WD
348 rprintf(F,"\nUse \"rsync --daemon --help\" to see the daemon-mode command-line options.\n");
349 rprintf(F,"Please see the rsync(1) and rsyncd.conf(5) man pages for full documentation.\n");
2855f61f 350 rprintf(F,"See http://rsync.samba.org/ for updates, bug reports, and answers\n");
7a6421fa
AT
351}
352
3ac7f5d4 353enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
aa4d3b4c 354 OPT_FILTER, OPT_COMPARE_DEST, OPT_COPY_DEST, OPT_LINK_DEST,
1f3d6cdd 355 OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW,
7d5acf1d 356 OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_TIMEOUT, OPT_MAX_SIZE,
c67d1386 357 OPT_REFUSED_BASE = 9000};
7a6421fa 358
2855f61f
MP
359static struct poptOption long_options[] = {
360 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
8db7cc2c 361 {"version", 0, POPT_ARG_NONE, 0, OPT_VERSION, 0, 0},
d175d7e1 362 {"suffix", 0, POPT_ARG_STRING, &backup_suffix, 0, 0, 0 },
3dd22903
WD
363 {"rsync-path", 0, POPT_ARG_STRING, &rsync_path, 0, 0, 0 },
364 {"password-file", 0, POPT_ARG_STRING, &password_file, 0, 0, 0 },
afb6e945
WD
365 {"ignore-times", 'I', POPT_ARG_NONE, &ignore_times, 0, 0, 0 },
366 {"size-only", 0, POPT_ARG_NONE, &size_only, 0, 0, 0 },
8b54f004 367 {"modify-window", 0, POPT_ARG_INT, &modify_window, OPT_MODIFY_WINDOW, 0, 0 },
afb6e945 368 {"one-file-system", 'x', POPT_ARG_NONE, &one_file_system, 0, 0, 0 },
afb6e945
WD
369 {"existing", 0, POPT_ARG_NONE, &only_existing, 0, 0, 0 },
370 {"ignore-existing", 0, POPT_ARG_NONE, &opt_ignore_existing, 0, 0, 0 },
3671987f 371 {"del", 0, POPT_ARG_NONE, &delete_during, 0, 0, 0 },
3359acb8 372 {"delete", 0, POPT_ARG_NONE, &delete_mode, 0, 0, 0 },
c6eb7fad 373 {"delete-before", 0, POPT_ARG_VAL, &delete_before, 2, 0, 0 },
3359acb8 374 {"delete-during", 0, POPT_ARG_NONE, &delete_during, 0, 0, 0 },
51d48398
WD
375 {"delete-after", 0, POPT_ARG_NONE, &delete_after, 0, 0, 0 },
376 {"delete-excluded", 0, POPT_ARG_NONE, &delete_excluded, 0, 0, 0 },
07c6ae7d 377 {"remove-sent-files",0, POPT_ARG_NONE, &remove_sent_files, 0, 0, 0 },
afb6e945
WD
378 {"force", 0, POPT_ARG_NONE, &force_delete, 0, 0, 0 },
379 {"numeric-ids", 0, POPT_ARG_NONE, &numeric_ids, 0, 0, 0 },
aa4d3b4c 380 {"filter", 'f', POPT_ARG_STRING, 0, OPT_FILTER, 0, 0 },
8db7cc2c
WD
381 {"exclude", 0, POPT_ARG_STRING, 0, OPT_EXCLUDE, 0, 0 },
382 {"include", 0, POPT_ARG_STRING, 0, OPT_INCLUDE, 0, 0 },
383 {"exclude-from", 0, POPT_ARG_STRING, 0, OPT_EXCLUDE_FROM, 0, 0 },
384 {"include-from", 0, POPT_ARG_STRING, 0, OPT_INCLUDE_FROM, 0, 0 },
afb6e945 385 {"safe-links", 0, POPT_ARG_NONE, &safe_symlinks, 0, 0, 0 },
8db7cc2c 386 {"help", 'h', POPT_ARG_NONE, 0, 'h', 0, 0 },
afb6e945
WD
387 {"backup", 'b', POPT_ARG_NONE, &make_backups, 0, 0, 0 },
388 {"dry-run", 'n', POPT_ARG_NONE, &dry_run, 0, 0, 0 },
389 {"sparse", 'S', POPT_ARG_NONE, &sparse_files, 0, 0, 0 },
390 {"cvs-exclude", 'C', POPT_ARG_NONE, &cvs_exclude, 0, 0, 0 },
391 {"update", 'u', POPT_ARG_NONE, &update_only, 0, 0, 0 },
a3221d2a 392 {"inplace", 0, POPT_ARG_NONE, &inplace, 0, 0, 0 },
65e4cda0 393 {"dirs", 'd', POPT_ARG_VAL, &xfer_dirs, 2, 0, 0 },
afb6e945
WD
394 {"links", 'l', POPT_ARG_NONE, &preserve_links, 0, 0, 0 },
395 {"copy-links", 'L', POPT_ARG_NONE, &copy_links, 0, 0, 0 },
65e4cda0 396 {"keep-dirlinks", 'K', POPT_ARG_NONE, &keep_dirlinks, 0, 0, 0 },
afb6e945
WD
397 {"whole-file", 'W', POPT_ARG_VAL, &whole_file, 1, 0, 0 },
398 {"no-whole-file", 0, POPT_ARG_VAL, &whole_file, 0, 0, 0 },
b78296cb 399 {"copy-unsafe-links",0, POPT_ARG_NONE, &copy_unsafe_links, 0, 0, 0 },
afb6e945
WD
400 {"perms", 'p', POPT_ARG_NONE, &preserve_perms, 0, 0, 0 },
401 {"owner", 'o', POPT_ARG_NONE, &preserve_uid, 0, 0, 0 },
402 {"group", 'g', POPT_ARG_NONE, &preserve_gid, 0, 0, 0 },
403 {"devices", 'D', POPT_ARG_NONE, &preserve_devices, 0, 0, 0 },
404 {"times", 't', POPT_ARG_NONE, &preserve_times, 0, 0, 0 },
20fb7b91 405 {"omit-dir-times", 'O', POPT_ARG_NONE, &omit_dir_times, 0, 0, 0 },
afb6e945 406 {"checksum", 'c', POPT_ARG_NONE, &always_checksum, 0, 0, 0 },
8db7cc2c
WD
407 {"verbose", 'v', POPT_ARG_NONE, 0, 'v', 0, 0 },
408 {"quiet", 'q', POPT_ARG_NONE, 0, 'q', 0, 0 },
dfa32483 409 {"archive", 'a', POPT_ARG_NONE, &archive_mode, 0, 0, 0 },
afb6e945 410 {"server", 0, POPT_ARG_NONE, &am_server, 0, 0, 0 },
8db7cc2c 411 {"sender", 0, POPT_ARG_NONE, 0, OPT_SENDER, 0, 0 },
51d48398
WD
412 {"recursive", 'r', POPT_ARG_VAL, &recurse, -1, 0, 0 },
413 {"list-only", 0, POPT_ARG_VAL, &list_only, 2, 0, 0 },
ea5164d1
WD
414 {"relative", 'R', POPT_ARG_VAL, &relative_paths, 1, 0, 0 },
415 {"no-relative", 0, POPT_ARG_VAL, &relative_paths, 0, 0, 0 },
afb6e945 416 {"rsh", 'e', POPT_ARG_STRING, &shell_cmd, 0, 0, 0 },
a06b419d 417 {"block-size", 'B', POPT_ARG_LONG, &block_size, 0, 0, 0 },
afb6e945 418 {"max-delete", 0, POPT_ARG_INT, &max_delete, 0, 0, 0 },
7d5acf1d 419 {"max-size", 0, POPT_ARG_STRING, &max_size_arg, OPT_MAX_SIZE, 0, 0 },
99218d82 420 {"timeout", 0, POPT_ARG_INT, &io_timeout, OPT_TIMEOUT, 0, 0 },
afb6e945 421 {"temp-dir", 'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
e012f858
WD
422 {"compare-dest", 0, POPT_ARG_STRING, 0, OPT_COMPARE_DEST, 0, 0 },
423 {"copy-dest", 0, POPT_ARG_STRING, 0, OPT_COPY_DEST, 0, 0 },
424 {"link-dest", 0, POPT_ARG_STRING, 0, OPT_LINK_DEST, 0, 0 },
c4ed1487 425 {"fuzzy", 'y', POPT_ARG_NONE, &fuzzy_basis, 0, 0, 0 },
2855f61f 426 /* TODO: Should this take an optional int giving the compression level? */
afb6e945 427 {"compress", 'z', POPT_ARG_NONE, &do_compression, 0, 0, 0 },
afb6e945
WD
428 {"stats", 0, POPT_ARG_NONE, &do_stats, 0, 0, 0 },
429 {"progress", 0, POPT_ARG_NONE, &do_progress, 0, 0, 0 },
430 {"partial", 0, POPT_ARG_NONE, &keep_partial, 0, 0, 0 },
a7260c40 431 {"partial-dir", 0, POPT_ARG_STRING, &partial_dir, 0, 0, 0 },
f06e7082 432 {"delay-updates", 0, POPT_ARG_NONE, &delay_updates, 0, 0, 0 },
afb6e945
WD
433 {"ignore-errors", 0, POPT_ARG_NONE, &ignore_errors, 0, 0, 0 },
434 {"blocking-io", 0, POPT_ARG_VAL, &blocking_io, 1, 0, 0 },
435 {"no-blocking-io", 0, POPT_ARG_VAL, &blocking_io, 0, 0, 0 },
aa4d3b4c 436 {0, 'F', POPT_ARG_NONE, 0, 'F', 0, 0 },
8db7cc2c 437 {0, 'P', POPT_ARG_NONE, 0, 'P', 0, 0 },
b4713295 438 {"port", 0, POPT_ARG_INT, &rsync_port, 0, 0, 0 },
afb6e945 439 {"log-format", 0, POPT_ARG_STRING, &log_format, 0, 0, 0 },
b78296cb 440 {"itemize-changes", 'i', POPT_ARG_NONE, &itemize_changes, 0, 0, 0 },
afb6e945 441 {"bwlimit", 0, POPT_ARG_INT, &bwlimit, 0, 0, 0 },
afb6e945
WD
442 {"backup-dir", 0, POPT_ARG_STRING, &backup_dir, 0, 0, 0 },
443 {"hard-links", 'H', POPT_ARG_NONE, &preserve_hard_links, 0, 0, 0 },
8db7cc2c
WD
444 {"read-batch", 0, POPT_ARG_STRING, &batch_name, OPT_READ_BATCH, 0, 0 },
445 {"write-batch", 0, POPT_ARG_STRING, &batch_name, OPT_WRITE_BATCH, 0, 0 },
ea5164d1
WD
446 {"files-from", 0, POPT_ARG_STRING, &files_from, 0, 0, 0 },
447 {"from0", '0', POPT_ARG_NONE, &eol_nulls, 0, 0, 0},
448 {"no-implied-dirs", 0, POPT_ARG_VAL, &implied_dirs, 0, 0, 0 },
4f3e9a0f 449 {"protocol", 0, POPT_ARG_INT, &protocol_version, 0, 0, 0 },
c8d895de 450 {"checksum-seed", 0, POPT_ARG_INT, &checksum_seed, 0, 0, 0 },
4f5b0756 451#ifdef INET6
3dd22903
WD
452 {"ipv4", '4', POPT_ARG_VAL, &default_af_hint, AF_INET, 0, 0 },
453 {"ipv6", '6', POPT_ARG_VAL, &default_af_hint, AF_INET6, 0, 0 },
06963d0f 454#endif
3ac7f5d4
WD
455 /* All these options switch us into daemon-mode option-parsing. */
456 {"address", 0, POPT_ARG_STRING, 0, OPT_DAEMON, 0, 0 },
457 {"config", 0, POPT_ARG_STRING, 0, OPT_DAEMON, 0, 0 },
458 {"daemon", 0, POPT_ARG_NONE, 0, OPT_DAEMON, 0, 0 },
459 {"no-detach", 0, POPT_ARG_NONE, 0, OPT_DAEMON, 0, 0 },
3ac7f5d4
WD
460 {0,0,0,0, 0, 0, 0}
461};
462
463static void daemon_usage(enum logcode F)
464{
465 print_rsync_version(F);
466
467 rprintf(F,"\nUsage: rsync --daemon [OPTION]...\n");
468 rprintf(F," --address=ADDRESS bind to the specified address\n");
b3708acf 469 rprintf(F," --bwlimit=KBPS limit I/O bandwidth; KBytes per second\n");
3ac7f5d4
WD
470 rprintf(F," --config=FILE specify alternate rsyncd.conf file\n");
471 rprintf(F," --no-detach do not detach from the parent\n");
b3708acf 472 rprintf(F," --port=PORT listen on alternate port number\n");
1bd9db74 473 rprintf(F," -v, --verbose increase verbosity\n");
4f5b0756 474#ifdef INET6
3ac7f5d4
WD
475 rprintf(F," -4, --ipv4 prefer IPv4\n");
476 rprintf(F," -6, --ipv6 prefer IPv6\n");
477#endif
478 rprintf(F," -h, --help show this help screen\n");
479
480 rprintf(F,"\nIf you were not trying to invoke rsync as a daemon, avoid using any of the\n");
481 rprintf(F,"daemon-specific rsync options. See also the rsyncd.conf(5) man page.\n");
482}
483
484static struct poptOption long_daemon_options[] = {
485 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
486 {"address", 0, POPT_ARG_STRING, &bind_address, 0, 0, 0 },
9fb08441 487 {"bwlimit", 0, POPT_ARG_INT, &daemon_bwlimit, 0, 0, 0 },
3ac7f5d4
WD
488 {"config", 0, POPT_ARG_STRING, &config_file, 0, 0, 0 },
489 {"daemon", 0, POPT_ARG_NONE, &daemon_opt, 0, 0, 0 },
4f5b0756 490#ifdef INET6
3ac7f5d4
WD
491 {"ipv4", '4', POPT_ARG_VAL, &default_af_hint, AF_INET, 0, 0 },
492 {"ipv6", '6', POPT_ARG_VAL, &default_af_hint, AF_INET6, 0, 0 },
493#endif
494 {"no-detach", 0, POPT_ARG_NONE, &no_detach, 0, 0, 0 },
495 {"port", 0, POPT_ARG_INT, &rsync_port, 0, 0, 0 },
496 {"protocol", 0, POPT_ARG_INT, &protocol_version, 0, 0, 0 },
497 {"server", 0, POPT_ARG_NONE, &am_server, 0, 0, 0 },
1bd9db74 498 {"verbose", 'v', POPT_ARG_NONE, 0, 'v', 0, 0 },
3ac7f5d4 499 {"help", 'h', POPT_ARG_NONE, 0, 'h', 0, 0 },
ad715008 500 {0,0,0,0, 0, 0, 0}
2855f61f 501};
7a6421fa 502
06963d0f 503
e51094b7 504static char err_buf[200];
cd8185f2 505
2855f61f 506
dafe63ca
MP
507/**
508 * Store the option error message, if any, so that we can log the
509 * connection attempt (which requires parsing the options), and then
510 * show the error later on.
511 **/
cd8185f2
AT
512void option_error(void)
513{
e51094b7
WD
514 if (!err_buf[0]) {
515 strcpy(err_buf, "Error parsing options: "
516 "option may be supported on client but not on server?\n");
cd8185f2 517 }
e51094b7 518
e51094b7 519 rprintf(FERROR, RSYNC_NAME ": %s", err_buf);
cd8185f2
AT
520}
521
dafe63ca
MP
522
523/**
27ed20f7
WD
524 * Tweak the option table to disable all options that the rsyncd.conf
525 * file has told us to refuse.
dafe63ca 526 **/
27ed20f7 527static void set_refuse_options(char *bp)
cd8185f2 528{
27ed20f7 529 struct poptOption *op;
093e816c 530 char *cp, shortname[2];
d73e7f6e 531 int is_wild, found_match;
093e816c
WD
532
533 shortname[1] = '\0';
27ed20f7
WD
534
535 while (1) {
06a50542
WD
536 while (*bp == ' ') bp++;
537 if (!*bp)
538 break;
27ed20f7
WD
539 if ((cp = strchr(bp, ' ')) != NULL)
540 *cp= '\0';
093e816c 541 is_wild = strpbrk(bp, "*?[") != NULL;
d73e7f6e 542 found_match = 0;
55afbb52 543 for (op = long_options; ; op++) {
093e816c 544 *shortname = op->shortName;
d73e7f6e
WD
545 if (!op->longName && !*shortname)
546 break;
547 if ((op->longName && wildmatch(bp, op->longName))
684d7582 548 || (*shortname && wildmatch(bp, shortname))) {
e57211c5
WD
549 if (op->argInfo == POPT_ARG_VAL)
550 op->argInfo = POPT_ARG_NONE;
06a50542 551 op->val = (op - long_options) + OPT_REFUSED_BASE;
d73e7f6e 552 found_match = 1;
3671987f
WD
553 /* These flags are set to let us easily check
554 * an implied option later in the code. */
555 switch (*shortname) {
3671987f
WD
556 case 'r': case 'd': case 'l': case 'p':
557 case 't': case 'g': case 'o': case 'D':
558 refused_archive_part = op->val;
559 break;
560 case '\0':
561 if (wildmatch("delete", op->longName))
562 refused_delete = op->val;
3296f91b
WD
563 else if (wildmatch("delete-before", op->longName))
564 refused_delete_before = op->val;
3671987f
WD
565 else if (wildmatch("partial", op->longName))
566 refused_partial = op->val;
567 else if (wildmatch("progress", op->longName))
568 refused_progress = op->val;
569 break;
570 }
06a50542
WD
571 if (!is_wild)
572 break;
27ed20f7 573 }
cd8185f2 574 }
d73e7f6e
WD
575 if (!found_match) {
576 rprintf(FLOG, "No match for refuse-options string \"%s\"\n",
577 bp);
578 }
27ed20f7
WD
579 if (!cp)
580 break;
581 *cp = ' ';
582 bp = cp + 1;
cd8185f2 583 }
684d7582
WD
584
585 for (op = long_options; ; op++) {
586 *shortname = op->shortName;
587 if (!op->longName && !*shortname)
588 break;
589 if (op->val == OPT_DAEMON) {
590 if (op->argInfo == POPT_ARG_VAL)
591 op->argInfo = POPT_ARG_NONE;
592 op->val = (op - long_options) + OPT_REFUSED_BASE;
593 }
594 }
cd8185f2
AT
595}
596
597
8db7cc2c 598static int count_args(const char **argv)
2855f61f 599{
dfa32483 600 int i = 0;
2855f61f 601
8db7cc2c
WD
602 if (argv) {
603 while (argv[i] != NULL)
604 i++;
605 }
dfa32483
WD
606
607 return i;
2855f61f
MP
608}
609
610
3671987f
WD
611static void create_refuse_error(int which)
612{
613 /* The "which" value is the index + OPT_REFUSED_BASE. */
614 struct poptOption *op = &long_options[which - OPT_REFUSED_BASE];
615 int n = snprintf(err_buf, sizeof err_buf,
616 "The server is configured to refuse --%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}
623
624
dafe63ca
MP
625/**
626 * Process command line arguments. Called on both local and remote.
627 *
628 * @retval 1 if all options are OK; with globals set to appropriate
629 * values
630 *
631 * @retval 0 on error, with err_buf containing an explanation
632 **/
2855f61f 633int parse_arguments(int *argc, const char ***argv, int frommain)
7a6421fa 634{
d853783f 635 int opt;
cd8185f2 636 char *ref = lp_refuse_options(module_id);
7be73df4 637 const char *arg;
dfa32483 638 poptContext pc;
d853783f 639
27ed20f7
WD
640 if (ref && *ref)
641 set_refuse_options(ref);
642
dfa32483 643 /* TODO: Call poptReadDefaultConfig; handle errors. */
cd8185f2 644
dfa32483
WD
645 /* The context leaks in case of an error, but if there's a
646 * problem we always exit anyhow. */
647 pc = poptGetContext(RSYNC_NAME, *argc, *argv, long_options, 0);
9fb08441 648 poptReadDefaultConfig(pc, 0);
2855f61f
MP
649
650 while ((opt = poptGetNextOpt(pc)) != -1) {
dfa32483
WD
651 /* most options are handled automatically by popt;
652 * only special cases are returned and listed here. */
2855f61f 653
d853783f
AT
654 switch (opt) {
655 case OPT_VERSION:
dfa32483 656 print_rsync_version(FINFO);
d853783f 657 exit_cleanup(0);
dfa32483 658
3ac7f5d4
WD
659 case OPT_DAEMON:
660 if (am_daemon) {
661 strcpy(err_buf, "Attempt to hack rsync thwarted!\n");
662 return 0;
663 }
664 poptFreeContext(pc);
665 pc = poptGetContext(RSYNC_NAME, *argc, *argv,
666 long_daemon_options, 0);
667 while ((opt = poptGetNextOpt(pc)) != -1) {
668 switch (opt) {
669 case 'h':
670 daemon_usage(FINFO);
671 exit_cleanup(0);
672
1bd9db74
WD
673 case 'v':
674 verbose++;
675 break;
676
3ac7f5d4
WD
677 default:
678 rprintf(FERROR,
679 "rsync: %s: %s (in daemon mode)\n",
680 poptBadOption(pc, POPT_BADOPTION_NOALIAS),
681 poptStrerror(opt));
682 goto daemon_error;
683 }
684 }
685 if (!daemon_opt) {
686 rprintf(FERROR, "Daemon option(s) used without --daemon.\n");
687 daemon_error:
688 rprintf(FERROR,
689 "(Type \"rsync --daemon --help\" for assistance with daemon mode.)\n");
690 exit_cleanup(RERR_SYNTAX);
691 }
692 *argv = poptGetArgs(pc);
693 *argc = count_args(*argv);
694 daemon_opt = 0;
695 am_daemon = 1;
696 return 1;
697
5b56cc19 698 case OPT_MODIFY_WINDOW:
dfa32483
WD
699 /* The value has already been set by popt, but
700 * we need to remember that we're using a
701 * non-default setting. */
5b56cc19
AT
702 modify_window_set = 1;
703 break;
1de50993 704
aa4d3b4c 705 case OPT_FILTER:
3a5e9224 706 parse_rule(&filter_list, poptGetOptArg(pc), 0, 0);
d853783f
AT
707 break;
708
aa4d3b4c 709 case OPT_EXCLUDE:
3a5e9224 710 parse_rule(&filter_list, poptGetOptArg(pc),
0a68f869 711 0, XFLG_OLD_PREFIXES);
aa4d3b4c
WD
712 break;
713
d853783f 714 case OPT_INCLUDE:
3a5e9224 715 parse_rule(&filter_list, poptGetOptArg(pc),
0a68f869 716 MATCHFLG_INCLUDE, XFLG_OLD_PREFIXES);
d853783f
AT
717 break;
718
719 case OPT_EXCLUDE_FROM:
93695764 720 case OPT_INCLUDE_FROM:
7be73df4 721 arg = poptGetOptArg(pc);
ba3db479
WD
722 if (sanitize_paths)
723 arg = sanitize_path(NULL, arg, NULL, 0);
7842418b 724 if (server_filter_list.head) {
ba3db479 725 char *cp = (char *)arg;
3671987f
WD
726 if (!*cp)
727 goto options_rejected;
ba3db479 728 clean_fname(cp, 1);
7842418b 729 if (check_filter(&server_filter_list, cp, 0) < 0)
ba3db479
WD
730 goto options_rejected;
731 }
3a5e9224
WD
732 parse_filter_file(&filter_list, arg,
733 opt == OPT_INCLUDE_FROM ? MATCHFLG_INCLUDE : 0,
734 XFLG_FATAL_ERRORS | XFLG_OLD_PREFIXES);
93695764
DD
735 break;
736
d853783f
AT
737 case 'h':
738 usage(FINFO);
739 exit_cleanup(0);
740
d853783f
AT
741 case 'v':
742 verbose++;
743 break;
7a6421fa 744
b86f0cef 745 case 'q':
f98c60bf
WD
746 if (frommain)
747 quiet++;
b86f0cef
DD
748 break;
749
d853783f
AT
750 case OPT_SENDER:
751 if (!am_server) {
752 usage(FERROR);
65417579 753 exit_cleanup(RERR_SYNTAX);
d853783f
AT
754 }
755 am_sender = 1;
756 break;
757
aa4d3b4c
WD
758 case 'F':
759 switch (++F_option_cnt) {
760 case 1:
3a5e9224 761 parse_rule(&filter_list,": /.rsync-filter",0,0);
aa4d3b4c
WD
762 break;
763 case 2:
3a5e9224 764 parse_rule(&filter_list,"- .rsync-filter",0,0);
aa4d3b4c
WD
765 break;
766 }
767 break;
768
d9fcc198 769 case 'P':
3671987f
WD
770 if (refused_partial || refused_progress) {
771 create_refuse_error(refused_partial
772 ? refused_partial : refused_progress);
773 return 0;
774 }
d9fcc198
AT
775 do_progress = 1;
776 keep_partial = 1;
777 break;
778
088aac85 779 case OPT_WRITE_BATCH:
9b3318b0 780 /* batch_name is already set */
088aac85
DD
781 write_batch = 1;
782 break;
783
76f79ba7 784 case OPT_READ_BATCH:
9b3318b0 785 /* batch_name is already set */
6902ed17
MP
786 read_batch = 1;
787 break;
ea5164d1 788
7d5acf1d 789 case OPT_MAX_SIZE:
cc80022e 790 for (arg = max_size_arg; isdigit(*(uchar*)arg); arg++) {}
7d5acf1d 791 if (*arg == '.')
cc80022e 792 for (arg++; isdigit(*(uchar*)arg); arg++) {}
7d5acf1d
WD
793 switch (*arg) {
794 case 'k': case 'K':
795 max_size = atof(max_size_arg) * 1024;
796 break;
797 case 'm': case 'M':
798 max_size = atof(max_size_arg) * 1024*1024;
799 break;
800 case 'g': case 'G':
801 max_size = atof(max_size_arg) * 1024*1024*1024;
802 break;
803 case '\0':
804 max_size = atof(max_size_arg);
805 break;
806 default:
807 max_size = 0;
808 break;
809 }
810 if (max_size <= 0) {
e012f858 811 snprintf(err_buf, sizeof err_buf,
7d5acf1d
WD
812 "--max-size value is invalid: %s\n",
813 max_size_arg);
e012f858 814 return 0;
7d5acf1d
WD
815 }
816 break;
817
99218d82
WD
818 case OPT_TIMEOUT:
819 if (io_timeout && io_timeout < select_timeout)
820 select_timeout = io_timeout;
821 break;
822
59c95e42 823 case OPT_LINK_DEST:
4f5b0756 824#ifdef HAVE_LINK
59c95e42 825 link_dest = 1;
e012f858
WD
826 dest_option = "--link-dest";
827 goto set_dest_dir;
59c95e42 828#else
d175d7e1 829 snprintf(err_buf, sizeof err_buf,
dfa32483 830 "hard links are not supported on this %s\n",
59c95e42 831 am_server ? "server" : "client");
59c95e42
DD
832 return 0;
833#endif
834
e012f858
WD
835 case OPT_COPY_DEST:
836 copy_dest = 1;
837 dest_option = "--copy-dest";
838 goto set_dest_dir;
839
840 case OPT_COMPARE_DEST:
841 compare_dest = 1;
842 dest_option = "--compare-dest";
843 set_dest_dir:
3b26bba0 844 if (basis_dir_cnt >= MAX_BASIS_DIRS) {
e012f858
WD
845 snprintf(err_buf, sizeof err_buf,
846 "ERROR: at most %d %s args may be specified\n",
847 MAX_BASIS_DIRS, dest_option);
848 return 0;
849 }
850 arg = poptGetOptArg(pc);
851 if (sanitize_paths)
852 arg = sanitize_path(NULL, arg, NULL, 0);
853 basis_dir[basis_dir_cnt++] = (char *)arg;
854 break;
855
d853783f 856 default:
55afbb52 857 /* A large opt value means that set_refuse_options()
3671987f 858 * turned this option off. */
c67d1386 859 if (opt >= OPT_REFUSED_BASE) {
3671987f
WD
860 create_refuse_error(opt);
861 return 0;
27ed20f7 862 }
3671987f
WD
863 snprintf(err_buf, sizeof err_buf, "%s%s: %s\n",
864 am_server ? "on remote machine: " : "",
865 poptBadOption(pc, POPT_BADOPTION_NOALIAS),
866 poptStrerror(opt));
dfa32483 867 return 0;
d853783f 868 }
7a6421fa 869 }
2855f61f 870
f1d5ba40
WD
871 if (am_sender < 0)
872 am_sender = 0;
873
4f5b0756 874#ifndef SUPPORT_LINKS
54e87b4b 875 if (preserve_links && !am_sender) {
e1add893
WD
876 snprintf(err_buf, sizeof err_buf,
877 "symlinks are not supported on this %s\n",
878 am_server ? "server" : "client");
e1add893
WD
879 return 0;
880 }
881#endif
882
4f5b0756 883#ifndef SUPPORT_HARD_LINKS
e1add893
WD
884 if (preserve_hard_links) {
885 snprintf(err_buf, sizeof err_buf,
886 "hard links are not supported on this %s\n",
887 am_server ? "server" : "client");
e1add893
WD
888 return 0;
889 }
890#endif
891
088aac85 892 if (write_batch && read_batch) {
c3ea0990 893 snprintf(err_buf, sizeof err_buf,
36119893 894 "--write-batch and --read-batch can not be used together\n");
c3ea0990 895 return 0;
088aac85 896 }
94327ff0
WD
897 if (write_batch || read_batch) {
898 if (dry_run) {
c3ea0990 899 snprintf(err_buf, sizeof err_buf,
94327ff0
WD
900 "--%s-batch cannot be used with --dry_run (-n)\n",
901 write_batch ? "write" : "read");
c3ea0990 902 return 0;
94327ff0
WD
903 }
904 if (am_server) {
905 rprintf(FINFO,
906 "ignoring --%s-batch option sent to server\n",
907 write_batch ? "write" : "read");
908 /* We don't actually exit_cleanup(), so that we can
909 * still service older version clients that still send
910 * batch args to server. */
911 read_batch = write_batch = 0;
912 batch_name = NULL;
913 }
b9f592fb 914 }
36119893 915 if (read_batch && files_from) {
c3ea0990 916 snprintf(err_buf, sizeof err_buf,
36119893 917 "--read-batch cannot be used with --files-from\n");
c3ea0990 918 return 0;
36119893 919 }
9b3318b0 920 if (batch_name && strlen(batch_name) > MAX_BATCH_NAME_LEN) {
c3ea0990 921 snprintf(err_buf, sizeof err_buf,
9b3318b0
WD
922 "the batch-file name must be %d characters or less.\n",
923 MAX_BATCH_NAME_LEN);
c3ea0990 924 return 0;
beb93684 925 }
088aac85 926
ce58b1b4 927 if (tmpdir && strlen(tmpdir) >= MAXPATHLEN - 10) {
c3ea0990
WD
928 snprintf(err_buf, sizeof err_buf,
929 "the --temp-dir path is WAY too long.\n");
930 return 0;
ce58b1b4
WD
931 }
932
e012f858
WD
933 if (compare_dest + copy_dest + link_dest > 1) {
934 snprintf(err_buf, sizeof err_buf,
935 "You may not mix --compare-dest, --copy-dest, and --link-dest.\n");
936 return 0;
937 }
938
dfa32483 939 if (archive_mode) {
3671987f
WD
940 if (refused_archive_part) {
941 create_refuse_error(refused_archive_part);
942 return 0;
943 }
ea5164d1 944 if (!files_from)
51d48398 945 recurse = -1; /* infinite recursion */
4f5b0756 946#ifdef SUPPORT_LINKS
dfa32483
WD
947 preserve_links = 1;
948#endif
949 preserve_perms = 1;
950 preserve_times = 1;
951 preserve_gid = 1;
952 preserve_uid = 1;
953 preserve_devices = 1;
954 }
51d48398
WD
955
956 if (recurse || list_only || files_from)
65e4cda0 957 xfer_dirs |= 1;
dfa32483 958
ea5164d1
WD
959 if (relative_paths < 0)
960 relative_paths = files_from? 1 : 0;
961
c6eb7fad 962 if (!!delete_before + delete_during + delete_after > 1) {
3359acb8 963 snprintf(err_buf, sizeof err_buf,
c6eb7fad 964 "You may not combine multiple --delete-WHEN options.\n");
3359acb8
WD
965 return 0;
966 }
78fc60cd
WD
967 if (!recurse) {
968 delete_before = delete_during = delete_after = 0;
969 delete_mode = delete_excluded = 0;
970 } else if (delete_before || delete_during || delete_after)
51d48398 971 delete_mode = 1;
3296f91b
WD
972 else if (delete_mode || delete_excluded) {
973 if (refused_delete_before) {
974 create_refuse_error(refused_delete_before);
975 return 0;
976 }
3359acb8 977 delete_mode = delete_before = 1;
3296f91b 978 }
51d48398 979
3671987f
WD
980 if (delete_mode && refused_delete) {
981 create_refuse_error(refused_delete);
982 return 0;
983 }
984
07c6ae7d
WD
985 if (remove_sent_files) {
986 /* We only want to infer this refusal of --remove-sent-files
987 * via the refusal of "delete", not any of the "delete-FOO"
988 * options. */
989 if (refused_delete && am_sender) {
990 create_refuse_error(refused_delete);
991 return 0;
992 }
993 need_messages_from_generator = 1;
994 }
995
7be73df4 996 *argv = poptGetArgs(pc);
8db7cc2c 997 *argc = count_args(*argv);
7be73df4
WD
998
999 if (sanitize_paths) {
1000 int i;
1001 for (i = *argc; i-- > 0; )
10796f4b 1002 (*argv)[i] = sanitize_path(NULL, (*argv)[i], "", 0);
7be73df4 1003 if (tmpdir)
10796f4b 1004 tmpdir = sanitize_path(NULL, tmpdir, NULL, 0);
a7260c40 1005 if (partial_dir)
10796f4b 1006 partial_dir = sanitize_path(NULL, partial_dir, NULL, 0);
7be73df4 1007 if (backup_dir)
10796f4b 1008 backup_dir = sanitize_path(NULL, backup_dir, NULL, 0);
7be73df4 1009 if (files_from)
10796f4b 1010 files_from = sanitize_path(NULL, files_from, NULL, 0);
7be73df4 1011 }
7842418b
WD
1012 if (server_filter_list.head && !am_sender) {
1013 struct filter_list_struct *elp = &server_filter_list;
e012f858 1014 int i;
c3ea0990 1015 if (tmpdir) {
3671987f
WD
1016 if (!*tmpdir)
1017 goto options_rejected;
58b1999e 1018 clean_fname(tmpdir, 1);
7842418b 1019 if (check_filter(elp, tmpdir, 1) < 0)
c3ea0990
WD
1020 goto options_rejected;
1021 }
3671987f 1022 if (partial_dir && *partial_dir) {
58b1999e 1023 clean_fname(partial_dir, 1);
7842418b 1024 if (check_filter(elp, partial_dir, 1) < 0)
c3ea0990
WD
1025 goto options_rejected;
1026 }
e012f858 1027 for (i = 0; i < basis_dir_cnt; i++) {
3671987f
WD
1028 if (!*basis_dir[i])
1029 goto options_rejected;
e012f858 1030 clean_fname(basis_dir[i], 1);
7842418b 1031 if (check_filter(elp, basis_dir[i], 1) < 0)
c3ea0990
WD
1032 goto options_rejected;
1033 }
1034 if (backup_dir) {
3671987f
WD
1035 if (!*backup_dir)
1036 goto options_rejected;
58b1999e 1037 clean_fname(backup_dir, 1);
7842418b 1038 if (check_filter(elp, backup_dir, 1) < 0)
c3ea0990
WD
1039 goto options_rejected;
1040 }
1041 }
7842418b 1042 if (server_filter_list.head && files_from) {
3671987f
WD
1043 if (!*files_from)
1044 goto options_rejected;
58b1999e 1045 clean_fname(files_from, 1);
7842418b 1046 if (check_filter(&server_filter_list, files_from, 0) < 0) {
c3ea0990
WD
1047 options_rejected:
1048 snprintf(err_buf, sizeof err_buf,
1049 "Your options have been rejected by the server.\n");
1050 return 0;
1051 }
1052 }
7be73df4 1053
d175d7e1 1054 if (!backup_suffix)
e0391f81 1055 backup_suffix = backup_dir ? "" : BACKUP_SUFFIX;
d175d7e1 1056 backup_suffix_len = strlen(backup_suffix);
80ddadb7 1057 if (strchr(backup_suffix, '/') != NULL) {
c3ea0990
WD
1058 snprintf(err_buf, sizeof err_buf,
1059 "--suffix cannot contain slashes: %s\n",
80ddadb7 1060 backup_suffix);
c3ea0990 1061 return 0;
80ddadb7 1062 }
e0391f81
WD
1063 if (backup_dir) {
1064 backup_dir_len = strlcpy(backup_dir_buf, backup_dir, sizeof backup_dir_buf);
1065 backup_dir_remainder = sizeof backup_dir_buf - backup_dir_len;
1066 if (backup_dir_remainder < 32) {
c3ea0990
WD
1067 snprintf(err_buf, sizeof err_buf,
1068 "the --backup-dir path is WAY too long.\n");
1069 return 0;
e0391f81
WD
1070 }
1071 if (backup_dir_buf[backup_dir_len - 1] != '/') {
1072 backup_dir_buf[backup_dir_len++] = '/';
1073 backup_dir_buf[backup_dir_len] = '\0';
1074 }
4875d6b6
WD
1075 if (verbose > 1 && !am_sender) {
1076 rprintf(FINFO, "backup_dir is %s\n",
1077 safe_fname(backup_dir_buf));
1078 }
8dcf9335 1079 } else if (!backup_suffix_len && (!am_server || !am_sender)) {
c3ea0990 1080 snprintf(err_buf, sizeof err_buf,
d175d7e1 1081 "--suffix cannot be a null string without --backup-dir\n");
c3ea0990 1082 return 0;
d175d7e1
WD
1083 }
1084
e7651884
WD
1085 if (log_format) {
1086 if (strstr(log_format, "%i") != NULL)
684d7582 1087 log_format_has_i = 1;
e7651884
WD
1088 if (strstr(log_format, "%b") == NULL
1089 && strstr(log_format, "%c") == NULL)
1090 log_before_transfer = !am_server;
1091 } else if (itemize_changes) {
1092 log_format = "%i %n%L";
684d7582 1093 log_format_has_i = 1;
e7651884
WD
1094 log_before_transfer = !am_server;
1095 }
87383697
WD
1096
1097 if ((do_progress || dry_run) && !verbose && !log_before_transfer
702cd15c 1098 && !am_server)
e2559dbe 1099 verbose = 1;
87383697
WD
1100
1101 if (verbose && !log_format) {
1102 log_format = "%n%L";
1103 log_before_transfer = !am_server;
3671987f 1104 }
684d7582
WD
1105 if (log_format_has_i
1106 || (log_format && strstr(log_format, "%o") != NULL))
5c5e1598 1107 log_format_has_o_or_i = 1;
e2559dbe 1108
9fb08441
WD
1109 if (daemon_bwlimit && (!bwlimit || bwlimit > daemon_bwlimit))
1110 bwlimit = daemon_bwlimit;
3c74c3a3
WD
1111 if (bwlimit) {
1112 bwlimit_writemax = (size_t)bwlimit * 128;
1113 if (bwlimit_writemax < 512)
1114 bwlimit_writemax = 512;
1115 }
1116
f06e7082 1117 if (delay_updates && !partial_dir)
3671987f 1118 partial_dir = partialdir_for_delayupdate;
f06e7082 1119
a3221d2a 1120 if (inplace) {
4f5b0756 1121#ifdef HAVE_FTRUNCATE
a7260c40
WD
1122 if (partial_dir) {
1123 snprintf(err_buf, sizeof err_buf,
f06e7082
WD
1124 "--inplace cannot be used with --%s\n",
1125 delay_updates ? "delay-updates" : "partial-dir");
a7260c40
WD
1126 return 0;
1127 }
3671987f
WD
1128 /* --inplace implies --partial for refusal purposes, but we
1129 * clear the keep_partial flag for internal logic purposes. */
1130 if (refused_partial) {
1131 create_refuse_error(refused_partial);
1132 return 0;
1133 }
a3221d2a 1134 keep_partial = 0;
ded4daf0
WD
1135#else
1136 snprintf(err_buf, sizeof err_buf,
1137 "--inplace is not supported on this %s\n",
1138 am_server ? "server" : "client");
1139 return 0;
1140#endif
075aa18f 1141 } else {
3671987f
WD
1142 if (keep_partial && !partial_dir) {
1143 if ((arg = getenv("RSYNC_PARTIAL_DIR")) != NULL && *arg)
1144 partial_dir = strdup(arg);
1145 }
075aa18f 1146 if (partial_dir) {
3671987f
WD
1147 if (*partial_dir)
1148 clean_fname(partial_dir, 1);
075aa18f
WD
1149 if (!*partial_dir || strcmp(partial_dir, ".") == 0)
1150 partial_dir = NULL;
13791b1e 1151 else if (*partial_dir != '/') {
3a5e9224 1152 parse_rule(&filter_list, partial_dir,
0a68f869 1153 MATCHFLG_NO_PREFIXES|MATCHFLG_DIRECTORY, 0);
13791b1e 1154 }
3671987f
WD
1155 if (!partial_dir && refused_partial) {
1156 create_refuse_error(refused_partial);
1157 return 0;
1158 }
075aa18f
WD
1159 keep_partial = 1;
1160 }
a3221d2a
WD
1161 }
1162
ea5164d1
WD
1163 if (files_from) {
1164 char *colon;
c3ea0990 1165 if (*argc > 2 || (!am_daemon && *argc == 1)) {
ea5164d1
WD
1166 usage(FERROR);
1167 exit_cleanup(RERR_SYNTAX);
1168 }
63596e1c 1169 if (strcmp(files_from, "-") == 0) {
ea5164d1 1170 filesfrom_fd = 0;
63596e1c
WD
1171 if (am_server)
1172 remote_filesfrom_file = "-";
1173 }
ea5164d1
WD
1174 else if ((colon = find_colon(files_from)) != 0) {
1175 if (am_server) {
1176 usage(FERROR);
1177 exit_cleanup(RERR_SYNTAX);
1178 }
1179 remote_filesfrom_file = colon+1 + (colon[1] == ':');
1180 if (strcmp(remote_filesfrom_file, "-") == 0) {
c3ea0990
WD
1181 snprintf(err_buf, sizeof err_buf,
1182 "Invalid --files-from remote filename\n");
1183 return 0;
ea5164d1
WD
1184 }
1185 } else {
ea5164d1
WD
1186 filesfrom_fd = open(files_from, O_RDONLY|O_BINARY);
1187 if (filesfrom_fd < 0) {
c3ea0990
WD
1188 snprintf(err_buf, sizeof err_buf,
1189 "failed to open files-from file %s: %s\n",
1190 files_from, strerror(errno));
1191 return 0;
ea5164d1
WD
1192 }
1193 }
1194 }
1195
b11ed3b1 1196 return 1;
7a6421fa
AT
1197}
1198
1199
dafe63ca
MP
1200/**
1201 * Construct a filtered list of options to pass through from the
1202 * client to the server.
1203 *
1204 * This involves setting options that will tell the server how to
1205 * behave, and also filtering out options that are processed only
1206 * locally.
1207 **/
7a6421fa
AT
1208void server_options(char **args,int *argc)
1209{
e012f858 1210 static char argstr[50+MAX_BASIS_DIRS*2];
d853783f 1211 int ac = *argc;
f98c60bf 1212 char *arg;
ef5d23eb 1213
d853783f
AT
1214 int i, x;
1215
93689aa5
DD
1216 if (blocking_io == -1)
1217 blocking_io = 0;
1218
d853783f
AT
1219 args[ac++] = "--server";
1220
1312d9fc
WD
1221 if (daemon_over_rsh) {
1222 args[ac++] = "--daemon";
1223 *argc = ac;
1224 /* if we're passing --daemon, we're done */
1225 return;
1226 }
1227
d853783f
AT
1228 if (!am_sender)
1229 args[ac++] = "--sender";
1230
1231 x = 1;
1232 argstr[0] = '-';
f98c60bf 1233 for (i = 0; i < verbose; i++)
d853783f 1234 argstr[x++] = 'v';
f0b36a48 1235
b86f0cef 1236 /* the -q option is intentionally left out */
d853783f
AT
1237 if (make_backups)
1238 argstr[x++] = 'b';
1239 if (update_only)
1240 argstr[x++] = 'u';
1241 if (dry_run)
1242 argstr[x++] = 'n';
1243 if (preserve_links)
1244 argstr[x++] = 'l';
1245 if (copy_links)
1246 argstr[x++] = 'L';
65e4cda0 1247 if (xfer_dirs > 1)
5454d22a 1248 argstr[x++] = 'd';
716e73d4
WD
1249 if (keep_dirlinks && am_sender)
1250 argstr[x++] = 'K';
1bfbf40b 1251
dfa32483 1252 if (whole_file > 0)
d853783f 1253 argstr[x++] = 'W';
bceec82f
MP
1254 /* We don't need to send --no-whole-file, because it's the
1255 * default for remote transfers, and in any case old versions
1256 * of rsync will not understand it. */
dfa32483 1257
d853783f
AT
1258 if (preserve_hard_links)
1259 argstr[x++] = 'H';
1260 if (preserve_uid)
1261 argstr[x++] = 'o';
1262 if (preserve_gid)
1263 argstr[x++] = 'g';
1264 if (preserve_devices)
1265 argstr[x++] = 'D';
1266 if (preserve_times)
1267 argstr[x++] = 't';
20fb7b91
WD
1268 if (omit_dir_times && am_sender)
1269 argstr[x++] = 'O';
d853783f
AT
1270 if (preserve_perms)
1271 argstr[x++] = 'p';
51d48398 1272 if (recurse < 0)
d853783f
AT
1273 argstr[x++] = 'r';
1274 if (always_checksum)
1275 argstr[x++] = 'c';
1276 if (cvs_exclude)
1277 argstr[x++] = 'C';
1278 if (ignore_times)
1279 argstr[x++] = 'I';
1280 if (relative_paths)
1281 argstr[x++] = 'R';
1282 if (one_file_system)
1283 argstr[x++] = 'x';
1284 if (sparse_files)
1285 argstr[x++] = 'S';
1286 if (do_compression)
1287 argstr[x++] = 'z';
f0b36a48 1288
51d48398
WD
1289 /* This is a complete hack - blame Rusty. FIXME!
1290 * This hack is only needed for older rsync versions that
1291 * don't understand the --list-only option. */
1292 if (list_only == 1 && recurse >= 0)
f0b36a48
AT
1293 argstr[x++] = 'r';
1294
d853783f
AT
1295 argstr[x] = 0;
1296
f98c60bf
WD
1297 if (x != 1)
1298 args[ac++] = argstr;
d853783f 1299
51d48398
WD
1300 if (list_only > 1)
1301 args[ac++] = "--list-only";
1302
5c5e1598
WD
1303 /* The server side doesn't use our log-format, but in certain
1304 * circumstances they need to know a little about the option. */
684d7582
WD
1305 if (log_format && am_sender) {
1306 if (log_format_has_i)
1307 args[ac++] = "--log-format=%i";
1308 else if (log_format_has_o_or_i)
5c5e1598
WD
1309 args[ac++] = "--log-format=%o";
1310 else if (!verbose)
1311 args[ac++] = "--log-format=X";
1312 }
1f30a674 1313
195bd906 1314 if (block_size) {
a06b419d 1315 if (asprintf(&arg, "-B%lu", block_size) < 0)
f98c60bf
WD
1316 goto oom;
1317 args[ac++] = arg;
dfa32483 1318 }
d853783f 1319
0b73ca12 1320 if (max_delete && am_sender) {
f98c60bf
WD
1321 if (asprintf(&arg, "--max-delete=%d", max_delete) < 0)
1322 goto oom;
1323 args[ac++] = arg;
dfa32483
WD
1324 }
1325
7d5acf1d
WD
1326 if (max_size && am_sender) {
1327 args[ac++] = "--max-size";
1328 args[ac++] = max_size_arg;
1329 }
1330
d853783f 1331 if (io_timeout) {
f98c60bf
WD
1332 if (asprintf(&arg, "--timeout=%d", io_timeout) < 0)
1333 goto oom;
1334 args[ac++] = arg;
dfa32483 1335 }
d853783f 1336
ef5d23eb 1337 if (bwlimit) {
f98c60bf
WD
1338 if (asprintf(&arg, "--bwlimit=%d", bwlimit) < 0)
1339 goto oom;
1340 args[ac++] = arg;
ef5d23eb
DD
1341 }
1342
d175d7e1
WD
1343 if (backup_dir) {
1344 args[ac++] = "--backup-dir";
1345 args[ac++] = backup_dir;
1346 }
1347
1348 /* Only send --suffix if it specifies a non-default value. */
f98c60bf 1349 if (strcmp(backup_suffix, backup_dir ? "" : BACKUP_SUFFIX) != 0) {
191e40da 1350 /* We use the following syntax to avoid weirdness with '~'. */
f98c60bf
WD
1351 if (asprintf(&arg, "--suffix=%s", backup_suffix) < 0)
1352 goto oom;
1353 args[ac++] = arg;
d853783f
AT
1354 }
1355
06a50542
WD
1356 if (am_sender) {
1357 if (delete_excluded)
1358 args[ac++] = "--delete-excluded";
c6eb7fad 1359 else if (delete_before == 1 || delete_after)
06a50542 1360 args[ac++] = "--delete";
57f74bd1 1361 if (delete_before > 1)
c6eb7fad 1362 args[ac++] = "--delete-before";
3359acb8
WD
1363 if (delete_during)
1364 args[ac++] = "--delete-during";
06a50542
WD
1365 if (delete_after)
1366 args[ac++] = "--delete-after";
06a50542
WD
1367 if (force_delete)
1368 args[ac++] = "--force";
1369 }
b33b791e 1370
f83f0548
AT
1371 if (size_only)
1372 args[ac++] = "--size-only";
1373
5b56cc19 1374 if (modify_window_set) {
f98c60bf
WD
1375 if (asprintf(&arg, "--modify-window=%d", modify_window) < 0)
1376 goto oom;
1377 args[ac++] = arg;
5b56cc19
AT
1378 }
1379
c8d895de 1380 if (checksum_seed) {
221ddb94 1381 if (asprintf(&arg, "--checksum-seed=%d", checksum_seed) < 0)
c8d895de
WD
1382 goto oom;
1383 args[ac++] = arg;
1384 }
1385
a7260c40 1386 if (partial_dir && am_sender) {
3671987f
WD
1387 if (partial_dir != partialdir_for_delayupdate) {
1388 args[ac++] = "--partial-dir";
1389 args[ac++] = partial_dir;
1390 }
f06e7082
WD
1391 if (delay_updates)
1392 args[ac++] = "--delay-updates";
a7260c40 1393 } else if (keep_partial)
d853783f
AT
1394 args[ac++] = "--partial";
1395
ef55c686
AT
1396 if (ignore_errors)
1397 args[ac++] = "--ignore-errors";
1398
b5313607
DD
1399 if (copy_unsafe_links)
1400 args[ac++] = "--copy-unsafe-links";
1401
d853783f
AT
1402 if (safe_symlinks)
1403 args[ac++] = "--safe-links";
1404
1405 if (numeric_ids)
1406 args[ac++] = "--numeric-ids";
1407
0b73ca12 1408 if (only_existing && am_sender)
1347d512
AT
1409 args[ac++] = "--existing";
1410
dfa32483 1411 if (opt_ignore_existing && am_sender)
3d6feada
MP
1412 args[ac++] = "--ignore-existing";
1413
a3221d2a
WD
1414 if (inplace)
1415 args[ac++] = "--inplace";
1416
d853783f
AT
1417 if (tmpdir) {
1418 args[ac++] = "--temp-dir";
1419 args[ac++] = tmpdir;
1420 }
1421
e012f858 1422 if (basis_dir[0] && am_sender) {
375a4556
DD
1423 /* the server only needs this option if it is not the sender,
1424 * and it may be an older version that doesn't know this
1425 * option, so don't send it if client is the sender.
1426 */
e012f858
WD
1427 int i;
1428 for (i = 0; i < basis_dir_cnt; i++) {
1429 args[ac++] = dest_option;
1430 args[ac++] = basis_dir[i];
1431 }
375a4556
DD
1432 }
1433
ea5164d1
WD
1434 if (files_from && (!am_sender || remote_filesfrom_file)) {
1435 if (remote_filesfrom_file) {
1436 args[ac++] = "--files-from";
1437 args[ac++] = remote_filesfrom_file;
1438 if (eol_nulls)
1439 args[ac++] = "--from0";
1440 } else {
1441 args[ac++] = "--files-from=-";
1442 args[ac++] = "--from0";
1443 }
c0ab28d1
WD
1444 if (!relative_paths)
1445 args[ac++] = "--no-relative";
ea5164d1 1446 }
c72f5bd9 1447 if (!implied_dirs && !am_sender)
3a90ea0a 1448 args[ac++] = "--no-implied-dirs";
ea5164d1 1449
c4ed1487
WD
1450 if (fuzzy_basis && am_sender)
1451 args[ac++] = "--fuzzy";
1452
07c6ae7d
WD
1453 if (remove_sent_files)
1454 args[ac++] = "--remove-sent-files";
1455
d853783f 1456 *argc = ac;
f98c60bf
WD
1457 return;
1458
1459 oom:
1460 out_of_memory("server_options");
7a6421fa
AT
1461}
1462
ea5164d1
WD
1463/**
1464 * Return the position of a ':' IF it is not part of a filename (i.e. as
1465 * long as it doesn't occur after a slash.
1466 */
1467char *find_colon(char *s)
1468{
1469 char *p, *p2;
1470
1471 p = strchr(s,':');
f98c60bf
WD
1472 if (!p)
1473 return NULL;
ea5164d1
WD
1474
1475 /* now check to see if there is a / in the string before the : - if there is then
1476 discard the colon on the assumption that the : is part of a filename */
1477 p2 = strchr(s,'/');
f98c60bf
WD
1478 if (p2 && p2 < p)
1479 return NULL;
ea5164d1
WD
1480
1481 return p;
1482}