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