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