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