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