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