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