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