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