Added handling of the --min-size option.
[rsync/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,"     --existing              only update files that already exist on receiver\n");
300   rprintf(F,"     --ignore-existing       ignore files that already 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                         size = atoi(p + (*p == '+'));
671                         make_compatible = 1;
672                 } else
673                         p = NULL;
674         }
675         switch (*arg && arg != p ? *arg : def_suf) {
676         case 'b': case 'B':
677                 size += atof(*size_arg);
678                 break;
679         case 'k': case 'K':
680                 size += atof(*size_arg) * mult;
681                 break;
682         case 'm': case 'M':
683                 size += atof(*size_arg) * mult*mult;
684                 break;
685         case 'g': case 'G':
686                 size += atof(*size_arg) * mult*mult*mult;
687                 break;
688         default:
689                 size = -1;
690                 break;
691         }
692         if (size > 0 && make_compatible) {
693                 /* We convert this manually because we may need %lld precision,
694                  * and that's not a portable sprintf() escape. */
695                 char buf[128], *s = buf + sizeof buf;
696                 OFF_T num = size;
697                 *--s = '\0';
698                 while (num) {
699                         if (s == buf) /* impossible... */
700                                 out_of_memory("parse_size_arg@buf");
701                         *--s = (num % 10) + '0';
702                         num /= 10;
703                 }
704                 if (!(*size_arg = strdup(s)))
705                         out_of_memory("parse_size_arg");
706         }
707         return size;
708 }
709
710
711 static void create_refuse_error(int which)
712 {
713         /* The "which" value is the index + OPT_REFUSED_BASE. */
714         struct poptOption *op = &long_options[which - OPT_REFUSED_BASE];
715         int n = snprintf(err_buf, sizeof err_buf,
716                          "The server is configured to refuse --%s\n",
717                          op->longName) - 1;
718         if (op->shortName) {
719                 snprintf(err_buf + n, sizeof err_buf - n,
720                          " (-%c)\n", op->shortName);
721         }
722 }
723
724
725 /**
726  * Process command line arguments.  Called on both local and remote.
727  *
728  * @retval 1 if all options are OK; with globals set to appropriate
729  * values
730  *
731  * @retval 0 on error, with err_buf containing an explanation
732  **/
733 int parse_arguments(int *argc, const char ***argv, int frommain)
734 {
735         int opt;
736         char *ref = lp_refuse_options(module_id);
737         const char *arg;
738         poptContext pc;
739
740         if (ref && *ref)
741                 set_refuse_options(ref);
742
743         /* TODO: Call poptReadDefaultConfig; handle errors. */
744
745         /* The context leaks in case of an error, but if there's a
746          * problem we always exit anyhow. */
747         pc = poptGetContext(RSYNC_NAME, *argc, *argv, long_options, 0);
748         poptReadDefaultConfig(pc, 0);
749
750         while ((opt = poptGetNextOpt(pc)) != -1) {
751                 /* most options are handled automatically by popt;
752                  * only special cases are returned and listed here. */
753
754                 switch (opt) {
755                 case OPT_VERSION:
756                         print_rsync_version(FINFO);
757                         exit_cleanup(0);
758
759                 case OPT_DAEMON:
760                         if (am_daemon) {
761                                 strcpy(err_buf, "Attempt to hack rsync thwarted!\n");
762                                 return 0;
763                         }
764                         poptFreeContext(pc);
765                         pc = poptGetContext(RSYNC_NAME, *argc, *argv,
766                                             long_daemon_options, 0);
767                         while ((opt = poptGetNextOpt(pc)) != -1) {
768                                 switch (opt) {
769                                 case 'h':
770                                         daemon_usage(FINFO);
771                                         exit_cleanup(0);
772
773                                 case 'v':
774                                         verbose++;
775                                         break;
776
777                                 default:
778                                         rprintf(FERROR,
779                                             "rsync: %s: %s (in daemon mode)\n",
780                                             poptBadOption(pc, POPT_BADOPTION_NOALIAS),
781                                             poptStrerror(opt));
782                                         goto daemon_error;
783                                 }
784                         }
785
786                         if (tmpdir && strlen(tmpdir) >= MAXPATHLEN - 10) {
787                                 snprintf(err_buf, sizeof err_buf,
788                                          "the --temp-dir path is WAY too long.\n");
789                                 return 0;
790                         }
791
792                         if (!daemon_opt) {
793                                 rprintf(FERROR, "Daemon option(s) used without --daemon.\n");
794                             daemon_error:
795                                 rprintf(FERROR,
796                                     "(Type \"rsync --daemon --help\" for assistance with daemon mode.)\n");
797                                 exit_cleanup(RERR_SYNTAX);
798                         }
799
800                         *argv = poptGetArgs(pc);
801                         *argc = count_args(*argv);
802                         am_starting_up = 0;
803                         daemon_opt = 0;
804                         am_daemon = 1;
805                         return 1;
806
807                 case OPT_MODIFY_WINDOW:
808                         /* The value has already been set by popt, but
809                          * we need to remember that we're using a
810                          * non-default setting. */
811                         modify_window_set = 1;
812                         break;
813
814                 case OPT_FILTER:
815                         parse_rule(&filter_list, poptGetOptArg(pc), 0, 0);
816                         break;
817
818                 case OPT_EXCLUDE:
819                         parse_rule(&filter_list, poptGetOptArg(pc),
820                                    0, XFLG_OLD_PREFIXES);
821                         break;
822
823                 case OPT_INCLUDE:
824                         parse_rule(&filter_list, poptGetOptArg(pc),
825                                    MATCHFLG_INCLUDE, XFLG_OLD_PREFIXES);
826                         break;
827
828                 case OPT_EXCLUDE_FROM:
829                 case OPT_INCLUDE_FROM:
830                         arg = poptGetOptArg(pc);
831                         if (sanitize_paths)
832                                 arg = sanitize_path(NULL, arg, NULL, 0);
833                         if (server_filter_list.head) {
834                                 char *cp = (char *)arg;
835                                 if (!*cp)
836                                         goto options_rejected;
837                                 clean_fname(cp, 1);
838                                 if (check_filter(&server_filter_list, cp, 0) < 0)
839                                         goto options_rejected;
840                         }
841                         parse_filter_file(&filter_list, arg,
842                                 opt == OPT_INCLUDE_FROM ? MATCHFLG_INCLUDE : 0,
843                                 XFLG_FATAL_ERRORS | XFLG_OLD_PREFIXES);
844                         break;
845
846                 case 'a':
847                         if (refused_archive_part) {
848                                 create_refuse_error(refused_archive_part);
849                                 return 0;
850                         }
851                         if (!recurse) /* preserve recurse == 2 */
852                                 recurse = 1;
853 #ifdef SUPPORT_LINKS
854                         preserve_links = 1;
855 #endif
856                         preserve_perms = 1;
857                         preserve_times = 1;
858                         preserve_gid = 1;
859                         preserve_uid = 1;
860                         preserve_devices = 1;
861                         break;
862
863                 case 'h':
864                         usage(FINFO);
865                         exit_cleanup(0);
866
867                 case 'v':
868                         verbose++;
869                         break;
870
871                 case 'q':
872                         if (frommain)
873                                 quiet++;
874                         break;
875
876                 case OPT_SENDER:
877                         if (!am_server) {
878                                 usage(FERROR);
879                                 exit_cleanup(RERR_SYNTAX);
880                         }
881                         am_sender = 1;
882                         break;
883
884                 case 'F':
885                         switch (++F_option_cnt) {
886                         case 1:
887                                 parse_rule(&filter_list,": /.rsync-filter",0,0);
888                                 break;
889                         case 2:
890                                 parse_rule(&filter_list,"- .rsync-filter",0,0);
891                                 break;
892                         }
893                         break;
894
895                 case 'P':
896                         if (refused_partial || refused_progress) {
897                                 create_refuse_error(refused_partial
898                                     ? refused_partial : refused_progress);
899                                 return 0;
900                         }
901                         do_progress = 1;
902                         keep_partial = 1;
903                         break;
904
905                 case OPT_WRITE_BATCH:
906                         /* batch_name is already set */
907                         write_batch = 1;
908                         break;
909
910                 case OPT_ONLY_WRITE_BATCH:
911                         /* batch_name is already set */
912                         write_batch = -1;
913                         break;
914
915                 case OPT_READ_BATCH:
916                         /* batch_name is already set */
917                         read_batch = 1;
918                         break;
919
920                 case OPT_MAX_SIZE:
921                         if ((max_size = parse_size_arg(&max_size_arg, 'b')) <= 0) {
922                                 snprintf(err_buf, sizeof err_buf,
923                                         "--max-size value is invalid: %s\n",
924                                         max_size_arg);
925                                 return 0;
926                         }
927                         break;
928
929                 case OPT_MIN_SIZE:
930                         if ((min_size = parse_size_arg(&min_size_arg, 'b')) <= 0) {
931                                 snprintf(err_buf, sizeof err_buf,
932                                         "--min-size value is invalid: %s\n",
933                                         min_size_arg);
934                                 return 0;
935                         }
936                         break;
937
938                 case OPT_LINK_DEST:
939 #ifdef HAVE_LINK
940                         link_dest = 1;
941                         dest_option = "--link-dest";
942                         goto set_dest_dir;
943 #else
944                         snprintf(err_buf, sizeof err_buf,
945                                  "hard links are not supported on this %s\n",
946                                  am_server ? "server" : "client");
947                         return 0;
948 #endif
949
950                 case OPT_COPY_DEST:
951                         copy_dest = 1;
952                         dest_option = "--copy-dest";
953                         goto set_dest_dir;
954
955                 case OPT_COMPARE_DEST:
956                         compare_dest = 1;
957                         dest_option = "--compare-dest";
958                 set_dest_dir:
959                         if (basis_dir_cnt >= MAX_BASIS_DIRS) {
960                                 snprintf(err_buf, sizeof err_buf,
961                                         "ERROR: at most %d %s args may be specified\n",
962                                         MAX_BASIS_DIRS, dest_option);
963                                 return 0;
964                         }
965                         arg = poptGetOptArg(pc);
966                         if (sanitize_paths)
967                                 arg = sanitize_path(NULL, arg, NULL, 0);
968                         basis_dir[basis_dir_cnt++] = (char *)arg;
969                         break;
970
971                 default:
972                         /* A large opt value means that set_refuse_options()
973                          * turned this option off. */
974                         if (opt >= OPT_REFUSED_BASE) {
975                                 create_refuse_error(opt);
976                                 return 0;
977                         }
978                         snprintf(err_buf, sizeof err_buf, "%s%s: %s\n",
979                                  am_server ? "on remote machine: " : "",
980                                  poptBadOption(pc, POPT_BADOPTION_NOALIAS),
981                                  poptStrerror(opt));
982                         return 0;
983                 }
984         }
985
986 #ifndef SUPPORT_LINKS
987         if (preserve_links && !am_sender) {
988                 snprintf(err_buf, sizeof err_buf,
989                          "symlinks are not supported on this %s\n",
990                          am_server ? "server" : "client");
991                 return 0;
992         }
993 #endif
994
995 #ifndef SUPPORT_HARD_LINKS
996         if (preserve_hard_links) {
997                 snprintf(err_buf, sizeof err_buf,
998                          "hard links are not supported on this %s\n",
999                          am_server ? "server" : "client");
1000                 return 0;
1001         }
1002 #endif
1003
1004         if (write_batch && read_batch) {
1005                 snprintf(err_buf, sizeof err_buf,
1006                         "--write-batch and --read-batch can not be used together\n");
1007                 return 0;
1008         }
1009         if (write_batch > 0 || read_batch) {
1010                 if (am_server) {
1011                         rprintf(FINFO,
1012                                 "ignoring --%s-batch option sent to server\n",
1013                                 write_batch ? "write" : "read");
1014                         /* We don't actually exit_cleanup(), so that we can
1015                          * still service older version clients that still send
1016                          * batch args to server. */
1017                         read_batch = write_batch = 0;
1018                         batch_name = NULL;
1019                 } else if (dry_run)
1020                         write_batch = 0;
1021         }
1022         if (read_batch && files_from) {
1023                 snprintf(err_buf, sizeof err_buf,
1024                         "--read-batch cannot be used with --files-from\n");
1025                 return 0;
1026         }
1027         if (batch_name && strlen(batch_name) > MAX_BATCH_NAME_LEN) {
1028                 snprintf(err_buf, sizeof err_buf,
1029                         "the batch-file name must be %d characters or less.\n",
1030                         MAX_BATCH_NAME_LEN);
1031                 return 0;
1032         }
1033
1034         if (tmpdir && strlen(tmpdir) >= MAXPATHLEN - 10) {
1035                 snprintf(err_buf, sizeof err_buf,
1036                          "the --temp-dir path is WAY too long.\n");
1037                 return 0;
1038         }
1039
1040         if (compare_dest + copy_dest + link_dest > 1) {
1041                 snprintf(err_buf, sizeof err_buf,
1042                         "You may not mix --compare-dest, --copy-dest, and --link-dest.\n");
1043                 return 0;
1044         }
1045
1046         if (files_from) {
1047                 if (recurse == 1) /* preserve recurse == 2 */
1048                         recurse = 0;
1049                 if (xfer_dirs < 0)
1050                         xfer_dirs = 1;
1051         }
1052
1053         if (xfer_dirs < 1)
1054                 xfer_dirs = recurse || list_only;
1055
1056         if (relative_paths < 0)
1057                 relative_paths = files_from? 1 : 0;
1058         if (!relative_paths)
1059                 implied_dirs = 0;
1060
1061         if (!!delete_before + delete_during + delete_after > 1) {
1062                 snprintf(err_buf, sizeof err_buf,
1063                         "You may not combine multiple --delete-WHEN options.\n");
1064                 return 0;
1065         }
1066         if (!xfer_dirs) {
1067                 delete_before = delete_during = delete_after = 0;
1068                 delete_mode = delete_excluded = 0;
1069         } else if (delete_before || delete_during || delete_after)
1070                 delete_mode = 1;
1071         else if (delete_mode || delete_excluded) {
1072                 if (refused_delete_before) {
1073                         create_refuse_error(refused_delete_before);
1074                         return 0;
1075                 }
1076                 delete_mode = delete_before = 1;
1077         }
1078
1079         if (delete_mode && refused_delete) {
1080                 create_refuse_error(refused_delete);
1081                 return 0;
1082         }
1083
1084         if (remove_sent_files) {
1085                 /* We only want to infer this refusal of --remove-sent-files
1086                  * via the refusal of "delete", not any of the "delete-FOO"
1087                  * options. */
1088                 if (refused_delete && am_sender) {
1089                         create_refuse_error(refused_delete);
1090                         return 0;
1091                 }
1092                 need_messages_from_generator = 1;
1093         }
1094
1095         *argv = poptGetArgs(pc);
1096         *argc = count_args(*argv);
1097
1098         if (sanitize_paths) {
1099                 int i;
1100                 for (i = *argc; i-- > 0; )
1101                         (*argv)[i] = sanitize_path(NULL, (*argv)[i], "", 0);
1102                 if (tmpdir)
1103                         tmpdir = sanitize_path(NULL, tmpdir, NULL, 0);
1104                 if (partial_dir)
1105                         partial_dir = sanitize_path(NULL, partial_dir, NULL, 0);
1106                 if (backup_dir)
1107                         backup_dir = sanitize_path(NULL, backup_dir, NULL, 0);
1108         }
1109         if (server_filter_list.head && !am_sender) {
1110                 struct filter_list_struct *elp = &server_filter_list;
1111                 int i;
1112                 if (tmpdir) {
1113                         if (!*tmpdir)
1114                                 goto options_rejected;
1115                         clean_fname(tmpdir, 1);
1116                         if (check_filter(elp, tmpdir, 1) < 0)
1117                                 goto options_rejected;
1118                 }
1119                 if (partial_dir && *partial_dir) {
1120                         clean_fname(partial_dir, 1);
1121                         if (check_filter(elp, partial_dir, 1) < 0)
1122                                 goto options_rejected;
1123                 }
1124                 for (i = 0; i < basis_dir_cnt; i++) {
1125                         if (!*basis_dir[i])
1126                                 goto options_rejected;
1127                         clean_fname(basis_dir[i], 1);
1128                         if (check_filter(elp, basis_dir[i], 1) < 0)
1129                                 goto options_rejected;
1130                 }
1131                 if (backup_dir) {
1132                         if (!*backup_dir)
1133                                 goto options_rejected;
1134                         clean_fname(backup_dir, 1);
1135                         if (check_filter(elp, backup_dir, 1) < 0) {
1136                             options_rejected:
1137                                 snprintf(err_buf, sizeof err_buf,
1138                                     "Your options have been rejected by the server.\n");
1139                                 return 0;
1140                         }
1141                 }
1142         }
1143
1144         if (!backup_suffix)
1145                 backup_suffix = backup_dir ? "" : BACKUP_SUFFIX;
1146         backup_suffix_len = strlen(backup_suffix);
1147         if (strchr(backup_suffix, '/') != NULL) {
1148                 snprintf(err_buf, sizeof err_buf,
1149                         "--suffix cannot contain slashes: %s\n",
1150                         backup_suffix);
1151                 return 0;
1152         }
1153         if (backup_dir) {
1154                 backup_dir_len = strlcpy(backup_dir_buf, backup_dir, sizeof backup_dir_buf);
1155                 backup_dir_remainder = sizeof backup_dir_buf - backup_dir_len;
1156                 if (backup_dir_remainder < 32) {
1157                         snprintf(err_buf, sizeof err_buf,
1158                                 "the --backup-dir path is WAY too long.\n");
1159                         return 0;
1160                 }
1161                 if (backup_dir_buf[backup_dir_len - 1] != '/') {
1162                         backup_dir_buf[backup_dir_len++] = '/';
1163                         backup_dir_buf[backup_dir_len] = '\0';
1164                 }
1165                 if (verbose > 1 && !am_sender) {
1166                         rprintf(FINFO, "backup_dir is %s\n",
1167                                 safe_fname(backup_dir_buf));
1168                 }
1169         } else if (!backup_suffix_len && (!am_server || !am_sender)) {
1170                 snprintf(err_buf, sizeof err_buf,
1171                         "--suffix cannot be a null string without --backup-dir\n");
1172                 return 0;
1173         }
1174         if (make_backups && !backup_dir)
1175                 omit_dir_times = 1;
1176
1177         if (log_format) {
1178                 if (log_format_has(log_format, 'i'))
1179                         log_format_has_i = 1;
1180                 if (!log_format_has(log_format, 'b')
1181                  && !log_format_has(log_format, 'c'))
1182                         log_before_transfer = !am_server;
1183         } else if (itemize_changes) {
1184                 log_format = "%i %n%L";
1185                 log_format_has_i = 1;
1186                 log_before_transfer = !am_server;
1187         }
1188
1189         if ((do_progress || dry_run) && !verbose && !log_before_transfer
1190             && !am_server)
1191                 verbose = 1;
1192
1193         if (dry_run)
1194                 do_xfers = 0;
1195
1196         set_io_timeout(io_timeout);
1197
1198         if (verbose && !log_format) {
1199                 log_format = "%n%L";
1200                 log_before_transfer = !am_server;
1201         }
1202         if (log_format_has_i || log_format_has(log_format, 'o'))
1203                 log_format_has_o_or_i = 1;
1204
1205         if (daemon_bwlimit && (!bwlimit || bwlimit > daemon_bwlimit))
1206                 bwlimit = daemon_bwlimit;
1207         if (bwlimit) {
1208                 bwlimit_writemax = (size_t)bwlimit * 128;
1209                 if (bwlimit_writemax < 512)
1210                         bwlimit_writemax = 512;
1211         }
1212
1213         if (sparse_files && inplace) {
1214                 /* Note: we don't check for this below, because --append is
1215                  * OK with --sparse (as long as redos are handled right). */
1216                 snprintf(err_buf, sizeof err_buf,
1217                          "--sparse cannot be used with --inplace\n");
1218                 return 0;
1219         }
1220
1221         if (append_mode) {
1222                 if (whole_file > 0) {
1223                         snprintf(err_buf, sizeof err_buf,
1224                                  "--append cannot be used with --whole-file\n");
1225                         return 0;
1226                 }
1227                 if (refused_inplace) {
1228                         create_refuse_error(refused_inplace);
1229                         return 0;
1230                 }
1231                 inplace = 1;
1232         }
1233
1234         if (delay_updates && !partial_dir)
1235                 partial_dir = partialdir_for_delayupdate;
1236
1237         if (inplace) {
1238 #ifdef HAVE_FTRUNCATE
1239                 if (partial_dir) {
1240                         snprintf(err_buf, sizeof err_buf,
1241                                  "--%s cannot be used with --%s\n",
1242                                  append_mode ? "append" : "inplace",
1243                                  delay_updates ? "delay-updates" : "partial-dir");
1244                         return 0;
1245                 }
1246                 /* --inplace implies --partial for refusal purposes, but we
1247                  * clear the keep_partial flag for internal logic purposes. */
1248                 if (refused_partial) {
1249                         create_refuse_error(refused_partial);
1250                         return 0;
1251                 }
1252                 keep_partial = 0;
1253 #else
1254                 snprintf(err_buf, sizeof err_buf,
1255                          "--%s is not supported on this %s\n",
1256                          append_mode ? "append" : "inplace",
1257                          am_server ? "server" : "client");
1258                 return 0;
1259 #endif
1260         } else {
1261                 if (keep_partial && !partial_dir) {
1262                         if ((arg = getenv("RSYNC_PARTIAL_DIR")) != NULL && *arg)
1263                                 partial_dir = strdup(arg);
1264                 }
1265                 if (partial_dir) {
1266                         if (*partial_dir)
1267                                 clean_fname(partial_dir, 1);
1268                         if (!*partial_dir || strcmp(partial_dir, ".") == 0)
1269                                 partial_dir = NULL;
1270                         else if (*partial_dir != '/') {
1271                                 parse_rule(&filter_list, partial_dir,
1272                                     MATCHFLG_NO_PREFIXES|MATCHFLG_DIRECTORY, 0);
1273                         }
1274                         if (!partial_dir && refused_partial) {
1275                                 create_refuse_error(refused_partial);
1276                                 return 0;
1277                         }
1278                         keep_partial = 1;
1279                 }
1280         }
1281
1282         if (files_from) {
1283                 char *h, *p;
1284                 int q;
1285                 if (*argc > 2 || (!am_daemon && *argc == 1)) {
1286                         usage(FERROR);
1287                         exit_cleanup(RERR_SYNTAX);
1288                 }
1289                 if (strcmp(files_from, "-") == 0) {
1290                         filesfrom_fd = 0;
1291                         if (am_server)
1292                                 filesfrom_host = ""; /* reading from socket */
1293                 } else if ((p = check_for_hostspec(files_from, &h, &q)) != 0) {
1294                         if (am_server) {
1295                                 snprintf(err_buf, sizeof err_buf,
1296                                         "The --files-from sent to the server cannot specify a host.\n");
1297                                 return 0;
1298                         }
1299                         files_from = p;
1300                         filesfrom_host = h;
1301                         if (strcmp(files_from, "-") == 0) {
1302                                 snprintf(err_buf, sizeof err_buf,
1303                                         "Invalid --files-from remote filename\n");
1304                                 return 0;
1305                         }
1306                 } else {
1307                         if (sanitize_paths)
1308                                 files_from = sanitize_path(NULL, files_from, NULL, 0);
1309                         if (server_filter_list.head) {
1310                                 if (!*files_from)
1311                                         goto options_rejected;
1312                                 clean_fname(files_from, 1);
1313                                 if (check_filter(&server_filter_list, files_from, 0) < 0)
1314                                         goto options_rejected;
1315                         }
1316                         filesfrom_fd = open(files_from, O_RDONLY|O_BINARY);
1317                         if (filesfrom_fd < 0) {
1318                                 snprintf(err_buf, sizeof err_buf,
1319                                         "failed to open files-from file %s: %s\n",
1320                                         files_from, strerror(errno));
1321                                 return 0;
1322                         }
1323                 }
1324         }
1325
1326         am_starting_up = 0;
1327
1328         return 1;
1329 }
1330
1331
1332 /**
1333  * Construct a filtered list of options to pass through from the
1334  * client to the server.
1335  *
1336  * This involves setting options that will tell the server how to
1337  * behave, and also filtering out options that are processed only
1338  * locally.
1339  **/
1340 void server_options(char **args,int *argc)
1341 {
1342         static char argstr[64];
1343         int ac = *argc;
1344         char *arg;
1345
1346         int i, x;
1347
1348         if (blocking_io == -1)
1349                 blocking_io = 0;
1350
1351         args[ac++] = "--server";
1352
1353         if (daemon_over_rsh) {
1354                 args[ac++] = "--daemon";
1355                 *argc = ac;
1356                 /* if we're passing --daemon, we're done */
1357                 return;
1358         }
1359
1360         if (!am_sender)
1361                 args[ac++] = "--sender";
1362
1363         x = 1;
1364         argstr[0] = '-';
1365         for (i = 0; i < verbose; i++)
1366                 argstr[x++] = 'v';
1367
1368         /* the -q option is intentionally left out */
1369         if (make_backups)
1370                 argstr[x++] = 'b';
1371         if (update_only)
1372                 argstr[x++] = 'u';
1373         if (!do_xfers) /* NOT "dry_run"! */
1374                 argstr[x++] = 'n';
1375         if (preserve_links)
1376                 argstr[x++] = 'l';
1377         if (copy_links)
1378                 argstr[x++] = 'L';
1379         if (xfer_dirs > 1)
1380                 argstr[x++] = 'd';
1381         if (keep_dirlinks && am_sender)
1382                 argstr[x++] = 'K';
1383
1384         if (whole_file > 0)
1385                 argstr[x++] = 'W';
1386         /* We don't need to send --no-whole-file, because it's the
1387          * default for remote transfers, and in any case old versions
1388          * of rsync will not understand it. */
1389
1390         if (preserve_hard_links)
1391                 argstr[x++] = 'H';
1392         if (preserve_uid)
1393                 argstr[x++] = 'o';
1394         if (preserve_gid)
1395                 argstr[x++] = 'g';
1396         if (preserve_devices)
1397                 argstr[x++] = 'D';
1398         if (preserve_times)
1399                 argstr[x++] = 't';
1400         if (omit_dir_times == 2 && am_sender)
1401                 argstr[x++] = 'O';
1402         if (preserve_perms)
1403                 argstr[x++] = 'p';
1404         if (recurse)
1405                 argstr[x++] = 'r';
1406         if (always_checksum)
1407                 argstr[x++] = 'c';
1408         if (cvs_exclude)
1409                 argstr[x++] = 'C';
1410         if (ignore_times)
1411                 argstr[x++] = 'I';
1412         if (relative_paths)
1413                 argstr[x++] = 'R';
1414         if (one_file_system)
1415                 argstr[x++] = 'x';
1416         if (sparse_files)
1417                 argstr[x++] = 'S';
1418         if (do_compression)
1419                 argstr[x++] = 'z';
1420
1421         /* This is a complete hack - blame Rusty.  FIXME!
1422          * This hack is only needed for older rsync versions that
1423          * don't understand the --list-only option. */
1424         if (list_only == 1 && !recurse)
1425                 argstr[x++] = 'r';
1426
1427         argstr[x] = 0;
1428
1429         if (x != 1)
1430                 args[ac++] = argstr;
1431
1432         if (list_only > 1)
1433                 args[ac++] = "--list-only";
1434
1435         /* The server side doesn't use our log-format, but in certain
1436          * circumstances they need to know a little about the option. */
1437         if (log_format && am_sender) {
1438                 if (log_format_has_i)
1439                         args[ac++] = "--log-format=%i";
1440                 else if (log_format_has_o_or_i)
1441                         args[ac++] = "--log-format=%o";
1442                 else if (!verbose)
1443                         args[ac++] = "--log-format=X";
1444         }
1445
1446         if (block_size) {
1447                 if (asprintf(&arg, "-B%lu", block_size) < 0)
1448                         goto oom;
1449                 args[ac++] = arg;
1450         }
1451
1452         if (max_delete && am_sender) {
1453                 if (asprintf(&arg, "--max-delete=%d", max_delete) < 0)
1454                         goto oom;
1455                 args[ac++] = arg;
1456         }
1457
1458         if (min_size && am_sender) {
1459                 args[ac++] = "--min-size";
1460                 args[ac++] = min_size_arg;
1461         }
1462
1463         if (max_size && am_sender) {
1464                 args[ac++] = "--max-size";
1465                 args[ac++] = max_size_arg;
1466         }
1467
1468         if (io_timeout) {
1469                 if (asprintf(&arg, "--timeout=%d", io_timeout) < 0)
1470                         goto oom;
1471                 args[ac++] = arg;
1472         }
1473
1474         if (bwlimit) {
1475                 if (asprintf(&arg, "--bwlimit=%d", bwlimit) < 0)
1476                         goto oom;
1477                 args[ac++] = arg;
1478         }
1479
1480         if (backup_dir) {
1481                 args[ac++] = "--backup-dir";
1482                 args[ac++] = backup_dir;
1483         }
1484
1485         /* Only send --suffix if it specifies a non-default value. */
1486         if (strcmp(backup_suffix, backup_dir ? "" : BACKUP_SUFFIX) != 0) {
1487                 /* We use the following syntax to avoid weirdness with '~'. */
1488                 if (asprintf(&arg, "--suffix=%s", backup_suffix) < 0)
1489                         goto oom;
1490                 args[ac++] = arg;
1491         }
1492
1493         if (am_sender) {
1494                 if (delete_excluded)
1495                         args[ac++] = "--delete-excluded";
1496                 else if (delete_before == 1 || delete_after)
1497                         args[ac++] = "--delete";
1498                 if (delete_before > 1)
1499                         args[ac++] = "--delete-before";
1500                 if (delete_during)
1501                         args[ac++] = "--delete-during";
1502                 if (delete_after)
1503                         args[ac++] = "--delete-after";
1504                 if (force_delete)
1505                         args[ac++] = "--force";
1506                 if (write_batch < 0)
1507                         args[ac++] = "--only-write-batch=X";
1508         }
1509
1510         if (size_only)
1511                 args[ac++] = "--size-only";
1512
1513         if (modify_window_set) {
1514                 if (asprintf(&arg, "--modify-window=%d", modify_window) < 0)
1515                         goto oom;
1516                 args[ac++] = arg;
1517         }
1518
1519         if (checksum_seed) {
1520                 if (asprintf(&arg, "--checksum-seed=%d", checksum_seed) < 0)
1521                         goto oom;
1522                 args[ac++] = arg;
1523         }
1524
1525         if (partial_dir && am_sender) {
1526                 if (partial_dir != partialdir_for_delayupdate) {
1527                         args[ac++] = "--partial-dir";
1528                         args[ac++] = partial_dir;
1529                 }
1530                 if (delay_updates)
1531                         args[ac++] = "--delay-updates";
1532         } else if (keep_partial)
1533                 args[ac++] = "--partial";
1534
1535         if (ignore_errors)
1536                 args[ac++] = "--ignore-errors";
1537
1538         if (copy_unsafe_links)
1539                 args[ac++] = "--copy-unsafe-links";
1540
1541         if (safe_symlinks)
1542                 args[ac++] = "--safe-links";
1543
1544         if (numeric_ids)
1545                 args[ac++] = "--numeric-ids";
1546
1547         if (ignore_existing && am_sender)
1548                 args[ac++] = "--ignore-existing";
1549
1550         /* Backward compatibility: send --existing, not --ignore-non-existing. */
1551         if (ignore_non_existing && am_sender)
1552                 args[ac++] = "--existing";
1553
1554         if (append_mode)
1555                 args[ac++] = "--append";
1556         else if (inplace)
1557                 args[ac++] = "--inplace";
1558
1559         if (tmpdir) {
1560                 args[ac++] = "--temp-dir";
1561                 args[ac++] = tmpdir;
1562         }
1563
1564         if (basis_dir[0] && am_sender) {
1565                 /* the server only needs this option if it is not the sender,
1566                  *   and it may be an older version that doesn't know this
1567                  *   option, so don't send it if client is the sender.
1568                  */
1569                 int i;
1570                 for (i = 0; i < basis_dir_cnt; i++) {
1571                         args[ac++] = dest_option;
1572                         args[ac++] = basis_dir[i];
1573                 }
1574         }
1575
1576         if (files_from && (!am_sender || filesfrom_host)) {
1577                 if (filesfrom_host) {
1578                         args[ac++] = "--files-from";
1579                         args[ac++] = files_from;
1580                         if (eol_nulls)
1581                                 args[ac++] = "--from0";
1582                 } else {
1583                         args[ac++] = "--files-from=-";
1584                         args[ac++] = "--from0";
1585                 }
1586                 if (!relative_paths)
1587                         args[ac++] = "--no-relative";
1588         }
1589         if (relative_paths && !implied_dirs && !am_sender)
1590                 args[ac++] = "--no-implied-dirs";
1591
1592         if (fuzzy_basis && am_sender)
1593                 args[ac++] = "--fuzzy";
1594
1595         if (remove_sent_files)
1596                 args[ac++] = "--remove-sent-files";
1597
1598         *argc = ac;
1599         return;
1600
1601     oom:
1602         out_of_memory("server_options");
1603 }
1604
1605 /* Look for a HOST specfication of the form "HOST:PATH", "HOST::PATH", or
1606  * "rsync://HOST:PORT/PATH".  If found, *host_ptr will be set to some allocated
1607  * memory with the HOST.  If a daemon-accessing spec was specified, the value
1608  * of *port_ptr will contain a non-0 port number, otherwise it will be set to
1609  * 0.  The return value is a pointer to the PATH.  Note that the HOST spec can
1610  * be an IPv6 literal address enclosed in '[' and ']' (such as "[::1]" or
1611  * "[::ffff:127.0.0.1]") which is returned without the '[' and ']'. */
1612 char *check_for_hostspec(char *s, char **host_ptr, int *port_ptr)
1613 {
1614         char *p;
1615         int not_host;
1616
1617         if (port_ptr && strncasecmp(URL_PREFIX, s, strlen(URL_PREFIX)) == 0) {
1618                 char *path;
1619                 int hostlen;
1620                 s += strlen(URL_PREFIX);
1621                 if ((p = strchr(s, '/')) != NULL) {
1622                         hostlen = p - s;
1623                         path = p + 1;
1624                 } else {
1625                         hostlen = strlen(s);
1626                         path = "";
1627                 }
1628                 if (*s == '[' && (p = strchr(s, ']')) != NULL) {
1629                         s++;
1630                         hostlen = p - s;
1631                         if (p[1] == ':')
1632                                 *port_ptr = atoi(p+2);
1633                 } else {
1634                         if ((p = strchr(s, ':')) != NULL) {
1635                                 hostlen = p - s;
1636                                 *port_ptr = atoi(p+1);
1637                         }
1638                 }
1639                 if (!*port_ptr)
1640                         *port_ptr = RSYNC_PORT;
1641                 *host_ptr = new_array(char, hostlen + 1);
1642                 strlcpy(*host_ptr, s, hostlen + 1);
1643                 return path;
1644         }
1645
1646         if (*s == '[' && (p = strchr(s, ']')) != NULL && p[1] == ':') {
1647                 s++;
1648                 *p = '\0';
1649                 not_host = strchr(s, '/') || !strchr(s, ':');
1650                 *p = ']';
1651                 if (not_host)
1652                         return NULL;
1653                 p++;
1654         } else {
1655                 if (!(p = strchr(s, ':')))
1656                         return NULL;
1657                 *p = '\0';
1658                 not_host = strchr(s, '/') != NULL;
1659                 *p = ':';
1660                 if (not_host)
1661                         return NULL;
1662         }
1663
1664         *host_ptr = new_array(char, p - s + 1);
1665         strlcpy(*host_ptr, s, p - s + 1);
1666
1667         if (p[1] == ':') {
1668                 if (port_ptr && !*port_ptr)
1669                         *port_ptr = RSYNC_PORT;
1670                 return p + 2;
1671         }
1672         if (port_ptr)
1673                 *port_ptr = 0;
1674
1675         return p + 1;
1676 }