Mention recent changes.
[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;
7be73df4 26extern char curr_dir[MAXPATHLEN];
bf6dcd17 27extern struct exclude_list_struct exclude_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;
51int update_only = 0;
52int cvs_exclude = 0;
a5c11139
WD
53int dry_run = 0;
54int local_server = 0;
55int ignore_times = 0;
56int delete_mode = 0;
57int delete_excluded = 0;
58int one_file_system = 0;
4f3e9a0f 59int protocol_version = PROTOCOL_VERSION;
a5c11139
WD
60int sparse_files = 0;
61int do_compression = 0;
62int am_root = 0;
63int orig_umask = 0;
ea5164d1
WD
64int relative_paths = -1;
65int implied_dirs = 1;
7a6421fa
AT
66int numeric_ids = 0;
67int force_delete = 0;
68int io_timeout = 0;
7a6421fa
AT
69int read_only = 0;
70int module_id = -1;
71int am_server = 0;
30ce7e8a 72int am_sender = 0;
4337c8f8 73int am_generator = 0;
ea5164d1
WD
74char *files_from = NULL;
75int filesfrom_fd = -1;
76char *remote_filesfrom_file = NULL;
77int eol_nulls = 0;
7a6421fa 78int recurse = 0;
1312d9fc
WD
79int am_daemon = 0;
80int daemon_over_rsh = 0;
a5c11139
WD
81int do_stats = 0;
82int do_progress = 0;
83int keep_partial = 0;
84int safe_symlinks = 0;
85int copy_unsafe_links = 0;
86int size_only = 0;
87int bwlimit = 0;
3c74c3a3 88size_t bwlimit_writemax = 0;
a5c11139
WD
89int delete_after = 0;
90int only_existing = 0;
91int opt_ignore_existing = 0;
92int max_delete = 0;
93int ignore_errors = 0;
94int modify_window = 0;
95int blocking_io = -1;
2289bf64 96int checksum_seed = 0;
da9d12f5 97unsigned int block_size = 0;
7a6421fa 98
b35d0d8e 99
13e29995 100/** Network address family. **/
6ab6d4bf 101#ifdef INET6
13e29995 102int default_af_hint = 0; /* Any protocol */
6ab6d4bf 103#else
13e29995 104int default_af_hint = AF_INET; /* Must use IPv4 */
6ab6d4bf 105#endif
06963d0f 106
13e29995
MP
107/** Do not go into the background when run as --daemon. Good
108 * for debugging and required for running as a service on W32,
109 * or under Unix process-monitors. **/
110int no_detach = 0;
111
088aac85
DD
112int write_batch = 0;
113int read_batch = 0;
d175d7e1
WD
114int backup_dir_len = 0;
115int backup_suffix_len;
e0391f81 116unsigned int backup_dir_remainder;
6902ed17 117
d175d7e1 118char *backup_suffix = NULL;
7a6421fa 119char *tmpdir = NULL;
375a4556 120char *compare_dest = NULL;
30e8c8e1 121char *config_file = NULL;
7a6421fa 122char *shell_cmd = NULL;
b6062654 123char *log_format = NULL;
65575e96 124char *password_file = NULL;
41bd28fe 125char *rsync_path = RSYNC_PATH;
66203a98 126char *backup_dir = NULL;
e0391f81 127char backup_dir_buf[MAXPATHLEN];
7a6421fa 128int rsync_port = RSYNC_PORT;
59c95e42 129int link_dest = 0;
7a6421fa
AT
130
131int verbose = 0;
b86f0cef 132int quiet = 0;
7a6421fa 133int always_checksum = 0;
f7632fc6 134int list_only = 0;
7a6421fa 135
2289bf64 136#define FIXED_CHECKSUM_SEED 32761
beb93684 137#define MAX_BATCH_PREFIX_LEN 256 /* Must be less than MAXPATHLEN-13 */
088aac85 138char *batch_prefix = NULL;
6902ed17 139
e1add893 140static int daemon_opt; /* sets am_daemon after option error-reporting */
5b56cc19
AT
141static int modify_window_set;
142
06963d0f 143/** Local address to bind. As a character string because it's
fdf57ede 144 * interpreted by the IPv6 layer: should be a numeric IP4 or IP6
06963d0f
MP
145 * address, or a hostname. **/
146char *bind_address;
5c9730a4 147
7a24c346 148
27a12348 149static void print_rsync_version(enum logcode f)
7a24c346 150{
dfa32483
WD
151 char const *got_socketpair = "no ";
152 char const *hardlinks = "no ";
153 char const *links = "no ";
a358449a 154 char const *ipv6 = "no ";
736a6a29 155 STRUCT_STAT *dumstat;
0c80cd8e
MP
156
157#ifdef HAVE_SOCKETPAIR
dfa32483 158 got_socketpair = "";
0c80cd8e 159#endif
2855f61f
MP
160
161#if SUPPORT_HARD_LINKS
dfa32483 162 hardlinks = "";
2855f61f
MP
163#endif
164
165#if SUPPORT_LINKS
dfa32483 166 links = "";
2855f61f
MP
167#endif
168
a358449a
MP
169#if INET6
170 ipv6 = "";
dfa32483 171#endif
a358449a 172
dfa32483
WD
173 rprintf(f, "%s version %s protocol version %d\n",
174 RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION);
175 rprintf(f,
45ddbf62 176 "Copyright (C) 1996-2004 by Andrew Tridgell and others\n");
3b4b1984 177 rprintf(f, "<http://rsync.samba.org/>\n");
dfa32483
WD
178 rprintf(f, "Capabilities: %d-bit files, %ssocketpairs, "
179 "%shard links, %ssymlinks, batchfiles, \n",
a5c11139 180 (int) (sizeof (OFF_T) * 8),
dfa32483 181 got_socketpair, hardlinks, links);
2855f61f 182
736a6a29
MP
183 /* Note that this field may not have type ino_t. It depends
184 * on the complicated interaction between largefile feature
185 * macros. */
7a52790b 186 rprintf(f, " %sIPv6, %d-bit system inums, %d-bit internal inums\n",
dfa32483 187 ipv6,
a5c11139 188 (int) (sizeof dumstat->st_ino * 8),
5f381268 189 (int) (sizeof (uint64) * 8));
fc0302cf
MP
190#ifdef MAINTAINER_MODE
191 rprintf(f, " panic action: \"%s\"\n",
192 get_panic_action());
193#endif
736a6a29 194
7a24c346 195#ifdef NO_INT64
dfa32483 196 rprintf(f, "WARNING: no 64-bit integers on this platform!\n");
7a24c346 197#endif
7b329a2d
MP
198
199 rprintf(f,
200"\n"
201"rsync comes with ABSOLUTELY NO WARRANTY. This is free software, and you\n"
202"are welcome to redistribute it under certain conditions. See the GNU\n"
203"General Public Licence for details.\n"
204 );
7a24c346
MP
205}
206
207
0f3203c3 208void usage(enum logcode F)
7a6421fa 209{
2855f61f 210 print_rsync_version(F);
704f908e 211
3ff984d7 212 rprintf(F,"\nrsync is a file transfer program capable of efficient remote update\nvia a fast differencing algorithm.\n\n");
704f908e 213
9ef53907 214 rprintf(F,"Usage: rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST\n");
704f908e 215 rprintf(F," or rsync [OPTION]... [USER@]HOST:SRC DEST\n");
9ef53907 216 rprintf(F," or rsync [OPTION]... SRC [SRC]... DEST\n");
14d43f1f 217 rprintf(F," or rsync [OPTION]... [USER@]HOST::SRC [DEST]\n");
9ef53907 218 rprintf(F," or rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST\n");
14d43f1f 219 rprintf(F," or rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST]\n");
eaa4c150 220 rprintf(F," or rsync [OPTION]... SRC [SRC]... rsync://[USER@]HOST[:PORT]/DEST\n");
9ef53907
DD
221 rprintf(F,"SRC on single-colon remote HOST will be expanded by remote shell\n");
222 rprintf(F,"SRC on server remote HOST may contain shell wildcards or multiple\n");
223 rprintf(F," sources separated by space as long as they have same top-level\n");
704f908e
AT
224 rprintf(F,"\nOptions\n");
225 rprintf(F," -v, --verbose increase verbosity\n");
b86f0cef 226 rprintf(F," -q, --quiet decrease verbosity\n");
704f908e 227 rprintf(F," -c, --checksum always checksum\n");
06891710 228 rprintf(F," -a, --archive archive mode, equivalent to -rlptgoD\n");
704f908e
AT
229 rprintf(F," -r, --recursive recurse into directories\n");
230 rprintf(F," -R, --relative use relative path names\n");
ea5164d1
WD
231 rprintf(F," --no-relative turn off --relative\n");
232 rprintf(F," --no-implied-dirs don't send implied dirs with -R\n");
6839140e 233 rprintf(F," -b, --backup make backups (see --suffix & --backup-dir)\n");
e20c5e95 234 rprintf(F," --backup-dir make backups into this directory\n");
6839140e 235 rprintf(F," --suffix=SUFFIX backup suffix (default %s w/o --backup-dir)\n",BACKUP_SUFFIX);
704f908e 236 rprintf(F," -u, --update update only (don't overwrite newer files)\n");
716e73d4 237 rprintf(F," -K, --keep-dirlinks treat symlinked dir on receiver as dir\n");
13e29995 238 rprintf(F," -l, --links copy symlinks as symlinks\n");
06d76beb
WD
239 rprintf(F," -L, --copy-links copy the referent of all symlinks\n");
240 rprintf(F," --copy-unsafe-links copy the referent of \"unsafe\" symlinks\n");
241 rprintf(F," --safe-links ignore \"unsafe\" symlinks\n");
704f908e
AT
242 rprintf(F," -H, --hard-links preserve hard links\n");
243 rprintf(F," -p, --perms preserve permissions\n");
244 rprintf(F," -o, --owner preserve owner (root only)\n");
245 rprintf(F," -g, --group preserve group\n");
246 rprintf(F," -D, --devices preserve devices (root only)\n");
dfa32483 247 rprintf(F," -t, --times preserve times\n");
704f908e
AT
248 rprintf(F," -S, --sparse handle sparse files efficiently\n");
249 rprintf(F," -n, --dry-run show what would have been transferred\n");
250 rprintf(F," -W, --whole-file copy whole files, no incremental checks\n");
93689aa5 251 rprintf(F," --no-whole-file turn off --whole-file\n");
704f908e 252 rprintf(F," -x, --one-file-system don't cross filesystem boundaries\n");
dfa32483 253 rprintf(F," -B, --block-size=SIZE checksum blocking size (default %d)\n",BLOCK_SIZE);
54170a08 254 rprintf(F," -e, --rsh=COMMAND specify the remote shell\n");
704f908e 255 rprintf(F," --rsync-path=PATH specify path to rsync on the remote machine\n");
1347d512 256 rprintf(F," --existing only update files that already exist\n");
6839140e 257 rprintf(F," --ignore-existing ignore files that already exist on receiving side\n");
704f908e 258 rprintf(F," --delete delete files that don't exist on the sending side\n");
b33b791e 259 rprintf(F," --delete-excluded also delete excluded files on the receiving side\n");
ad1a09a5 260 rprintf(F," --delete-after receiver deletes after transferring, not before\n");
db2b5cb7 261 rprintf(F," --ignore-errors delete even if there are I/O errors\n");
0b73ca12 262 rprintf(F," --max-delete=NUM don't delete more than NUM files\n");
c95da96a 263 rprintf(F," --partial keep partially transferred files\n");
704f908e
AT
264 rprintf(F," --force force deletion of directories even if not empty\n");
265 rprintf(F," --numeric-ids don't map uid/gid values by user/group name\n");
db2b5cb7 266 rprintf(F," --timeout=TIME set I/O timeout in seconds\n");
6839140e
WD
267 rprintf(F," -I, --ignore-times turn off mod time & file size quick check\n");
268 rprintf(F," --size-only ignore mod time for quick check (use size)\n");
269 rprintf(F," --modify-window=NUM compare mod times with reduced accuracy\n");
704f908e 270 rprintf(F," -T --temp-dir=DIR create temporary files in directory DIR\n");
375a4556 271 rprintf(F," --compare-dest=DIR also compare destination files relative to DIR\n");
8294b00c 272 rprintf(F," --link-dest=DIR create hardlinks to DIR for unchanged files\n");
d9fcc198 273 rprintf(F," -P equivalent to --partial --progress\n");
704f908e 274 rprintf(F," -z, --compress compress file data\n");
ea5164d1 275 rprintf(F," -C, --cvs-exclude auto ignore files in the same way CVS does\n");
2acf81eb 276 rprintf(F," --exclude=PATTERN exclude files matching PATTERN\n");
858fb9eb 277 rprintf(F," --exclude-from=FILE exclude patterns listed in FILE\n");
2acf81eb 278 rprintf(F," --include=PATTERN don't exclude files matching PATTERN\n");
858fb9eb 279 rprintf(F," --include-from=FILE don't exclude patterns listed in FILE\n");
ea5164d1 280 rprintf(F," --files-from=FILE read FILE for list of source-file names\n");
6839140e 281 rprintf(F," -0 --from0 all *-from file lists are delimited by nulls\n");
dfa32483 282 rprintf(F," --version print version number\n");
db2b5cb7 283 rprintf(F," --daemon run as an rsync daemon\n");
dfa32483
WD
284 rprintf(F," --no-detach do not detach from the parent\n");
285 rprintf(F," --address=ADDRESS bind to the specified address\n");
286 rprintf(F," --config=FILE specify alternate rsyncd.conf file\n");
704f908e 287 rprintf(F," --port=PORT specify alternate rsyncd port number\n");
db2b5cb7 288 rprintf(F," --blocking-io use blocking I/O for the remote shell\n");
dfa32483
WD
289 rprintf(F," --no-blocking-io turn off --blocking-io\n");
290 rprintf(F," --stats give some file transfer stats\n");
291 rprintf(F," --progress show progress during transfer\n");
292 rprintf(F," --log-format=FORMAT log file transfers using specified format\n");
65575e96 293 rprintf(F," --password-file=FILE get password from FILE\n");
ef5d23eb 294 rprintf(F," --bwlimit=KBPS limit I/O bandwidth, KBytes per second\n");
088aac85
DD
295 rprintf(F," --write-batch=PREFIX write batch fileset starting with PREFIX\n");
296 rprintf(F," --read-batch=PREFIX read batch fileset starting with PREFIX\n");
c8d895de 297 rprintf(F," --checksum-seed=NUM set block/file checksum seed\n");
06963d0f 298#ifdef INET6
3dd22903
WD
299 rprintf(F," -4 --ipv4 prefer IPv4\n");
300 rprintf(F," -6 --ipv6 prefer IPv6\n");
06963d0f 301#endif
3dd22903 302 rprintf(F," -h, --help show this help screen\n");
7a6421fa
AT
303
304 rprintf(F,"\n");
b72f24c7
AT
305
306 rprintf(F,"\nPlease see the rsync(1) and rsyncd.conf(5) man pages for full documentation\n");
2855f61f 307 rprintf(F,"See http://rsync.samba.org/ for updates, bug reports, and answers\n");
7a6421fa
AT
308}
309
1f3d6cdd
WD
310enum {OPT_VERSION = 1000, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
311 OPT_DELETE_AFTER, OPT_DELETE_EXCLUDED, OPT_LINK_DEST,
312 OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW,
99218d82 313 OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_TIMEOUT,
c67d1386 314 OPT_REFUSED_BASE = 9000};
7a6421fa 315
2855f61f
MP
316static struct poptOption long_options[] = {
317 /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
dfa32483 318 {"version", 0, POPT_ARG_NONE, 0, OPT_VERSION, 0, 0},
d175d7e1 319 {"suffix", 0, POPT_ARG_STRING, &backup_suffix, 0, 0, 0 },
3dd22903
WD
320 {"rsync-path", 0, POPT_ARG_STRING, &rsync_path, 0, 0, 0 },
321 {"password-file", 0, POPT_ARG_STRING, &password_file, 0, 0, 0 },
afb6e945
WD
322 {"ignore-times", 'I', POPT_ARG_NONE, &ignore_times, 0, 0, 0 },
323 {"size-only", 0, POPT_ARG_NONE, &size_only, 0, 0, 0 },
8b54f004 324 {"modify-window", 0, POPT_ARG_INT, &modify_window, OPT_MODIFY_WINDOW, 0, 0 },
afb6e945
WD
325 {"one-file-system", 'x', POPT_ARG_NONE, &one_file_system, 0, 0, 0 },
326 {"delete", 0, POPT_ARG_NONE, &delete_mode, 0, 0, 0 },
327 {"existing", 0, POPT_ARG_NONE, &only_existing, 0, 0, 0 },
328 {"ignore-existing", 0, POPT_ARG_NONE, &opt_ignore_existing, 0, 0, 0 },
1de50993 329 {"delete-after", 0, POPT_ARG_NONE, 0, OPT_DELETE_AFTER, 0, 0 },
8b54f004 330 {"delete-excluded", 0, POPT_ARG_NONE, 0, OPT_DELETE_EXCLUDED, 0, 0 },
afb6e945
WD
331 {"force", 0, POPT_ARG_NONE, &force_delete, 0, 0, 0 },
332 {"numeric-ids", 0, POPT_ARG_NONE, &numeric_ids, 0, 0, 0 },
8b54f004
MP
333 {"exclude", 0, POPT_ARG_STRING, 0, OPT_EXCLUDE, 0, 0 },
334 {"include", 0, POPT_ARG_STRING, 0, OPT_INCLUDE, 0, 0 },
335 {"exclude-from", 0, POPT_ARG_STRING, 0, OPT_EXCLUDE_FROM, 0, 0 },
336 {"include-from", 0, POPT_ARG_STRING, 0, OPT_INCLUDE_FROM, 0, 0 },
afb6e945 337 {"safe-links", 0, POPT_ARG_NONE, &safe_symlinks, 0, 0, 0 },
8b54f004 338 {"help", 'h', POPT_ARG_NONE, 0, 'h', 0, 0 },
afb6e945
WD
339 {"backup", 'b', POPT_ARG_NONE, &make_backups, 0, 0, 0 },
340 {"dry-run", 'n', POPT_ARG_NONE, &dry_run, 0, 0, 0 },
341 {"sparse", 'S', POPT_ARG_NONE, &sparse_files, 0, 0, 0 },
342 {"cvs-exclude", 'C', POPT_ARG_NONE, &cvs_exclude, 0, 0, 0 },
343 {"update", 'u', POPT_ARG_NONE, &update_only, 0, 0, 0 },
716e73d4 344 {"keep-dirlinks", 'K', POPT_ARG_NONE, &keep_dirlinks, 0, 0, 0 },
afb6e945
WD
345 {"links", 'l', POPT_ARG_NONE, &preserve_links, 0, 0, 0 },
346 {"copy-links", 'L', POPT_ARG_NONE, &copy_links, 0, 0, 0 },
347 {"whole-file", 'W', POPT_ARG_VAL, &whole_file, 1, 0, 0 },
348 {"no-whole-file", 0, POPT_ARG_VAL, &whole_file, 0, 0, 0 },
349 {"copy-unsafe-links", 0, POPT_ARG_NONE, &copy_unsafe_links, 0, 0, 0 },
350 {"perms", 'p', POPT_ARG_NONE, &preserve_perms, 0, 0, 0 },
351 {"owner", 'o', POPT_ARG_NONE, &preserve_uid, 0, 0, 0 },
352 {"group", 'g', POPT_ARG_NONE, &preserve_gid, 0, 0, 0 },
353 {"devices", 'D', POPT_ARG_NONE, &preserve_devices, 0, 0, 0 },
354 {"times", 't', POPT_ARG_NONE, &preserve_times, 0, 0, 0 },
355 {"checksum", 'c', POPT_ARG_NONE, &always_checksum, 0, 0, 0 },
8b54f004
MP
356 {"verbose", 'v', POPT_ARG_NONE, 0, 'v', 0, 0 },
357 {"quiet", 'q', POPT_ARG_NONE, 0, 'q', 0, 0 },
dfa32483 358 {"archive", 'a', POPT_ARG_NONE, &archive_mode, 0, 0, 0 },
afb6e945 359 {"server", 0, POPT_ARG_NONE, &am_server, 0, 0, 0 },
dfa32483 360 {"sender", 0, POPT_ARG_NONE, 0, OPT_SENDER, 0, 0 },
afb6e945 361 {"recursive", 'r', POPT_ARG_NONE, &recurse, 0, 0, 0 },
ea5164d1
WD
362 {"relative", 'R', POPT_ARG_VAL, &relative_paths, 1, 0, 0 },
363 {"no-relative", 0, POPT_ARG_VAL, &relative_paths, 0, 0, 0 },
afb6e945
WD
364 {"rsh", 'e', POPT_ARG_STRING, &shell_cmd, 0, 0, 0 },
365 {"block-size", 'B', POPT_ARG_INT, &block_size, 0, 0, 0 },
366 {"max-delete", 0, POPT_ARG_INT, &max_delete, 0, 0, 0 },
99218d82 367 {"timeout", 0, POPT_ARG_INT, &io_timeout, OPT_TIMEOUT, 0, 0 },
afb6e945
WD
368 {"temp-dir", 'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
369 {"compare-dest", 0, POPT_ARG_STRING, &compare_dest, 0, 0, 0 },
7be73df4 370 {"link-dest", 0, POPT_ARG_STRING, &compare_dest, OPT_LINK_DEST, 0, 0 },
2855f61f 371 /* TODO: Should this take an optional int giving the compression level? */
afb6e945 372 {"compress", 'z', POPT_ARG_NONE, &do_compression, 0, 0, 0 },
e1add893 373 {"daemon", 0, POPT_ARG_NONE, &daemon_opt, 0, 0, 0 },
afb6e945
WD
374 {"no-detach", 0, POPT_ARG_NONE, &no_detach, 0, 0, 0 },
375 {"stats", 0, POPT_ARG_NONE, &do_stats, 0, 0, 0 },
376 {"progress", 0, POPT_ARG_NONE, &do_progress, 0, 0, 0 },
377 {"partial", 0, POPT_ARG_NONE, &keep_partial, 0, 0, 0 },
378 {"ignore-errors", 0, POPT_ARG_NONE, &ignore_errors, 0, 0, 0 },
379 {"blocking-io", 0, POPT_ARG_VAL, &blocking_io, 1, 0, 0 },
380 {"no-blocking-io", 0, POPT_ARG_VAL, &blocking_io, 0, 0, 0 },
dfa32483 381 {0, 'P', POPT_ARG_NONE, 0, 'P', 0, 0 },
afb6e945
WD
382 {"config", 0, POPT_ARG_STRING, &config_file, 0, 0, 0 },
383 {"port", 0, POPT_ARG_INT, &rsync_port, 0, 0, 0 },
384 {"log-format", 0, POPT_ARG_STRING, &log_format, 0, 0, 0 },
385 {"bwlimit", 0, POPT_ARG_INT, &bwlimit, 0, 0, 0 },
8b54f004 386 {"address", 0, POPT_ARG_STRING, &bind_address, 0, 0, 0 },
afb6e945
WD
387 {"backup-dir", 0, POPT_ARG_STRING, &backup_dir, 0, 0, 0 },
388 {"hard-links", 'H', POPT_ARG_NONE, &preserve_hard_links, 0, 0, 0 },
dfa32483
WD
389 {"read-batch", 0, POPT_ARG_STRING, &batch_prefix, OPT_READ_BATCH, 0, 0 },
390 {"write-batch", 0, POPT_ARG_STRING, &batch_prefix, OPT_WRITE_BATCH, 0, 0 },
ea5164d1
WD
391 {"files-from", 0, POPT_ARG_STRING, &files_from, 0, 0, 0 },
392 {"from0", '0', POPT_ARG_NONE, &eol_nulls, 0, 0, 0},
393 {"no-implied-dirs", 0, POPT_ARG_VAL, &implied_dirs, 0, 0, 0 },
4f3e9a0f 394 {"protocol", 0, POPT_ARG_INT, &protocol_version, 0, 0, 0 },
c8d895de 395 {"checksum-seed", 0, POPT_ARG_INT, &checksum_seed, 0, 0, 0 },
06963d0f 396#ifdef INET6
3dd22903
WD
397 {"ipv4", '4', POPT_ARG_VAL, &default_af_hint, AF_INET, 0, 0 },
398 {"ipv6", '6', POPT_ARG_VAL, &default_af_hint, AF_INET6, 0, 0 },
06963d0f 399#endif
8b54f004 400 {0,0,0,0, 0, 0, 0}
2855f61f 401};
7a6421fa 402
06963d0f 403
e51094b7 404static char err_buf[200];
cd8185f2 405
2855f61f 406
dafe63ca
MP
407/**
408 * Store the option error message, if any, so that we can log the
409 * connection attempt (which requires parsing the options), and then
410 * show the error later on.
411 **/
cd8185f2
AT
412void option_error(void)
413{
e51094b7
WD
414 if (!err_buf[0]) {
415 strcpy(err_buf, "Error parsing options: "
416 "option may be supported on client but not on server?\n");
cd8185f2 417 }
e51094b7 418
e51094b7 419 rprintf(FERROR, RSYNC_NAME ": %s", err_buf);
cd8185f2
AT
420}
421
dafe63ca
MP
422
423/**
27ed20f7
WD
424 * Tweak the option table to disable all options that the rsyncd.conf
425 * file has told us to refuse.
dafe63ca 426 **/
27ed20f7 427static void set_refuse_options(char *bp)
cd8185f2 428{
27ed20f7
WD
429 struct poptOption *op;
430 char *cp;
431
432 while (1) {
433 if ((cp = strchr(bp, ' ')) != NULL)
434 *cp= '\0';
55afbb52
WD
435 for (op = long_options; ; op++) {
436 if (!op->longName) {
437 rprintf(FLOG,
438 "Unknown option %s in \"refuse options\" setting\n",
439 bp);
440 break;
441 }
27ed20f7 442 if (strcmp(bp, op->longName) == 0) {
c67d1386 443 op->val = (op - long_options)+OPT_REFUSED_BASE;
27ed20f7
WD
444 break;
445 }
cd8185f2 446 }
27ed20f7
WD
447 if (!cp)
448 break;
449 *cp = ' ';
450 bp = cp + 1;
cd8185f2 451 }
cd8185f2
AT
452}
453
454
2855f61f
MP
455static int count_args(char const **argv)
456{
dfa32483 457 int i = 0;
2855f61f 458
dfa32483
WD
459 while (argv[i] != NULL)
460 i++;
461
462 return i;
2855f61f
MP
463}
464
465
dafe63ca
MP
466/**
467 * Process command line arguments. Called on both local and remote.
468 *
469 * @retval 1 if all options are OK; with globals set to appropriate
470 * values
471 *
472 * @retval 0 on error, with err_buf containing an explanation
473 **/
2855f61f 474int parse_arguments(int *argc, const char ***argv, int frommain)
7a6421fa 475{
d853783f 476 int opt;
cd8185f2 477 char *ref = lp_refuse_options(module_id);
7be73df4 478 const char *arg;
dfa32483 479 poptContext pc;
d853783f 480
27ed20f7
WD
481 if (ref && *ref)
482 set_refuse_options(ref);
483
dfa32483 484 /* TODO: Call poptReadDefaultConfig; handle errors. */
cd8185f2 485
dfa32483
WD
486 /* The context leaks in case of an error, but if there's a
487 * problem we always exit anyhow. */
488 pc = poptGetContext(RSYNC_NAME, *argc, *argv, long_options, 0);
2855f61f
MP
489
490 while ((opt = poptGetNextOpt(pc)) != -1) {
dfa32483
WD
491 /* most options are handled automatically by popt;
492 * only special cases are returned and listed here. */
2855f61f 493
d853783f
AT
494 switch (opt) {
495 case OPT_VERSION:
dfa32483 496 print_rsync_version(FINFO);
d853783f 497 exit_cleanup(0);
dfa32483 498
5b56cc19 499 case OPT_MODIFY_WINDOW:
dfa32483
WD
500 /* The value has already been set by popt, but
501 * we need to remember that we're using a
502 * non-default setting. */
5b56cc19
AT
503 modify_window_set = 1;
504 break;
1de50993
WD
505
506 case OPT_DELETE_AFTER:
507 delete_after = 1;
508 delete_mode = 1;
509 break;
510
b33b791e
DD
511 case OPT_DELETE_EXCLUDED:
512 delete_excluded = 1;
513 delete_mode = 1;
514 break;
515
d853783f 516 case OPT_EXCLUDE:
fa0c1939
WD
517 if (am_server || sanitize_paths)
518 return 0; /* Impossible... */
357406ec 519 add_exclude(&exclude_list, poptGetOptArg(pc), 0);
d853783f
AT
520 break;
521
522 case OPT_INCLUDE:
fa0c1939
WD
523 if (am_server || sanitize_paths)
524 return 0; /* Impossible... */
8645af1d 525 add_exclude(&exclude_list, poptGetOptArg(pc),
357406ec 526 XFLG_DEF_INCLUDE);
d853783f
AT
527 break;
528
529 case OPT_EXCLUDE_FROM:
fa0c1939
WD
530 if (am_server || sanitize_paths)
531 return 0; /* Impossible... */
7be73df4 532 arg = poptGetOptArg(pc);
7be73df4 533 add_exclude_file(&exclude_list, arg,
357406ec 534 XFLG_FATAL_ERRORS);
d853783f
AT
535 break;
536
93695764 537 case OPT_INCLUDE_FROM:
fa0c1939
WD
538 if (am_server || sanitize_paths)
539 return 0; /* Impossible... */
7be73df4 540 arg = poptGetOptArg(pc);
7be73df4 541 add_exclude_file(&exclude_list, arg,
357406ec 542 XFLG_FATAL_ERRORS | XFLG_DEF_INCLUDE);
93695764
DD
543 break;
544
d853783f
AT
545 case 'h':
546 usage(FINFO);
547 exit_cleanup(0);
548
d853783f
AT
549 case 'v':
550 verbose++;
551 break;
7a6421fa 552
b86f0cef 553 case 'q':
f98c60bf
WD
554 if (frommain)
555 quiet++;
b86f0cef
DD
556 break;
557
d853783f
AT
558 case OPT_SENDER:
559 if (!am_server) {
560 usage(FERROR);
65417579 561 exit_cleanup(RERR_SYNTAX);
d853783f
AT
562 }
563 am_sender = 1;
564 break;
565
d9fcc198
AT
566 case 'P':
567 do_progress = 1;
568 keep_partial = 1;
569 break;
570
088aac85
DD
571 case OPT_WRITE_BATCH:
572 /* popt stores the filename in batch_prefix for us */
573 write_batch = 1;
2289bf64 574 checksum_seed = FIXED_CHECKSUM_SEED;
088aac85
DD
575 break;
576
76f79ba7 577 case OPT_READ_BATCH:
088aac85 578 /* popt stores the filename in batch_prefix for us */
6902ed17 579 read_batch = 1;
2289bf64 580 checksum_seed = FIXED_CHECKSUM_SEED;
6902ed17 581 break;
ea5164d1 582
99218d82
WD
583 case OPT_TIMEOUT:
584 if (io_timeout && io_timeout < select_timeout)
585 select_timeout = io_timeout;
586 break;
587
59c95e42
DD
588 case OPT_LINK_DEST:
589#if HAVE_LINK
59c95e42
DD
590 link_dest = 1;
591 break;
592#else
d175d7e1 593 snprintf(err_buf, sizeof err_buf,
dfa32483 594 "hard links are not supported on this %s\n",
59c95e42 595 am_server ? "server" : "client");
59c95e42
DD
596 return 0;
597#endif
598
d853783f 599 default:
55afbb52 600 /* A large opt value means that set_refuse_options()
c67d1386
WD
601 * turned this option off (opt-BASE is its index). */
602 if (opt >= OPT_REFUSED_BASE) {
603 struct poptOption *op =
604 &long_options[opt-OPT_REFUSED_BASE];
27ed20f7
WD
605 int n = snprintf(err_buf, sizeof err_buf,
606 "This server does not support --%s\n",
607 op->longName) - 1;
608 if (op->shortName) {
609 snprintf(err_buf+n, sizeof err_buf-n,
610 " (-%c)\n", op->shortName);
611 }
612 } else {
613 snprintf(err_buf, sizeof err_buf,
614 "%s%s: %s\n",
615 am_server ? "on remote machine: " : "",
616 poptBadOption(pc, POPT_BADOPTION_NOALIAS),
617 poptStrerror(opt));
618 }
dfa32483 619 return 0;
d853783f 620 }
7a6421fa 621 }
2855f61f 622
e1add893 623#if !SUPPORT_LINKS
54e87b4b 624 if (preserve_links && !am_sender) {
e1add893
WD
625 snprintf(err_buf, sizeof err_buf,
626 "symlinks are not supported on this %s\n",
627 am_server ? "server" : "client");
e1add893
WD
628 return 0;
629 }
630#endif
631
632#if !SUPPORT_HARD_LINKS
633 if (preserve_hard_links) {
634 snprintf(err_buf, sizeof err_buf,
635 "hard links are not supported on this %s\n",
636 am_server ? "server" : "client");
e1add893
WD
637 return 0;
638 }
639#endif
640
088aac85 641 if (write_batch && read_batch) {
d175d7e1
WD
642 rprintf(FERROR,
643 "write-batch and read-batch can not be used together\n");
644 exit_cleanup(RERR_SYNTAX);
088aac85 645 }
beb93684
WD
646 if (batch_prefix && strlen(batch_prefix) > MAX_BATCH_PREFIX_LEN) {
647 rprintf(FERROR,
ce58b1b4 648 "the batch-file prefix must be %d characters or less.\n",
beb93684
WD
649 MAX_BATCH_PREFIX_LEN);
650 exit_cleanup(RERR_SYNTAX);
651 }
088aac85 652
ce58b1b4
WD
653 if (tmpdir && strlen(tmpdir) >= MAXPATHLEN - 10) {
654 rprintf(FERROR, "the --temp-dir path is WAY too long.\n");
655 exit_cleanup(RERR_SYNTAX);
656 }
657
088aac85 658 if (do_compression && (write_batch || read_batch)) {
d175d7e1
WD
659 rprintf(FERROR,
660 "compress can not be used with write-batch or read-batch\n");
661 exit_cleanup(RERR_SYNTAX);
088aac85
DD
662 }
663
dfa32483 664 if (archive_mode) {
ea5164d1
WD
665 if (!files_from)
666 recurse = 1;
dfa32483
WD
667#if SUPPORT_LINKS
668 preserve_links = 1;
669#endif
670 preserve_perms = 1;
671 preserve_times = 1;
672 preserve_gid = 1;
673 preserve_uid = 1;
674 preserve_devices = 1;
675 }
676
ea5164d1
WD
677 if (relative_paths < 0)
678 relative_paths = files_from? 1 : 0;
679
7be73df4
WD
680 *argv = poptGetArgs(pc);
681 if (*argv)
682 *argc = count_args(*argv);
683 else
684 *argc = 0;
685
686 if (sanitize_paths) {
687 int i;
688 for (i = *argc; i-- > 0; )
689 (*argv)[i] = alloc_sanitize_path((*argv)[i], NULL);
690 if (tmpdir)
691 tmpdir = alloc_sanitize_path(tmpdir, curr_dir);
692 if (compare_dest)
693 compare_dest = alloc_sanitize_path(compare_dest, curr_dir);
7be73df4
WD
694 if (backup_dir)
695 backup_dir = alloc_sanitize_path(backup_dir, curr_dir);
696 if (files_from)
697 files_from = alloc_sanitize_path(files_from, curr_dir);
698 }
699
5df1fcf2
WD
700 if (daemon_opt) {
701 daemon_opt = 0;
702 am_daemon = 1;
703 return 1;
704 }
705
d175d7e1 706 if (!backup_suffix)
e0391f81 707 backup_suffix = backup_dir ? "" : BACKUP_SUFFIX;
d175d7e1 708 backup_suffix_len = strlen(backup_suffix);
80ddadb7
WD
709 if (strchr(backup_suffix, '/') != NULL) {
710 rprintf(FERROR, "--suffix cannot contain slashes: %s\n",
711 backup_suffix);
712 exit_cleanup(RERR_SYNTAX);
713 }
e0391f81
WD
714 if (backup_dir) {
715 backup_dir_len = strlcpy(backup_dir_buf, backup_dir, sizeof backup_dir_buf);
716 backup_dir_remainder = sizeof backup_dir_buf - backup_dir_len;
717 if (backup_dir_remainder < 32) {
718 rprintf(FERROR, "the --backup-dir path is WAY too long.\n");
719 exit_cleanup(RERR_SYNTAX);
720 }
721 if (backup_dir_buf[backup_dir_len - 1] != '/') {
722 backup_dir_buf[backup_dir_len++] = '/';
723 backup_dir_buf[backup_dir_len] = '\0';
724 }
8dcf9335 725 if (verbose > 1 && !am_sender)
e0391f81 726 rprintf(FINFO, "backup_dir is %s\n", backup_dir_buf);
8dcf9335 727 } else if (!backup_suffix_len && (!am_server || !am_sender)) {
d175d7e1
WD
728 rprintf(FERROR,
729 "--suffix cannot be a null string without --backup-dir\n");
730 exit_cleanup(RERR_SYNTAX);
731 }
732
e2559dbe
S
733 if (do_progress && !verbose)
734 verbose = 1;
735
3c74c3a3
WD
736 if (bwlimit) {
737 bwlimit_writemax = (size_t)bwlimit * 128;
738 if (bwlimit_writemax < 512)
739 bwlimit_writemax = 512;
740 }
741
ea5164d1
WD
742 if (files_from) {
743 char *colon;
3e89da86 744 if (*argc != 2 && !(am_server && am_sender && *argc == 1)) {
ea5164d1
WD
745 usage(FERROR);
746 exit_cleanup(RERR_SYNTAX);
747 }
63596e1c 748 if (strcmp(files_from, "-") == 0) {
ea5164d1 749 filesfrom_fd = 0;
63596e1c
WD
750 if (am_server)
751 remote_filesfrom_file = "-";
752 }
ea5164d1
WD
753 else if ((colon = find_colon(files_from)) != 0) {
754 if (am_server) {
755 usage(FERROR);
756 exit_cleanup(RERR_SYNTAX);
757 }
758 remote_filesfrom_file = colon+1 + (colon[1] == ':');
759 if (strcmp(remote_filesfrom_file, "-") == 0) {
760 rprintf(FERROR, "Invalid --files-from remote filename\n");
761 exit_cleanup(RERR_SYNTAX);
762 }
763 } else {
ea5164d1
WD
764 filesfrom_fd = open(files_from, O_RDONLY|O_BINARY);
765 if (filesfrom_fd < 0) {
766 rsyserr(FERROR, errno,
767 "failed to open files-from file %s",
768 files_from);
769 exit_cleanup(RERR_FILEIO);
770 }
771 }
772 }
773
b11ed3b1 774 return 1;
7a6421fa
AT
775}
776
777
dafe63ca
MP
778/**
779 * Construct a filtered list of options to pass through from the
780 * client to the server.
781 *
782 * This involves setting options that will tell the server how to
783 * behave, and also filtering out options that are processed only
784 * locally.
785 **/
7a6421fa
AT
786void server_options(char **args,int *argc)
787{
d853783f
AT
788 int ac = *argc;
789 static char argstr[50];
f98c60bf 790 char *arg;
ef5d23eb 791
d853783f
AT
792 int i, x;
793
93689aa5
DD
794 if (blocking_io == -1)
795 blocking_io = 0;
796
d853783f
AT
797 args[ac++] = "--server";
798
1312d9fc
WD
799 if (daemon_over_rsh) {
800 args[ac++] = "--daemon";
801 *argc = ac;
802 /* if we're passing --daemon, we're done */
803 return;
804 }
805
d853783f
AT
806 if (!am_sender)
807 args[ac++] = "--sender";
808
809 x = 1;
810 argstr[0] = '-';
f98c60bf 811 for (i = 0; i < verbose; i++)
d853783f 812 argstr[x++] = 'v';
f0b36a48 813
b86f0cef 814 /* the -q option is intentionally left out */
d853783f
AT
815 if (make_backups)
816 argstr[x++] = 'b';
817 if (update_only)
818 argstr[x++] = 'u';
819 if (dry_run)
820 argstr[x++] = 'n';
821 if (preserve_links)
822 argstr[x++] = 'l';
823 if (copy_links)
824 argstr[x++] = 'L';
716e73d4
WD
825 if (keep_dirlinks && am_sender)
826 argstr[x++] = 'K';
1bfbf40b 827
dfa32483 828 if (whole_file > 0)
d853783f 829 argstr[x++] = 'W';
bceec82f
MP
830 /* We don't need to send --no-whole-file, because it's the
831 * default for remote transfers, and in any case old versions
832 * of rsync will not understand it. */
dfa32483 833
d853783f
AT
834 if (preserve_hard_links)
835 argstr[x++] = 'H';
836 if (preserve_uid)
837 argstr[x++] = 'o';
838 if (preserve_gid)
839 argstr[x++] = 'g';
840 if (preserve_devices)
841 argstr[x++] = 'D';
842 if (preserve_times)
843 argstr[x++] = 't';
844 if (preserve_perms)
845 argstr[x++] = 'p';
846 if (recurse)
847 argstr[x++] = 'r';
848 if (always_checksum)
849 argstr[x++] = 'c';
850 if (cvs_exclude)
851 argstr[x++] = 'C';
852 if (ignore_times)
853 argstr[x++] = 'I';
854 if (relative_paths)
855 argstr[x++] = 'R';
856 if (one_file_system)
857 argstr[x++] = 'x';
858 if (sparse_files)
859 argstr[x++] = 'S';
860 if (do_compression)
861 argstr[x++] = 'z';
f0b36a48 862
dfa32483 863 /* this is a complete hack - blame Rusty
f0b36a48
AT
864
865 this is a hack to make the list_only (remote file list)
866 more useful */
dfa32483 867 if (list_only && !recurse)
f0b36a48
AT
868 argstr[x++] = 'r';
869
d853783f
AT
870 argstr[x] = 0;
871
f98c60bf
WD
872 if (x != 1)
873 args[ac++] = argstr;
d853783f 874
195bd906 875 if (block_size) {
f98c60bf
WD
876 if (asprintf(&arg, "-B%u", block_size) < 0)
877 goto oom;
878 args[ac++] = arg;
dfa32483 879 }
d853783f 880
0b73ca12 881 if (max_delete && am_sender) {
f98c60bf
WD
882 if (asprintf(&arg, "--max-delete=%d", max_delete) < 0)
883 goto oom;
884 args[ac++] = arg;
dfa32483
WD
885 }
886
f98c60bf
WD
887 if (batch_prefix) {
888 char *r_or_w = write_batch ? "write" : "read";
889 if (asprintf(&arg, "--%s-batch=%s", r_or_w, batch_prefix) < 0)
890 goto oom;
891 args[ac++] = arg;
6902ed17 892 }
0b73ca12 893
d853783f 894 if (io_timeout) {
f98c60bf
WD
895 if (asprintf(&arg, "--timeout=%d", io_timeout) < 0)
896 goto oom;
897 args[ac++] = arg;
dfa32483 898 }
d853783f 899
ef5d23eb 900 if (bwlimit) {
f98c60bf
WD
901 if (asprintf(&arg, "--bwlimit=%d", bwlimit) < 0)
902 goto oom;
903 args[ac++] = arg;
ef5d23eb
DD
904 }
905
d175d7e1
WD
906 if (backup_dir) {
907 args[ac++] = "--backup-dir";
908 args[ac++] = backup_dir;
909 }
910
911 /* Only send --suffix if it specifies a non-default value. */
f98c60bf 912 if (strcmp(backup_suffix, backup_dir ? "" : BACKUP_SUFFIX) != 0) {
191e40da 913 /* We use the following syntax to avoid weirdness with '~'. */
f98c60bf
WD
914 if (asprintf(&arg, "--suffix=%s", backup_suffix) < 0)
915 goto oom;
916 args[ac++] = arg;
d853783f
AT
917 }
918
b33b791e
DD
919 if (delete_excluded)
920 args[ac++] = "--delete-excluded";
f98c60bf
WD
921 else if (delete_mode)
922 args[ac++] = "--delete";
b33b791e 923
f83f0548
AT
924 if (size_only)
925 args[ac++] = "--size-only";
926
5b56cc19 927 if (modify_window_set) {
f98c60bf
WD
928 if (asprintf(&arg, "--modify-window=%d", modify_window) < 0)
929 goto oom;
930 args[ac++] = arg;
5b56cc19
AT
931 }
932
c8d895de 933 if (checksum_seed) {
221ddb94 934 if (asprintf(&arg, "--checksum-seed=%d", checksum_seed) < 0)
c8d895de
WD
935 goto oom;
936 args[ac++] = arg;
937 }
938
d853783f
AT
939 if (keep_partial)
940 args[ac++] = "--partial";
941
942 if (force_delete)
943 args[ac++] = "--force";
944
57df171b
AT
945 if (delete_after)
946 args[ac++] = "--delete-after";
947
ef55c686
AT
948 if (ignore_errors)
949 args[ac++] = "--ignore-errors";
950
b5313607
DD
951 if (copy_unsafe_links)
952 args[ac++] = "--copy-unsafe-links";
953
d853783f
AT
954 if (safe_symlinks)
955 args[ac++] = "--safe-links";
956
957 if (numeric_ids)
958 args[ac++] = "--numeric-ids";
959
0b73ca12 960 if (only_existing && am_sender)
1347d512
AT
961 args[ac++] = "--existing";
962
dfa32483 963 if (opt_ignore_existing && am_sender)
3d6feada
MP
964 args[ac++] = "--ignore-existing";
965
d853783f
AT
966 if (tmpdir) {
967 args[ac++] = "--temp-dir";
968 args[ac++] = tmpdir;
969 }
970
375a4556
DD
971 if (compare_dest && am_sender) {
972 /* the server only needs this option if it is not the sender,
973 * and it may be an older version that doesn't know this
974 * option, so don't send it if client is the sender.
975 */
59c95e42 976 args[ac++] = link_dest ? "--link-dest" : "--compare-dest";
375a4556
DD
977 args[ac++] = compare_dest;
978 }
979
ea5164d1
WD
980 if (files_from && (!am_sender || remote_filesfrom_file)) {
981 if (remote_filesfrom_file) {
982 args[ac++] = "--files-from";
983 args[ac++] = remote_filesfrom_file;
984 if (eol_nulls)
985 args[ac++] = "--from0";
986 } else {
987 args[ac++] = "--files-from=-";
988 args[ac++] = "--from0";
989 }
990 }
991
d853783f 992 *argc = ac;
f98c60bf
WD
993 return;
994
995 oom:
996 out_of_memory("server_options");
7a6421fa
AT
997}
998
ea5164d1
WD
999/**
1000 * Return the position of a ':' IF it is not part of a filename (i.e. as
1001 * long as it doesn't occur after a slash.
1002 */
1003char *find_colon(char *s)
1004{
1005 char *p, *p2;
1006
1007 p = strchr(s,':');
f98c60bf
WD
1008 if (!p)
1009 return NULL;
ea5164d1
WD
1010
1011 /* now check to see if there is a / in the string before the : - if there is then
1012 discard the colon on the assumption that the : is part of a filename */
1013 p2 = strchr(s,'/');
f98c60bf
WD
1014 if (p2 && p2 < p)
1015 return NULL;
ea5164d1
WD
1016
1017 return p;
1018}