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