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