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