Made --existing the main option, with --ignore-non-existing
[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",
1204                                 safe_fname(backup_dir_buf));
1205                 }
1206         } else if (!backup_suffix_len && (!am_server || !am_sender)) {
1207                 snprintf(err_buf, sizeof err_buf,
1208                         "--suffix cannot be a null string without --backup-dir\n");
1209                 return 0;
1210         } else if (delete_mode && !delete_excluded) {
1211                 snprintf(backup_dir_buf, sizeof backup_dir_buf,
1212                         "P *%s", backup_suffix);
1213                 parse_rule(&filter_list, backup_dir_buf, 0, 0);
1214         }
1215         if (make_backups && !backup_dir)
1216                 omit_dir_times = 1;
1217
1218         if (chmod_mode && !(chmod_modes = parse_chmod(chmod_mode))) {
1219                 snprintf(err_buf, sizeof err_buf,
1220                     "Invalid argument passed to chmod\n");
1221                 return 0;
1222         }
1223
1224         if (log_format) {
1225                 if (log_format_has(log_format, 'i'))
1226                         log_format_has_i = 1;
1227                 if (!log_format_has(log_format, 'b')
1228                  && !log_format_has(log_format, 'c'))
1229                         log_before_transfer = !am_server;
1230         } else if (itemize_changes) {
1231                 log_format = "%i %n%L";
1232                 log_format_has_i = 1;
1233                 log_before_transfer = !am_server;
1234         }
1235
1236         if ((do_progress || dry_run) && !verbose && !log_before_transfer
1237             && !am_server)
1238                 verbose = 1;
1239
1240         if (dry_run)
1241                 do_xfers = 0;
1242
1243         set_io_timeout(io_timeout);
1244
1245         if (verbose && !log_format) {
1246                 log_format = "%n%L";
1247                 log_before_transfer = !am_server;
1248         }
1249         if (log_format_has_i || log_format_has(log_format, 'o'))
1250                 log_format_has_o_or_i = 1;
1251
1252         if (daemon_bwlimit && (!bwlimit || bwlimit > daemon_bwlimit))
1253                 bwlimit = daemon_bwlimit;
1254         if (bwlimit) {
1255                 bwlimit_writemax = (size_t)bwlimit * 128;
1256                 if (bwlimit_writemax < 512)
1257                         bwlimit_writemax = 512;
1258         }
1259
1260         if (sparse_files && inplace) {
1261                 /* Note: we don't check for this below, because --append is
1262                  * OK with --sparse (as long as redos are handled right). */
1263                 snprintf(err_buf, sizeof err_buf,
1264                          "--sparse cannot be used with --inplace\n");
1265                 return 0;
1266         }
1267
1268         if (append_mode) {
1269                 if (whole_file > 0) {
1270                         snprintf(err_buf, sizeof err_buf,
1271                                  "--append cannot be used with --whole-file\n");
1272                         return 0;
1273                 }
1274                 if (refused_inplace) {
1275                         create_refuse_error(refused_inplace);
1276                         return 0;
1277                 }
1278                 inplace = 1;
1279         }
1280
1281         if (delay_updates && !partial_dir)
1282                 partial_dir = partialdir_for_delayupdate;
1283
1284         if (inplace) {
1285 #ifdef HAVE_FTRUNCATE
1286                 if (partial_dir) {
1287                         snprintf(err_buf, sizeof err_buf,
1288                                  "--%s cannot be used with --%s\n",
1289                                  append_mode ? "append" : "inplace",
1290                                  delay_updates ? "delay-updates" : "partial-dir");
1291                         return 0;
1292                 }
1293                 /* --inplace implies --partial for refusal purposes, but we
1294                  * clear the keep_partial flag for internal logic purposes. */
1295                 if (refused_partial) {
1296                         create_refuse_error(refused_partial);
1297                         return 0;
1298                 }
1299                 keep_partial = 0;
1300 #else
1301                 snprintf(err_buf, sizeof err_buf,
1302                          "--%s is not supported on this %s\n",
1303                          append_mode ? "append" : "inplace",
1304                          am_server ? "server" : "client");
1305                 return 0;
1306 #endif
1307         } else {
1308                 if (keep_partial && !partial_dir) {
1309                         if ((arg = getenv("RSYNC_PARTIAL_DIR")) != NULL && *arg)
1310                                 partial_dir = strdup(arg);
1311                 }
1312                 if (partial_dir) {
1313                         if (*partial_dir)
1314                                 clean_fname(partial_dir, 1);
1315                         if (!*partial_dir || strcmp(partial_dir, ".") == 0)
1316                                 partial_dir = NULL;
1317                         else if (*partial_dir != '/') {
1318                                 parse_rule(&filter_list, partial_dir,
1319                                     MATCHFLG_NO_PREFIXES|MATCHFLG_DIRECTORY, 0);
1320                         }
1321                         if (!partial_dir && refused_partial) {
1322                                 create_refuse_error(refused_partial);
1323                                 return 0;
1324                         }
1325                         keep_partial = 1;
1326                 }
1327         }
1328
1329         if (files_from) {
1330                 char *h, *p;
1331                 int q;
1332                 if (*argc > 2 || (!am_daemon && *argc == 1)) {
1333                         usage(FERROR);
1334                         exit_cleanup(RERR_SYNTAX);
1335                 }
1336                 if (strcmp(files_from, "-") == 0) {
1337                         filesfrom_fd = 0;
1338                         if (am_server)
1339                                 filesfrom_host = ""; /* reading from socket */
1340                 } else if ((p = check_for_hostspec(files_from, &h, &q)) != 0) {
1341                         if (am_server) {
1342                                 snprintf(err_buf, sizeof err_buf,
1343                                         "The --files-from sent to the server cannot specify a host.\n");
1344                                 return 0;
1345                         }
1346                         files_from = p;
1347                         filesfrom_host = h;
1348                         if (strcmp(files_from, "-") == 0) {
1349                                 snprintf(err_buf, sizeof err_buf,
1350                                         "Invalid --files-from remote filename\n");
1351                                 return 0;
1352                         }
1353                 } else {
1354                         if (sanitize_paths)
1355                                 files_from = sanitize_path(NULL, files_from, NULL, 0);
1356                         if (server_filter_list.head) {
1357                                 if (!*files_from)
1358                                         goto options_rejected;
1359                                 clean_fname(files_from, 1);
1360                                 if (check_filter(&server_filter_list, files_from, 0) < 0)
1361                                         goto options_rejected;
1362                         }
1363                         filesfrom_fd = open(files_from, O_RDONLY|O_BINARY);
1364                         if (filesfrom_fd < 0) {
1365                                 snprintf(err_buf, sizeof err_buf,
1366                                         "failed to open files-from file %s: %s\n",
1367                                         files_from, strerror(errno));
1368                                 return 0;
1369                         }
1370                 }
1371         }
1372
1373         am_starting_up = 0;
1374
1375         return 1;
1376 }
1377
1378
1379 /**
1380  * Construct a filtered list of options to pass through from the
1381  * client to the server.
1382  *
1383  * This involves setting options that will tell the server how to
1384  * behave, and also filtering out options that are processed only
1385  * locally.
1386  **/
1387 void server_options(char **args,int *argc)
1388 {
1389         static char argstr[64];
1390         int ac = *argc;
1391         char *arg;
1392
1393         int i, x;
1394
1395         if (blocking_io == -1)
1396                 blocking_io = 0;
1397
1398         args[ac++] = "--server";
1399
1400         if (daemon_over_rsh) {
1401                 args[ac++] = "--daemon";
1402                 *argc = ac;
1403                 /* if we're passing --daemon, we're done */
1404                 return;
1405         }
1406
1407         if (!am_sender)
1408                 args[ac++] = "--sender";
1409
1410         x = 1;
1411         argstr[0] = '-';
1412         for (i = 0; i < verbose; i++)
1413                 argstr[x++] = 'v';
1414
1415         /* the -q option is intentionally left out */
1416         if (make_backups)
1417                 argstr[x++] = 'b';
1418         if (update_only)
1419                 argstr[x++] = 'u';
1420         if (!do_xfers) /* NOT "dry_run"! */
1421                 argstr[x++] = 'n';
1422         if (preserve_links)
1423                 argstr[x++] = 'l';
1424         if (copy_links)
1425                 argstr[x++] = 'L';
1426         if (xfer_dirs > 1)
1427                 argstr[x++] = 'd';
1428         if (keep_dirlinks && am_sender)
1429                 argstr[x++] = 'K';
1430
1431         if (whole_file > 0)
1432                 argstr[x++] = 'W';
1433         /* We don't need to send --no-whole-file, because it's the
1434          * default for remote transfers, and in any case old versions
1435          * of rsync will not understand it. */
1436
1437         if (preserve_hard_links)
1438                 argstr[x++] = 'H';
1439         if (preserve_uid)
1440                 argstr[x++] = 'o';
1441         if (preserve_gid)
1442                 argstr[x++] = 'g';
1443         if (preserve_devices)
1444                 argstr[x++] = 'D';
1445         if (preserve_times)
1446                 argstr[x++] = 't';
1447         if (omit_dir_times == 2 && am_sender)
1448                 argstr[x++] = 'O';
1449         if (preserve_perms)
1450                 argstr[x++] = 'p';
1451         if (recurse)
1452                 argstr[x++] = 'r';
1453         if (always_checksum)
1454                 argstr[x++] = 'c';
1455         if (cvs_exclude)
1456                 argstr[x++] = 'C';
1457         if (ignore_times)
1458                 argstr[x++] = 'I';
1459         if (relative_paths)
1460                 argstr[x++] = 'R';
1461         if (one_file_system)
1462                 argstr[x++] = 'x';
1463         if (sparse_files)
1464                 argstr[x++] = 'S';
1465         if (do_compression)
1466                 argstr[x++] = 'z';
1467
1468         /* This is a complete hack - blame Rusty.  FIXME!
1469          * This hack is only needed for older rsync versions that
1470          * don't understand the --list-only option. */
1471         if (list_only == 1 && !recurse)
1472                 argstr[x++] = 'r';
1473
1474         argstr[x] = 0;
1475
1476         if (x != 1)
1477                 args[ac++] = argstr;
1478
1479         if (list_only > 1)
1480                 args[ac++] = "--list-only";
1481
1482         if (do_compression && def_compress_level != Z_DEFAULT_COMPRESSION) {
1483                 if (asprintf(&arg, "--compress-level=%d", def_compress_level) < 0)
1484                         goto oom;
1485                 args[ac++] = arg;
1486         }
1487
1488         /* The server side doesn't use our log-format, but in certain
1489          * circumstances they need to know a little about the option. */
1490         if (log_format && am_sender) {
1491                 if (log_format_has_i)
1492                         args[ac++] = "--log-format=%i";
1493                 else if (log_format_has_o_or_i)
1494                         args[ac++] = "--log-format=%o";
1495                 else if (!verbose)
1496                         args[ac++] = "--log-format=X";
1497         }
1498
1499         if (block_size) {
1500                 if (asprintf(&arg, "-B%lu", block_size) < 0)
1501                         goto oom;
1502                 args[ac++] = arg;
1503         }
1504
1505         if (max_delete && am_sender) {
1506                 if (asprintf(&arg, "--max-delete=%d", max_delete) < 0)
1507                         goto oom;
1508                 args[ac++] = arg;
1509         }
1510
1511         if (min_size && am_sender) {
1512                 args[ac++] = "--min-size";
1513                 args[ac++] = min_size_arg;
1514         }
1515
1516         if (max_size && am_sender) {
1517                 args[ac++] = "--max-size";
1518                 args[ac++] = max_size_arg;
1519         }
1520
1521         if (io_timeout) {
1522                 if (asprintf(&arg, "--timeout=%d", io_timeout) < 0)
1523                         goto oom;
1524                 args[ac++] = arg;
1525         }
1526
1527         if (bwlimit) {
1528                 if (asprintf(&arg, "--bwlimit=%d", bwlimit) < 0)
1529                         goto oom;
1530                 args[ac++] = arg;
1531         }
1532
1533         if (backup_dir) {
1534                 args[ac++] = "--backup-dir";
1535                 args[ac++] = backup_dir;
1536         }
1537
1538         /* Only send --suffix if it specifies a non-default value. */
1539         if (strcmp(backup_suffix, backup_dir ? "" : BACKUP_SUFFIX) != 0) {
1540                 /* We use the following syntax to avoid weirdness with '~'. */
1541                 if (asprintf(&arg, "--suffix=%s", backup_suffix) < 0)
1542                         goto oom;
1543                 args[ac++] = arg;
1544         }
1545
1546         if (am_sender) {
1547                 if (delete_excluded)
1548                         args[ac++] = "--delete-excluded";
1549                 else if (delete_before == 1 || delete_after)
1550                         args[ac++] = "--delete";
1551                 if (delete_before > 1)
1552                         args[ac++] = "--delete-before";
1553                 if (delete_during)
1554                         args[ac++] = "--delete-during";
1555                 if (delete_after)
1556                         args[ac++] = "--delete-after";
1557                 if (force_delete)
1558                         args[ac++] = "--force";
1559                 if (write_batch < 0)
1560                         args[ac++] = "--only-write-batch=X";
1561         }
1562
1563         if (size_only)
1564                 args[ac++] = "--size-only";
1565
1566         if (modify_window_set) {
1567                 if (asprintf(&arg, "--modify-window=%d", modify_window) < 0)
1568                         goto oom;
1569                 args[ac++] = arg;
1570         }
1571
1572         if (checksum_seed) {
1573                 if (asprintf(&arg, "--checksum-seed=%d", checksum_seed) < 0)
1574                         goto oom;
1575                 args[ac++] = arg;
1576         }
1577
1578         if (partial_dir && am_sender) {
1579                 if (partial_dir != partialdir_for_delayupdate) {
1580                         args[ac++] = "--partial-dir";
1581                         args[ac++] = partial_dir;
1582                 }
1583                 if (delay_updates)
1584                         args[ac++] = "--delay-updates";
1585         } else if (keep_partial)
1586                 args[ac++] = "--partial";
1587
1588         if (ignore_errors)
1589                 args[ac++] = "--ignore-errors";
1590
1591         if (copy_unsafe_links)
1592                 args[ac++] = "--copy-unsafe-links";
1593
1594         if (safe_symlinks)
1595                 args[ac++] = "--safe-links";
1596
1597         if (numeric_ids)
1598                 args[ac++] = "--numeric-ids";
1599
1600         if (ignore_existing && am_sender)
1601                 args[ac++] = "--ignore-existing";
1602
1603         /* Backward compatibility: send --existing, not --ignore-non-existing. */
1604         if (ignore_non_existing && am_sender)
1605                 args[ac++] = "--existing";
1606
1607         if (append_mode)
1608                 args[ac++] = "--append";
1609         else if (inplace)
1610                 args[ac++] = "--inplace";
1611
1612         if (tmpdir) {
1613                 args[ac++] = "--temp-dir";
1614                 args[ac++] = tmpdir;
1615         }
1616
1617         if (basis_dir[0] && am_sender) {
1618                 /* the server only needs this option if it is not the sender,
1619                  *   and it may be an older version that doesn't know this
1620                  *   option, so don't send it if client is the sender.
1621                  */
1622                 int i;
1623                 for (i = 0; i < basis_dir_cnt; i++) {
1624                         args[ac++] = dest_option;
1625                         args[ac++] = basis_dir[i];
1626                 }
1627         }
1628
1629         if (chmod_mode && !am_sender) {
1630                 args[ac++] = "--chmod";
1631                 args[ac++] = chmod_mode;
1632         }
1633
1634         if (files_from && (!am_sender || filesfrom_host)) {
1635                 if (filesfrom_host) {
1636                         args[ac++] = "--files-from";
1637                         args[ac++] = files_from;
1638                         if (eol_nulls)
1639                                 args[ac++] = "--from0";
1640                 } else {
1641                         args[ac++] = "--files-from=-";
1642                         args[ac++] = "--from0";
1643                 }
1644                 if (!relative_paths)
1645                         args[ac++] = "--no-relative";
1646         }
1647         if (relative_paths && !implied_dirs && !am_sender)
1648                 args[ac++] = "--no-implied-dirs";
1649
1650         if (fuzzy_basis && am_sender)
1651                 args[ac++] = "--fuzzy";
1652
1653         if (remove_sent_files)
1654                 args[ac++] = "--remove-sent-files";
1655
1656         *argc = ac;
1657         return;
1658
1659     oom:
1660         out_of_memory("server_options");
1661 }
1662
1663 /* Look for a HOST specfication of the form "HOST:PATH", "HOST::PATH", or
1664  * "rsync://HOST:PORT/PATH".  If found, *host_ptr will be set to some allocated
1665  * memory with the HOST.  If a daemon-accessing spec was specified, the value
1666  * of *port_ptr will contain a non-0 port number, otherwise it will be set to
1667  * 0.  The return value is a pointer to the PATH.  Note that the HOST spec can
1668  * be an IPv6 literal address enclosed in '[' and ']' (such as "[::1]" or
1669  * "[::ffff:127.0.0.1]") which is returned without the '[' and ']'. */
1670 char *check_for_hostspec(char *s, char **host_ptr, int *port_ptr)
1671 {
1672         char *p;
1673         int not_host;
1674
1675         if (port_ptr && strncasecmp(URL_PREFIX, s, strlen(URL_PREFIX)) == 0) {
1676                 char *path;
1677                 int hostlen;
1678                 s += strlen(URL_PREFIX);
1679                 if ((p = strchr(s, '/')) != NULL) {
1680                         hostlen = p - s;
1681                         path = p + 1;
1682                 } else {
1683                         hostlen = strlen(s);
1684                         path = "";
1685                 }
1686                 if (*s == '[' && (p = strchr(s, ']')) != NULL) {
1687                         s++;
1688                         hostlen = p - s;
1689                         if (p[1] == ':')
1690                                 *port_ptr = atoi(p+2);
1691                 } else {
1692                         if ((p = strchr(s, ':')) != NULL) {
1693                                 hostlen = p - s;
1694                                 *port_ptr = atoi(p+1);
1695                         }
1696                 }
1697                 if (!*port_ptr)
1698                         *port_ptr = RSYNC_PORT;
1699                 *host_ptr = new_array(char, hostlen + 1);
1700                 strlcpy(*host_ptr, s, hostlen + 1);
1701                 return path;
1702         }
1703
1704         if (*s == '[' && (p = strchr(s, ']')) != NULL && p[1] == ':') {
1705                 s++;
1706                 *p = '\0';
1707                 not_host = strchr(s, '/') || !strchr(s, ':');
1708                 *p = ']';
1709                 if (not_host)
1710                         return NULL;
1711                 p++;
1712         } else {
1713                 if (!(p = strchr(s, ':')))
1714                         return NULL;
1715                 *p = '\0';
1716                 not_host = strchr(s, '/') != NULL;
1717                 *p = ':';
1718                 if (not_host)
1719                         return NULL;
1720         }
1721
1722         *host_ptr = new_array(char, p - s + 1);
1723         strlcpy(*host_ptr, s, p - s + 1);
1724
1725         if (p[1] == ':') {
1726                 if (port_ptr && !*port_ptr)
1727                         *port_ptr = RSYNC_PORT;
1728                 return p + 2;
1729         }
1730         if (port_ptr)
1731                 *port_ptr = 0;
1732
1733         return p + 1;
1734 }