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