Allow "port" to be specified in the rsyncd.conf file.
[rsync/rsync.git] / options.c
1 /*  -*- c-file-style: "linux" -*-
2  *
3  * Copyright (C) 1998-2001 by Andrew Tridgell <tridge@samba.org>
4  * Copyright (C) 2000, 2001, 2002 by Martin Pool <mbp@samba.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 #include "rsync.h"
22 #include "popt.h"
23
24 extern int sanitize_paths;
25 extern int select_timeout;
26 extern struct exclude_list_struct exclude_list;
27 extern struct exclude_list_struct server_exclude_list;
28
29 int make_backups = 0;
30
31 /**
32  * If 1, send the whole file as literal data rather than trying to
33  * create an incremental diff.
34  *
35  * If -1, then look at whether we're local or remote and go by that.
36  *
37  * @sa disable_deltas_p()
38  **/
39 int whole_file = -1;
40
41 int archive_mode = 0;
42 int keep_dirlinks = 0;
43 int copy_links = 0;
44 int preserve_links = 0;
45 int preserve_hard_links = 0;
46 int preserve_perms = 0;
47 int preserve_devices = 0;
48 int preserve_uid = 0;
49 int preserve_gid = 0;
50 int preserve_times = 0;
51 int update_only = 0;
52 int cvs_exclude = 0;
53 int dry_run = 0;
54 int local_server = 0;
55 int ignore_times = 0;
56 int delete_mode = 0;
57 int delete_excluded = 0;
58 int one_file_system = 0;
59 int protocol_version = PROTOCOL_VERSION;
60 int sparse_files = 0;
61 int do_compression = 0;
62 int am_root = 0;
63 int orig_umask = 0;
64 int relative_paths = -1;
65 int implied_dirs = 1;
66 int numeric_ids = 0;
67 int force_delete = 0;
68 int io_timeout = 0;
69 int read_only = 0;
70 int module_id = -1;
71 int am_server = 0;
72 int am_sender = 0;
73 int am_generator = 0;
74 char *files_from = NULL;
75 int filesfrom_fd = -1;
76 char *remote_filesfrom_file = NULL;
77 int eol_nulls = 0;
78 int recurse = 0;
79 int am_daemon = 0;
80 int daemon_over_rsh = 0;
81 int do_stats = 0;
82 int do_progress = 0;
83 int keep_partial = 0;
84 int safe_symlinks = 0;
85 int copy_unsafe_links = 0;
86 int size_only = 0;
87 int daemon_bwlimit = 0;
88 int bwlimit = 0;
89 size_t bwlimit_writemax = 0;
90 int delete_after = 0;
91 int only_existing = 0;
92 int opt_ignore_existing = 0;
93 int max_delete = 0;
94 OFF_T max_size = 0;
95 int ignore_errors = 0;
96 int modify_window = 0;
97 int blocking_io = -1;
98 int checksum_seed = 0;
99 int inplace = 0;
100 unsigned int block_size = 0;
101
102
103 /** Network address family. **/
104 #ifdef INET6
105 int default_af_hint = 0;        /* Any protocol */
106 #else
107 int default_af_hint = AF_INET;  /* Must use IPv4 */
108 #endif
109
110 /** Do not go into the background when run as --daemon.  Good
111  * for debugging and required for running as a service on W32,
112  * or under Unix process-monitors. **/
113 int no_detach = 0;
114
115 int write_batch = 0;
116 int read_batch = 0;
117 int backup_dir_len = 0;
118 int backup_suffix_len;
119 unsigned int backup_dir_remainder;
120
121 char *backup_suffix = NULL;
122 char *tmpdir = NULL;
123 char *partial_dir = NULL;
124 char *basis_dir[MAX_BASIS_DIRS+1];
125 char *config_file = NULL;
126 char *shell_cmd = NULL;
127 char *log_format = NULL;
128 char *password_file = NULL;
129 char *rsync_path = RSYNC_PATH;
130 char *backup_dir = NULL;
131 char backup_dir_buf[MAXPATHLEN];
132 int rsync_port = 0;
133 int copy_dest = 0;
134 int link_dest = 0;
135
136 int verbose = 0;
137 int quiet = 0;
138 int always_checksum = 0;
139 int list_only = 0;
140
141 #define MAX_BATCH_NAME_LEN 256  /* Must be less than MAXPATHLEN-13 */
142 char *batch_name = NULL;
143
144 static int daemon_opt;   /* sets am_daemon after option error-reporting */
145 static int modify_window_set;
146 static int compare_dest = 0;
147 static int basis_dir_cnt = 0;
148 static char *dest_option;
149 static char *max_size_arg;
150
151 /** Local address to bind.  As a character string because it's
152  * interpreted by the IPv6 layer: should be a numeric IP4 or IP6
153  * address, or a hostname. **/
154 char *bind_address;
155
156
157 static void print_rsync_version(enum logcode f)
158 {
159         char const *got_socketpair = "no ";
160         char const *have_inplace = "no ";
161         char const *hardlinks = "no ";
162         char const *links = "no ";
163         char const *ipv6 = "no ";
164         STRUCT_STAT *dumstat;
165
166 #ifdef HAVE_SOCKETPAIR
167         got_socketpair = "";
168 #endif
169
170 #if HAVE_FTRUNCATE
171         have_inplace = "";
172 #endif
173
174 #if SUPPORT_HARD_LINKS
175         hardlinks = "";
176 #endif
177
178 #if SUPPORT_LINKS
179         links = "";
180 #endif
181
182 #if INET6
183         ipv6 = "";
184 #endif
185
186         rprintf(f, "%s  version %s  protocol version %d\n",
187                 RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION);
188         rprintf(f,
189                 "Copyright (C) 1996-2004 by Andrew Tridgell and others\n");
190         rprintf(f, "<http://rsync.samba.org/>\n");
191         rprintf(f, "Capabilities: %d-bit files, %ssocketpairs, "
192                 "%shard links, %ssymlinks, batchfiles, \n",
193                 (int) (sizeof (OFF_T) * 8),
194                 got_socketpair, hardlinks, links);
195
196         /* Note that this field may not have type ino_t.  It depends
197          * on the complicated interaction between largefile feature
198          * macros. */
199         rprintf(f, "              %sinplace, %sIPv6, %d-bit system inums, %d-bit internal inums\n",
200                 have_inplace, ipv6,
201                 (int) (sizeof dumstat->st_ino * 8),
202                 (int) (sizeof (uint64) * 8));
203 #ifdef MAINTAINER_MODE
204         rprintf(f, "              panic action: \"%s\"\n",
205                 get_panic_action());
206 #endif
207
208 #ifdef INT64_IS_OFF_T
209         if (sizeof (int64) < 8)
210                 rprintf(f, "WARNING: no 64-bit integers on this platform!\n");
211 #endif
212
213         rprintf(f,
214 "\n"
215 "rsync comes with ABSOLUTELY NO WARRANTY.  This is free software, and you\n"
216 "are welcome to redistribute it under certain conditions.  See the GNU\n"
217 "General Public Licence for details.\n"
218                 );
219 }
220
221
222 void usage(enum logcode F)
223 {
224   print_rsync_version(F);
225
226   rprintf(F,"\nrsync is a file transfer program capable of efficient remote update\nvia a fast differencing algorithm.\n\n");
227
228   rprintf(F,"Usage: rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST\n");
229   rprintf(F,"  or   rsync [OPTION]... [USER@]HOST:SRC DEST\n");
230   rprintf(F,"  or   rsync [OPTION]... SRC [SRC]... DEST\n");
231   rprintf(F,"  or   rsync [OPTION]... [USER@]HOST::SRC [DEST]\n");
232   rprintf(F,"  or   rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST\n");
233   rprintf(F,"  or   rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST]\n");
234   rprintf(F,"  or   rsync [OPTION]... SRC [SRC]... rsync://[USER@]HOST[:PORT]/DEST\n");
235   rprintf(F,"SRC on single-colon remote HOST will be expanded by remote shell\n");
236   rprintf(F,"SRC on server remote HOST may contain shell wildcards or multiple\n");
237   rprintf(F,"  sources separated by space as long as they have same top-level\n");
238   rprintf(F,"\nOptions\n");
239   rprintf(F," -v, --verbose               increase verbosity\n");
240   rprintf(F," -q, --quiet                 decrease verbosity\n");
241   rprintf(F," -c, --checksum              always checksum\n");
242   rprintf(F," -a, --archive               archive mode, equivalent to -rlptgoD (no -H)\n");
243   rprintf(F," -r, --recursive             recurse into directories\n");
244   rprintf(F," -R, --relative              use relative path names\n");
245   rprintf(F,"     --no-relative           turn off --relative\n");
246   rprintf(F,"     --no-implied-dirs       don't send implied dirs with -R\n");
247   rprintf(F," -b, --backup                make backups (see --suffix & --backup-dir)\n");
248   rprintf(F,"     --backup-dir            make backups into this directory\n");
249   rprintf(F,"     --suffix=SUFFIX         backup suffix (default %s w/o --backup-dir)\n",BACKUP_SUFFIX);
250   rprintf(F," -u, --update                update only (don't overwrite newer files)\n");
251   rprintf(F,"     --inplace               update destination files inplace (SEE MAN PAGE)\n");
252   rprintf(F," -K, --keep-dirlinks         treat symlinked dir on receiver as dir\n");
253   rprintf(F," -l, --links                 copy symlinks as symlinks\n");
254   rprintf(F," -L, --copy-links            copy the referent of all symlinks\n");
255   rprintf(F,"     --copy-unsafe-links     copy the referent of \"unsafe\" symlinks\n");
256   rprintf(F,"     --safe-links            ignore \"unsafe\" symlinks\n");
257   rprintf(F," -H, --hard-links            preserve hard links\n");
258   rprintf(F," -p, --perms                 preserve permissions\n");
259   rprintf(F," -o, --owner                 preserve owner (root only)\n");
260   rprintf(F," -g, --group                 preserve group\n");
261   rprintf(F," -D, --devices               preserve devices (root only)\n");
262   rprintf(F," -t, --times                 preserve times\n");
263   rprintf(F," -S, --sparse                handle sparse files efficiently\n");
264   rprintf(F," -n, --dry-run               show what would have been transferred\n");
265   rprintf(F," -W, --whole-file            copy whole files, no incremental checks\n");
266   rprintf(F,"     --no-whole-file         turn off --whole-file\n");
267   rprintf(F," -x, --one-file-system       don't cross filesystem boundaries\n");
268   rprintf(F," -B, --block-size=SIZE       force a fixed checksum block-size\n");
269   rprintf(F," -e, --rsh=COMMAND           specify the remote shell\n");
270   rprintf(F,"     --rsync-path=PATH       specify path to rsync on the remote machine\n");
271   rprintf(F,"     --existing              only update files that already exist\n");
272   rprintf(F,"     --ignore-existing       ignore files that already exist on receiving side\n");
273   rprintf(F,"     --delete                delete files that don't exist on the sending side\n");
274   rprintf(F,"     --delete-excluded       also delete excluded files on the receiving side\n");
275   rprintf(F,"     --delete-after          receiver deletes after transferring, not before\n");
276   rprintf(F,"     --ignore-errors         delete even if there are I/O errors\n");
277   rprintf(F,"     --max-delete=NUM        don't delete more than NUM files\n");
278   rprintf(F,"     --max-size=SIZE         don't transfer any file larger than SIZE\n");
279   rprintf(F,"     --partial               keep partially transferred files\n");
280   rprintf(F,"     --partial-dir=DIR       put a partially transferred file into DIR\n");
281   rprintf(F,"     --force                 force deletion of directories even if not empty\n");
282   rprintf(F,"     --numeric-ids           don't map uid/gid values by user/group name\n");
283   rprintf(F,"     --timeout=TIME          set I/O timeout in seconds\n");
284   rprintf(F," -I, --ignore-times          turn off mod time & file size quick check\n");
285   rprintf(F,"     --size-only             ignore mod time for quick check (use size)\n");
286   rprintf(F,"     --modify-window=NUM     compare mod times with reduced accuracy\n");
287   rprintf(F," -T, --temp-dir=DIR          create temporary files in directory DIR\n");
288   rprintf(F,"     --compare-dest=DIR      also compare destination files relative to DIR\n");
289   rprintf(F,"     --copy-dest=DIR         ... and include copies of unchanged files\n");
290   rprintf(F,"     --link-dest=DIR         hardlink to files in DIR when unchanged\n");
291   rprintf(F," -P                          equivalent to --partial --progress\n");
292   rprintf(F," -z, --compress              compress file data\n");
293   rprintf(F," -C, --cvs-exclude           auto ignore files in the same way CVS does\n");
294   rprintf(F,"     --exclude=PATTERN       exclude files matching PATTERN\n");
295   rprintf(F,"     --exclude-from=FILE     exclude patterns listed in FILE\n");
296   rprintf(F,"     --include=PATTERN       don't exclude files matching PATTERN\n");
297   rprintf(F,"     --include-from=FILE     don't exclude patterns listed in FILE\n");
298   rprintf(F,"     --files-from=FILE       read FILE for list of source-file names\n");
299   rprintf(F," -0, --from0                 all *-from file lists are delimited by nulls\n");
300   rprintf(F,"     --version               print version number\n");
301   rprintf(F,"     --blocking-io           use blocking I/O for the remote shell\n");
302   rprintf(F,"     --no-blocking-io        turn off --blocking-io\n");
303   rprintf(F,"     --stats                 give some file transfer stats\n");
304   rprintf(F,"     --progress              show progress during transfer\n");
305   rprintf(F,"     --log-format=FORMAT     log file transfers using specified format\n");
306   rprintf(F,"     --password-file=FILE    get password from FILE\n");
307   rprintf(F,"     --bwlimit=KBPS          limit I/O bandwidth, KBytes per second\n");
308   rprintf(F,"     --write-batch=FILE      write a batch to FILE\n");
309   rprintf(F,"     --read-batch=FILE       read a batch from FILE\n");
310 #ifdef INET6
311   rprintf(F," -4, --ipv4                  prefer IPv4\n");
312   rprintf(F," -6, --ipv6                  prefer IPv6\n");
313 #endif
314   rprintf(F," -h, --help                  show this help screen\n");
315
316   rprintf(F,"\nUse \"rsync --daemon --help\" to see the daemon-mode command-line options.\n");
317   rprintf(F,"Please see the rsync(1) and rsyncd.conf(5) man pages for full documentation.\n");
318   rprintf(F,"See http://rsync.samba.org/ for updates, bug reports, and answers\n");
319 }
320
321 enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
322       OPT_DELETE_AFTER, OPT_DELETE_EXCLUDED,
323       OPT_COMPARE_DEST, OPT_COPY_DEST, OPT_LINK_DEST,
324       OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW,
325       OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_TIMEOUT, OPT_MAX_SIZE,
326       OPT_REFUSED_BASE = 9000};
327
328 static struct poptOption long_options[] = {
329   /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
330   {"version",          0,  POPT_ARG_NONE,   0, OPT_VERSION, 0, 0},
331   {"suffix",           0,  POPT_ARG_STRING, &backup_suffix, 0, 0, 0 },
332   {"rsync-path",       0,  POPT_ARG_STRING, &rsync_path, 0, 0, 0 },
333   {"password-file",    0,  POPT_ARG_STRING, &password_file, 0, 0, 0 },
334   {"ignore-times",    'I', POPT_ARG_NONE,   &ignore_times, 0, 0, 0 },
335   {"size-only",        0,  POPT_ARG_NONE,   &size_only, 0, 0, 0 },
336   {"modify-window",    0,  POPT_ARG_INT,    &modify_window, OPT_MODIFY_WINDOW, 0, 0 },
337   {"one-file-system", 'x', POPT_ARG_NONE,   &one_file_system, 0, 0, 0 },
338   {"delete",           0,  POPT_ARG_NONE,   &delete_mode, 0, 0, 0 },
339   {"existing",         0,  POPT_ARG_NONE,   &only_existing, 0, 0, 0 },
340   {"ignore-existing",  0,  POPT_ARG_NONE,   &opt_ignore_existing, 0, 0, 0 },
341   {"delete-after",     0,  POPT_ARG_NONE,   0, OPT_DELETE_AFTER, 0, 0 },
342   {"delete-excluded",  0,  POPT_ARG_NONE,   0, OPT_DELETE_EXCLUDED, 0, 0 },
343   {"force",            0,  POPT_ARG_NONE,   &force_delete, 0, 0, 0 },
344   {"numeric-ids",      0,  POPT_ARG_NONE,   &numeric_ids, 0, 0, 0 },
345   {"exclude",          0,  POPT_ARG_STRING, 0, OPT_EXCLUDE, 0, 0 },
346   {"include",          0,  POPT_ARG_STRING, 0, OPT_INCLUDE, 0, 0 },
347   {"exclude-from",     0,  POPT_ARG_STRING, 0, OPT_EXCLUDE_FROM, 0, 0 },
348   {"include-from",     0,  POPT_ARG_STRING, 0, OPT_INCLUDE_FROM, 0, 0 },
349   {"safe-links",       0,  POPT_ARG_NONE,   &safe_symlinks, 0, 0, 0 },
350   {"help",            'h', POPT_ARG_NONE,   0, 'h', 0, 0 },
351   {"backup",          'b', POPT_ARG_NONE,   &make_backups, 0, 0, 0 },
352   {"dry-run",         'n', POPT_ARG_NONE,   &dry_run, 0, 0, 0 },
353   {"sparse",          'S', POPT_ARG_NONE,   &sparse_files, 0, 0, 0 },
354   {"cvs-exclude",     'C', POPT_ARG_NONE,   &cvs_exclude, 0, 0, 0 },
355   {"update",          'u', POPT_ARG_NONE,   &update_only, 0, 0, 0 },
356   {"inplace",          0,  POPT_ARG_NONE,   &inplace, 0, 0, 0 },
357   {"keep-dirlinks",   'K', POPT_ARG_NONE,   &keep_dirlinks, 0, 0, 0 },
358   {"links",           'l', POPT_ARG_NONE,   &preserve_links, 0, 0, 0 },
359   {"copy-links",      'L', POPT_ARG_NONE,   &copy_links, 0, 0, 0 },
360   {"whole-file",      'W', POPT_ARG_VAL,    &whole_file, 1, 0, 0 },
361   {"no-whole-file",    0,  POPT_ARG_VAL,    &whole_file, 0, 0, 0 },
362   {"copy-unsafe-links", 0, POPT_ARG_NONE,   &copy_unsafe_links, 0, 0, 0 },
363   {"perms",           'p', POPT_ARG_NONE,   &preserve_perms, 0, 0, 0 },
364   {"owner",           'o', POPT_ARG_NONE,   &preserve_uid, 0, 0, 0 },
365   {"group",           'g', POPT_ARG_NONE,   &preserve_gid, 0, 0, 0 },
366   {"devices",         'D', POPT_ARG_NONE,   &preserve_devices, 0, 0, 0 },
367   {"times",           't', POPT_ARG_NONE,   &preserve_times, 0, 0, 0 },
368   {"checksum",        'c', POPT_ARG_NONE,   &always_checksum, 0, 0, 0 },
369   {"verbose",         'v', POPT_ARG_NONE,   0, 'v', 0, 0 },
370   {"quiet",           'q', POPT_ARG_NONE,   0, 'q', 0, 0 },
371   {"archive",         'a', POPT_ARG_NONE,   &archive_mode, 0, 0, 0 },
372   {"server",           0,  POPT_ARG_NONE,   &am_server, 0, 0, 0 },
373   {"sender",           0,  POPT_ARG_NONE,   0, OPT_SENDER, 0, 0 },
374   {"recursive",       'r', POPT_ARG_NONE,   &recurse, 0, 0, 0 },
375   {"relative",        'R', POPT_ARG_VAL,    &relative_paths, 1, 0, 0 },
376   {"no-relative",      0,  POPT_ARG_VAL,    &relative_paths, 0, 0, 0 },
377   {"rsh",             'e', POPT_ARG_STRING, &shell_cmd, 0, 0, 0 },
378   {"block-size",      'B', POPT_ARG_INT,    &block_size, 0, 0, 0 },
379   {"max-delete",       0,  POPT_ARG_INT,    &max_delete, 0, 0, 0 },
380   {"max-size",         0,  POPT_ARG_STRING, &max_size_arg,  OPT_MAX_SIZE, 0, 0 },
381   {"timeout",          0,  POPT_ARG_INT,    &io_timeout, OPT_TIMEOUT, 0, 0 },
382   {"temp-dir",        'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
383   {"compare-dest",     0,  POPT_ARG_STRING, 0, OPT_COMPARE_DEST, 0, 0 },
384   {"copy-dest",        0,  POPT_ARG_STRING, 0, OPT_COPY_DEST, 0, 0 },
385   {"link-dest",        0,  POPT_ARG_STRING, 0, OPT_LINK_DEST, 0, 0 },
386   /* TODO: Should this take an optional int giving the compression level? */
387   {"compress",        'z', POPT_ARG_NONE,   &do_compression, 0, 0, 0 },
388   {"stats",            0,  POPT_ARG_NONE,   &do_stats, 0, 0, 0 },
389   {"progress",         0,  POPT_ARG_NONE,   &do_progress, 0, 0, 0 },
390   {"partial",          0,  POPT_ARG_NONE,   &keep_partial, 0, 0, 0 },
391   {"partial-dir",      0,  POPT_ARG_STRING, &partial_dir, 0, 0, 0 },
392   {"ignore-errors",    0,  POPT_ARG_NONE,   &ignore_errors, 0, 0, 0 },
393   {"blocking-io",      0,  POPT_ARG_VAL,    &blocking_io, 1, 0, 0 },
394   {"no-blocking-io",   0,  POPT_ARG_VAL,    &blocking_io, 0, 0, 0 },
395   {0,                 'P', POPT_ARG_NONE,   0, 'P', 0, 0 },
396   {"log-format",       0,  POPT_ARG_STRING, &log_format, 0, 0, 0 },
397   {"bwlimit",          0,  POPT_ARG_INT,    &bwlimit, 0, 0, 0 },
398   {"backup-dir",       0,  POPT_ARG_STRING, &backup_dir, 0, 0, 0 },
399   {"hard-links",      'H', POPT_ARG_NONE,   &preserve_hard_links, 0, 0, 0 },
400   {"read-batch",       0,  POPT_ARG_STRING, &batch_name, OPT_READ_BATCH, 0, 0 },
401   {"write-batch",      0,  POPT_ARG_STRING, &batch_name, OPT_WRITE_BATCH, 0, 0 },
402   {"files-from",       0,  POPT_ARG_STRING, &files_from, 0, 0, 0 },
403   {"from0",           '0', POPT_ARG_NONE,   &eol_nulls, 0, 0, 0},
404   {"no-implied-dirs",  0,  POPT_ARG_VAL,    &implied_dirs, 0, 0, 0 },
405   {"protocol",         0,  POPT_ARG_INT,    &protocol_version, 0, 0, 0 },
406   {"checksum-seed",    0,  POPT_ARG_INT,    &checksum_seed, 0, 0, 0 },
407 #ifdef INET6
408   {"ipv4",            '4', POPT_ARG_VAL,    &default_af_hint, AF_INET, 0, 0 },
409   {"ipv6",            '6', POPT_ARG_VAL,    &default_af_hint, AF_INET6, 0, 0 },
410 #endif
411   /* All these options switch us into daemon-mode option-parsing. */
412   {"address",          0,  POPT_ARG_STRING, 0, OPT_DAEMON, 0, 0 },
413   {"config",           0,  POPT_ARG_STRING, 0, OPT_DAEMON, 0, 0 },
414   {"daemon",           0,  POPT_ARG_NONE,   0, OPT_DAEMON, 0, 0 },
415   {"no-detach",        0,  POPT_ARG_NONE,   0, OPT_DAEMON, 0, 0 },
416   {"port",             0,  POPT_ARG_INT,    0, OPT_DAEMON, 0, 0 },
417   {0,0,0,0, 0, 0, 0}
418 };
419
420 static void daemon_usage(enum logcode F)
421 {
422   print_rsync_version(F);
423
424   rprintf(F,"\nUsage: rsync --daemon [OPTION]...\n");
425   rprintf(F,"     --address=ADDRESS       bind to the specified address\n");
426   rprintf(F,"     --bwlimit=KBPS          limit I/O bandwidth, KBytes per second\n");
427   rprintf(F,"     --config=FILE           specify alternate rsyncd.conf file\n");
428   rprintf(F,"     --no-detach             do not detach from the parent\n");
429   rprintf(F,"     --port=PORT             specify alternate rsyncd port number\n");
430 #ifdef INET6
431   rprintf(F," -4, --ipv4                  prefer IPv4\n");
432   rprintf(F," -6, --ipv6                  prefer IPv6\n");
433 #endif
434   rprintf(F," -h, --help                  show this help screen\n");
435
436   rprintf(F,"\nIf you were not trying to invoke rsync as a daemon, avoid using any of the\n");
437   rprintf(F,"daemon-specific rsync options.  See also the rsyncd.conf(5) man page.\n");
438 }
439
440 static struct poptOption long_daemon_options[] = {
441   /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
442   {"address",          0,  POPT_ARG_STRING, &bind_address, 0, 0, 0 },
443   {"bwlimit",          0,  POPT_ARG_INT,    &daemon_bwlimit, 0, 0, 0 },
444   {"config",           0,  POPT_ARG_STRING, &config_file, 0, 0, 0 },
445   {"daemon",           0,  POPT_ARG_NONE,   &daemon_opt, 0, 0, 0 },
446 #ifdef INET6
447   {"ipv4",            '4', POPT_ARG_VAL,    &default_af_hint, AF_INET, 0, 0 },
448   {"ipv6",            '6', POPT_ARG_VAL,    &default_af_hint, AF_INET6, 0, 0 },
449 #endif
450   {"no-detach",        0,  POPT_ARG_NONE,   &no_detach, 0, 0, 0 },
451   {"port",             0,  POPT_ARG_INT,    &rsync_port, 0, 0, 0 },
452   {"protocol",         0,  POPT_ARG_INT,    &protocol_version, 0, 0, 0 },
453   {"server",           0,  POPT_ARG_NONE,   &am_server, 0, 0, 0 },
454   {"help",            'h', POPT_ARG_NONE,   0, 'h', 0, 0 },
455   {0,0,0,0, 0, 0, 0}
456 };
457
458
459 static char err_buf[200];
460
461
462 /**
463  * Store the option error message, if any, so that we can log the
464  * connection attempt (which requires parsing the options), and then
465  * show the error later on.
466  **/
467 void option_error(void)
468 {
469         if (!err_buf[0]) {
470                 strcpy(err_buf, "Error parsing options: "
471                     "option may be supported on client but not on server?\n");
472         }
473
474         rprintf(FERROR, RSYNC_NAME ": %s", err_buf);
475 }
476
477
478 /**
479  * Tweak the option table to disable all options that the rsyncd.conf
480  * file has told us to refuse.
481  **/
482 static void set_refuse_options(char *bp)
483 {
484         struct poptOption *op;
485         char *cp, shortname[2];
486         int is_wild, found_match;
487
488         shortname[1] = '\0';
489
490         while (1) {
491                 while (*bp == ' ') bp++;
492                 if (!*bp)
493                         break;
494                 if ((cp = strchr(bp, ' ')) != NULL)
495                         *cp= '\0';
496                 /* If they specify "delete", reject all delete options. */
497                 if (strcmp(bp, "delete") == 0)
498                         bp = "delete*";
499                 is_wild = strpbrk(bp, "*?[") != NULL;
500                 found_match = 0;
501                 for (op = long_options; ; op++) {
502                         *shortname = op->shortName;
503                         if (!op->longName && !*shortname)
504                                 break;
505                         if ((op->longName && wildmatch(bp, op->longName))
506                             || (*shortname && wildmatch(bp, shortname))) {
507                                 op->val = (op - long_options) + OPT_REFUSED_BASE;
508                                 found_match = 1;
509                                 if (!is_wild)
510                                         break;
511                         }
512                 }
513                 if (!found_match) {
514                         rprintf(FLOG, "No match for refuse-options string \"%s\"\n",
515                                 bp);
516                 }
517                 if (!cp)
518                         break;
519                 *cp = ' ';
520                 bp = cp + 1;
521         }
522 }
523
524
525 static int count_args(const char **argv)
526 {
527         int i = 0;
528
529         if (argv) {
530                 while (argv[i] != NULL)
531                         i++;
532         }
533
534         return i;
535 }
536
537
538 /**
539  * Process command line arguments.  Called on both local and remote.
540  *
541  * @retval 1 if all options are OK; with globals set to appropriate
542  * values
543  *
544  * @retval 0 on error, with err_buf containing an explanation
545  **/
546 int parse_arguments(int *argc, const char ***argv, int frommain)
547 {
548         int opt;
549         char *ref = lp_refuse_options(module_id);
550         const char *arg;
551         poptContext pc;
552
553         if (ref && *ref)
554                 set_refuse_options(ref);
555
556         /* TODO: Call poptReadDefaultConfig; handle errors. */
557
558         /* The context leaks in case of an error, but if there's a
559          * problem we always exit anyhow. */
560         pc = poptGetContext(RSYNC_NAME, *argc, *argv, long_options, 0);
561         poptReadDefaultConfig(pc, 0);
562
563         while ((opt = poptGetNextOpt(pc)) != -1) {
564                 /* most options are handled automatically by popt;
565                  * only special cases are returned and listed here. */
566
567                 switch (opt) {
568                 case OPT_VERSION:
569                         print_rsync_version(FINFO);
570                         exit_cleanup(0);
571
572                 case OPT_DAEMON:
573                         if (am_daemon) {
574                                 strcpy(err_buf, "Attempt to hack rsync thwarted!\n");
575                                 return 0;
576                         }
577                         poptFreeContext(pc);
578                         pc = poptGetContext(RSYNC_NAME, *argc, *argv,
579                                             long_daemon_options, 0);
580                         while ((opt = poptGetNextOpt(pc)) != -1) {
581                                 switch (opt) {
582                                 case 'h':
583                                         daemon_usage(FINFO);
584                                         exit_cleanup(0);
585
586                                 default:
587                                         rprintf(FERROR,
588                                             "rsync: %s: %s (in daemon mode)\n",
589                                             poptBadOption(pc, POPT_BADOPTION_NOALIAS),
590                                             poptStrerror(opt));
591                                         goto daemon_error;
592                                 }
593                         }
594                         if (!daemon_opt) {
595                                 rprintf(FERROR, "Daemon option(s) used without --daemon.\n");
596                             daemon_error:
597                                 rprintf(FERROR,
598                                     "(Type \"rsync --daemon --help\" for assistance with daemon mode.)\n");
599                                 exit_cleanup(RERR_SYNTAX);
600                         }
601                         *argv = poptGetArgs(pc);
602                         *argc = count_args(*argv);
603                         daemon_opt = 0;
604                         am_daemon = 1;
605                         return 1;
606
607                 case OPT_MODIFY_WINDOW:
608                         /* The value has already been set by popt, but
609                          * we need to remember that we're using a
610                          * non-default setting. */
611                         modify_window_set = 1;
612                         break;
613
614                 case OPT_DELETE_AFTER:
615                         delete_after = 1;
616                         delete_mode = 1;
617                         break;
618
619                 case OPT_DELETE_EXCLUDED:
620                         delete_excluded = 1;
621                         delete_mode = 1;
622                         break;
623
624                 case OPT_EXCLUDE:
625                         add_exclude(&exclude_list, poptGetOptArg(pc), 0);
626                         break;
627
628                 case OPT_INCLUDE:
629                         add_exclude(&exclude_list, poptGetOptArg(pc),
630                                     XFLG_DEF_INCLUDE);
631                         break;
632
633                 case OPT_EXCLUDE_FROM:
634                 case OPT_INCLUDE_FROM:
635                         arg = poptGetOptArg(pc);
636                         if (sanitize_paths)
637                                 arg = sanitize_path(NULL, arg, NULL, 0);
638                         if (server_exclude_list.head) {
639                                 char *cp = (char *)arg;
640                                 clean_fname(cp, 1);
641                                 if (check_exclude(&server_exclude_list, cp, 0) < 0)
642                                         goto options_rejected;
643                         }
644                         add_exclude_file(&exclude_list, arg, XFLG_FATAL_ERRORS
645                                          | (opt == OPT_INCLUDE_FROM
646                                           ? XFLG_DEF_INCLUDE : 0));
647                         break;
648
649                 case 'h':
650                         usage(FINFO);
651                         exit_cleanup(0);
652
653                 case 'v':
654                         verbose++;
655                         break;
656
657                 case 'q':
658                         if (frommain)
659                                 quiet++;
660                         break;
661
662                 case OPT_SENDER:
663                         if (!am_server) {
664                                 usage(FERROR);
665                                 exit_cleanup(RERR_SYNTAX);
666                         }
667                         am_sender = 1;
668                         break;
669
670                 case 'P':
671                         do_progress = 1;
672                         keep_partial = 1;
673                         break;
674
675                 case OPT_WRITE_BATCH:
676                         /* batch_name is already set */
677                         write_batch = 1;
678                         break;
679
680                 case OPT_READ_BATCH:
681                         /* batch_name is already set */
682                         read_batch = 1;
683                         break;
684
685                 case OPT_MAX_SIZE:
686                         for (arg = max_size_arg; isdigit(*arg); arg++) {}
687                         if (*arg == '.')
688                                 for (arg++; isdigit(*arg); arg++) {}
689                         switch (*arg) {
690                         case 'k': case 'K':
691                                 max_size = atof(max_size_arg) * 1024;
692                                 break;
693                         case 'm': case 'M':
694                                 max_size = atof(max_size_arg) * 1024*1024;
695                                 break;
696                         case 'g': case 'G':
697                                 max_size = atof(max_size_arg) * 1024*1024*1024;
698                                 break;
699                         case '\0':
700                                 max_size = atof(max_size_arg);
701                                 break;
702                         default:
703                                 max_size = 0;
704                                 break;
705                         }
706                         if (max_size <= 0) {
707                                 snprintf(err_buf, sizeof err_buf,
708                                         "--max-size value is invalid: %s\n",
709                                         max_size_arg);
710                                 return 0;
711                         }
712                         break;
713
714                 case OPT_TIMEOUT:
715                         if (io_timeout && io_timeout < select_timeout)
716                                 select_timeout = io_timeout;
717                         break;
718
719                 case OPT_LINK_DEST:
720 #if HAVE_LINK
721                         link_dest = 1;
722                         dest_option = "--link-dest";
723                         goto set_dest_dir;
724 #else
725                         snprintf(err_buf, sizeof err_buf,
726                                  "hard links are not supported on this %s\n",
727                                  am_server ? "server" : "client");
728                         return 0;
729 #endif
730
731                 case OPT_COPY_DEST:
732                         copy_dest = 1;
733                         dest_option = "--copy-dest";
734                         goto set_dest_dir;
735
736                 case OPT_COMPARE_DEST:
737                         compare_dest = 1;
738                         dest_option = "--compare-dest";
739                 set_dest_dir:
740                         if (basis_dir_cnt >= MAX_BASIS_DIRS-1) {
741                                 snprintf(err_buf, sizeof err_buf,
742                                         "ERROR: at most %d %s args may be specified\n",
743                                         MAX_BASIS_DIRS, dest_option);
744                                 return 0;
745                         }
746                         arg = poptGetOptArg(pc);
747                         if (sanitize_paths)
748                                 arg = sanitize_path(NULL, arg, NULL, 0);
749                         basis_dir[basis_dir_cnt++] = (char *)arg;
750                         break;
751
752                 default:
753                         /* A large opt value means that set_refuse_options()
754                          * turned this option off (opt-BASE is its index). */
755                         if (opt >= OPT_REFUSED_BASE) {
756                                 struct poptOption *op =
757                                     &long_options[opt-OPT_REFUSED_BASE];
758                                 int n = snprintf(err_buf, sizeof err_buf,
759                                     "The server is configured to refuse --%s\n",
760                                     op->longName) - 1;
761                                 if (op->shortName) {
762                                         snprintf(err_buf+n, sizeof err_buf-n,
763                                             " (-%c)\n", op->shortName);
764                                 }
765                         } else {
766                                 snprintf(err_buf, sizeof err_buf, "%s%s: %s\n",
767                                     am_server ? "on remote machine: " : "",
768                                     poptBadOption(pc, POPT_BADOPTION_NOALIAS),
769                                     poptStrerror(opt));
770                         }
771                         return 0;
772                 }
773         }
774
775 #if !SUPPORT_LINKS
776         if (preserve_links && !am_sender) {
777                 snprintf(err_buf, sizeof err_buf,
778                          "symlinks are not supported on this %s\n",
779                          am_server ? "server" : "client");
780                 return 0;
781         }
782 #endif
783
784 #if !SUPPORT_HARD_LINKS
785         if (preserve_hard_links) {
786                 snprintf(err_buf, sizeof err_buf,
787                          "hard links are not supported on this %s\n",
788                          am_server ? "server" : "client");
789                 return 0;
790         }
791 #endif
792
793         if (write_batch && read_batch) {
794                 snprintf(err_buf, sizeof err_buf,
795                         "--write-batch and --read-batch can not be used together\n");
796                 return 0;
797         }
798         if (write_batch || read_batch) {
799                 if (dry_run) {
800                         snprintf(err_buf, sizeof err_buf,
801                                 "--%s-batch cannot be used with --dry_run (-n)\n",
802                                 write_batch ? "write" : "read");
803                         return 0;
804                 }
805                 if (am_server) {
806                         rprintf(FINFO,
807                                 "ignoring --%s-batch option sent to server\n",
808                                 write_batch ? "write" : "read");
809                         /* We don't actually exit_cleanup(), so that we can
810                          * still service older version clients that still send
811                          * batch args to server. */
812                         read_batch = write_batch = 0;
813                         batch_name = NULL;
814                 }
815         }
816         if (read_batch && files_from) {
817                 snprintf(err_buf, sizeof err_buf,
818                         "--read-batch cannot be used with --files-from\n");
819                 return 0;
820         }
821         if (batch_name && strlen(batch_name) > MAX_BATCH_NAME_LEN) {
822                 snprintf(err_buf, sizeof err_buf,
823                         "the batch-file name must be %d characters or less.\n",
824                         MAX_BATCH_NAME_LEN);
825                 return 0;
826         }
827
828         if (tmpdir && strlen(tmpdir) >= MAXPATHLEN - 10) {
829                 snprintf(err_buf, sizeof err_buf,
830                          "the --temp-dir path is WAY too long.\n");
831                 return 0;
832         }
833
834         if (compare_dest + copy_dest + link_dest > 1) {
835                 snprintf(err_buf, sizeof err_buf,
836                         "You may not mix --compare-dest, --copy-dest, and --link-dest.\n");
837                 return 0;
838         }
839
840         if (archive_mode) {
841                 if (!files_from)
842                         recurse = 1;
843 #if SUPPORT_LINKS
844                 preserve_links = 1;
845 #endif
846                 preserve_perms = 1;
847                 preserve_times = 1;
848                 preserve_gid = 1;
849                 preserve_uid = 1;
850                 preserve_devices = 1;
851         }
852
853         if (relative_paths < 0)
854                 relative_paths = files_from? 1 : 0;
855
856         *argv = poptGetArgs(pc);
857         *argc = count_args(*argv);
858
859         if (sanitize_paths) {
860                 int i;
861                 for (i = *argc; i-- > 0; )
862                         (*argv)[i] = sanitize_path(NULL, (*argv)[i], "", 0);
863                 if (tmpdir)
864                         tmpdir = sanitize_path(NULL, tmpdir, NULL, 0);
865                 if (partial_dir)
866                         partial_dir = sanitize_path(NULL, partial_dir, NULL, 0);
867                 if (backup_dir)
868                         backup_dir = sanitize_path(NULL, backup_dir, NULL, 0);
869                 if (files_from)
870                         files_from = sanitize_path(NULL, files_from, NULL, 0);
871         }
872         if (server_exclude_list.head && !am_sender) {
873                 struct exclude_list_struct *elp = &server_exclude_list;
874                 int i;
875                 if (tmpdir) {
876                         clean_fname(tmpdir, 1);
877                         if (check_exclude(elp, tmpdir, 1) < 0)
878                                 goto options_rejected;
879                 }
880                 if (partial_dir) {
881                         clean_fname(partial_dir, 1);
882                         if (check_exclude(elp, partial_dir, 1) < 0)
883                                 goto options_rejected;
884                 }
885                 for (i = 0; i < basis_dir_cnt; i++) {
886                         clean_fname(basis_dir[i], 1);
887                         if (check_exclude(elp, basis_dir[i], 1) < 0)
888                                 goto options_rejected;
889                 }
890                 if (backup_dir) {
891                         clean_fname(backup_dir, 1);
892                         if (check_exclude(elp, backup_dir, 1) < 0)
893                                 goto options_rejected;
894                 }
895         }
896         if (server_exclude_list.head && files_from) {
897                 clean_fname(files_from, 1);
898                 if (check_exclude(&server_exclude_list, files_from, 0) < 0) {
899                     options_rejected:
900                         snprintf(err_buf, sizeof err_buf,
901                             "Your options have been rejected by the server.\n");
902                         return 0;
903                 }
904         }
905
906         if (!backup_suffix)
907                 backup_suffix = backup_dir ? "" : BACKUP_SUFFIX;
908         backup_suffix_len = strlen(backup_suffix);
909         if (strchr(backup_suffix, '/') != NULL) {
910                 snprintf(err_buf, sizeof err_buf,
911                         "--suffix cannot contain slashes: %s\n",
912                         backup_suffix);
913                 return 0;
914         }
915         if (backup_dir) {
916                 backup_dir_len = strlcpy(backup_dir_buf, backup_dir, sizeof backup_dir_buf);
917                 backup_dir_remainder = sizeof backup_dir_buf - backup_dir_len;
918                 if (backup_dir_remainder < 32) {
919                         snprintf(err_buf, sizeof err_buf,
920                                 "the --backup-dir path is WAY too long.\n");
921                         return 0;
922                 }
923                 if (backup_dir_buf[backup_dir_len - 1] != '/') {
924                         backup_dir_buf[backup_dir_len++] = '/';
925                         backup_dir_buf[backup_dir_len] = '\0';
926                 }
927                 if (verbose > 1 && !am_sender)
928                         rprintf(FINFO, "backup_dir is %s\n", backup_dir_buf);
929         } else if (!backup_suffix_len && (!am_server || !am_sender)) {
930                 snprintf(err_buf, sizeof err_buf,
931                         "--suffix cannot be a null string without --backup-dir\n");
932                 return 0;
933         }
934
935         if (do_progress && !verbose)
936                 verbose = 1;
937
938         if (daemon_bwlimit && (!bwlimit || bwlimit > daemon_bwlimit))
939                 bwlimit = daemon_bwlimit;
940         if (bwlimit) {
941                 bwlimit_writemax = (size_t)bwlimit * 128;
942                 if (bwlimit_writemax < 512)
943                         bwlimit_writemax = 512;
944         }
945
946         if (inplace) {
947 #if HAVE_FTRUNCATE
948                 if (partial_dir) {
949                         snprintf(err_buf, sizeof err_buf,
950                                  "--inplace cannot be used with --partial-dir\n");
951                         return 0;
952                 }
953                 keep_partial = 0;
954 #else
955                 snprintf(err_buf, sizeof err_buf,
956                          "--inplace is not supported on this %s\n",
957                          am_server ? "server" : "client");
958                 return 0;
959 #endif
960                 if (compare_dest || copy_dest || link_dest) {
961                         snprintf(err_buf, sizeof err_buf,
962                                  "--inplace does not yet work with %s\n",
963                                  dest_option);
964                         return 0;
965                 }
966         } else {
967                 if (keep_partial && !partial_dir)
968                         partial_dir = getenv("RSYNC_PARTIAL_DIR");
969                 if (partial_dir) {
970                         if (!*partial_dir || strcmp(partial_dir, ".") == 0)
971                                 partial_dir = NULL;
972                         else if (*partial_dir != '/') {
973                                 add_exclude(&exclude_list, partial_dir,
974                                             XFLG_DIRECTORY);
975                         }
976                         keep_partial = 1;
977                 }
978         }
979
980         if (files_from) {
981                 char *colon;
982                 if (*argc > 2 || (!am_daemon && *argc == 1)) {
983                         usage(FERROR);
984                         exit_cleanup(RERR_SYNTAX);
985                 }
986                 if (strcmp(files_from, "-") == 0) {
987                         filesfrom_fd = 0;
988                         if (am_server)
989                                 remote_filesfrom_file = "-";
990                 }
991                 else if ((colon = find_colon(files_from)) != 0) {
992                         if (am_server) {
993                                 usage(FERROR);
994                                 exit_cleanup(RERR_SYNTAX);
995                         }
996                         remote_filesfrom_file = colon+1 + (colon[1] == ':');
997                         if (strcmp(remote_filesfrom_file, "-") == 0) {
998                                 snprintf(err_buf, sizeof err_buf,
999                                         "Invalid --files-from remote filename\n");
1000                                 return 0;
1001                         }
1002                 } else {
1003                         filesfrom_fd = open(files_from, O_RDONLY|O_BINARY);
1004                         if (filesfrom_fd < 0) {
1005                                 snprintf(err_buf, sizeof err_buf,
1006                                         "failed to open files-from file %s: %s\n",
1007                                         files_from, strerror(errno));
1008                                 return 0;
1009                         }
1010                 }
1011         }
1012
1013         return 1;
1014 }
1015
1016
1017 /**
1018  * Construct a filtered list of options to pass through from the
1019  * client to the server.
1020  *
1021  * This involves setting options that will tell the server how to
1022  * behave, and also filtering out options that are processed only
1023  * locally.
1024  **/
1025 void server_options(char **args,int *argc)
1026 {
1027         static char argstr[50+MAX_BASIS_DIRS*2];
1028         int ac = *argc;
1029         char *arg;
1030
1031         int i, x;
1032
1033         if (blocking_io == -1)
1034                 blocking_io = 0;
1035
1036         args[ac++] = "--server";
1037
1038         if (daemon_over_rsh) {
1039                 args[ac++] = "--daemon";
1040                 *argc = ac;
1041                 /* if we're passing --daemon, we're done */
1042                 return;
1043         }
1044
1045         if (!am_sender)
1046                 args[ac++] = "--sender";
1047
1048         x = 1;
1049         argstr[0] = '-';
1050         for (i = 0; i < verbose; i++)
1051                 argstr[x++] = 'v';
1052
1053         /* the -q option is intentionally left out */
1054         if (make_backups)
1055                 argstr[x++] = 'b';
1056         if (update_only)
1057                 argstr[x++] = 'u';
1058         if (dry_run)
1059                 argstr[x++] = 'n';
1060         if (preserve_links)
1061                 argstr[x++] = 'l';
1062         if (copy_links)
1063                 argstr[x++] = 'L';
1064         if (keep_dirlinks && am_sender)
1065                 argstr[x++] = 'K';
1066
1067         if (whole_file > 0)
1068                 argstr[x++] = 'W';
1069         /* We don't need to send --no-whole-file, because it's the
1070          * default for remote transfers, and in any case old versions
1071          * of rsync will not understand it. */
1072
1073         if (preserve_hard_links)
1074                 argstr[x++] = 'H';
1075         if (preserve_uid)
1076                 argstr[x++] = 'o';
1077         if (preserve_gid)
1078                 argstr[x++] = 'g';
1079         if (preserve_devices)
1080                 argstr[x++] = 'D';
1081         if (preserve_times)
1082                 argstr[x++] = 't';
1083         if (preserve_perms)
1084                 argstr[x++] = 'p';
1085         if (recurse)
1086                 argstr[x++] = 'r';
1087         if (always_checksum)
1088                 argstr[x++] = 'c';
1089         if (cvs_exclude)
1090                 argstr[x++] = 'C';
1091         if (ignore_times)
1092                 argstr[x++] = 'I';
1093         if (relative_paths)
1094                 argstr[x++] = 'R';
1095         if (one_file_system)
1096                 argstr[x++] = 'x';
1097         if (sparse_files)
1098                 argstr[x++] = 'S';
1099         if (do_compression)
1100                 argstr[x++] = 'z';
1101
1102         /* this is a complete hack - blame Rusty
1103
1104            this is a hack to make the list_only (remote file list)
1105            more useful */
1106         if (list_only && !recurse)
1107                 argstr[x++] = 'r';
1108
1109         argstr[x] = 0;
1110
1111         if (x != 1)
1112                 args[ac++] = argstr;
1113
1114         if (block_size) {
1115                 if (asprintf(&arg, "-B%u", block_size) < 0)
1116                         goto oom;
1117                 args[ac++] = arg;
1118         }
1119
1120         if (max_delete && am_sender) {
1121                 if (asprintf(&arg, "--max-delete=%d", max_delete) < 0)
1122                         goto oom;
1123                 args[ac++] = arg;
1124         }
1125
1126         if (max_size && am_sender) {
1127                 args[ac++] = "--max-size";
1128                 args[ac++] = max_size_arg;
1129         }
1130
1131         if (io_timeout) {
1132                 if (asprintf(&arg, "--timeout=%d", io_timeout) < 0)
1133                         goto oom;
1134                 args[ac++] = arg;
1135         }
1136
1137         if (bwlimit) {
1138                 if (asprintf(&arg, "--bwlimit=%d", bwlimit) < 0)
1139                         goto oom;
1140                 args[ac++] = arg;
1141         }
1142
1143         if (backup_dir) {
1144                 args[ac++] = "--backup-dir";
1145                 args[ac++] = backup_dir;
1146         }
1147
1148         /* Only send --suffix if it specifies a non-default value. */
1149         if (strcmp(backup_suffix, backup_dir ? "" : BACKUP_SUFFIX) != 0) {
1150                 /* We use the following syntax to avoid weirdness with '~'. */
1151                 if (asprintf(&arg, "--suffix=%s", backup_suffix) < 0)
1152                         goto oom;
1153                 args[ac++] = arg;
1154         }
1155
1156         if (am_sender) {
1157                 if (delete_excluded)
1158                         args[ac++] = "--delete-excluded";
1159                 else if (delete_mode)
1160                         args[ac++] = "--delete";
1161
1162                 if (delete_after)
1163                         args[ac++] = "--delete-after";
1164
1165                 if (force_delete)
1166                         args[ac++] = "--force";
1167         }
1168
1169         if (size_only)
1170                 args[ac++] = "--size-only";
1171
1172         if (modify_window_set) {
1173                 if (asprintf(&arg, "--modify-window=%d", modify_window) < 0)
1174                         goto oom;
1175                 args[ac++] = arg;
1176         }
1177
1178         if (checksum_seed) {
1179                 if (asprintf(&arg, "--checksum-seed=%d", checksum_seed) < 0)
1180                         goto oom;
1181                 args[ac++] = arg;
1182         }
1183
1184         if (partial_dir && am_sender) {
1185                 args[ac++] = "--partial-dir";
1186                 args[ac++] = partial_dir;
1187         } else if (keep_partial)
1188                 args[ac++] = "--partial";
1189
1190         if (ignore_errors)
1191                 args[ac++] = "--ignore-errors";
1192
1193         if (copy_unsafe_links)
1194                 args[ac++] = "--copy-unsafe-links";
1195
1196         if (safe_symlinks)
1197                 args[ac++] = "--safe-links";
1198
1199         if (numeric_ids)
1200                 args[ac++] = "--numeric-ids";
1201
1202         if (only_existing && am_sender)
1203                 args[ac++] = "--existing";
1204
1205         if (opt_ignore_existing && am_sender)
1206                 args[ac++] = "--ignore-existing";
1207
1208         if (inplace)
1209                 args[ac++] = "--inplace";
1210
1211         if (tmpdir) {
1212                 args[ac++] = "--temp-dir";
1213                 args[ac++] = tmpdir;
1214         }
1215
1216         if (basis_dir[0] && am_sender) {
1217                 /* the server only needs this option if it is not the sender,
1218                  *   and it may be an older version that doesn't know this
1219                  *   option, so don't send it if client is the sender.
1220                  */
1221                 int i;
1222                 for (i = 0; i < basis_dir_cnt; i++) {
1223                         args[ac++] = dest_option;
1224                         args[ac++] = basis_dir[i];
1225                 }
1226         }
1227
1228         if (files_from && (!am_sender || remote_filesfrom_file)) {
1229                 if (remote_filesfrom_file) {
1230                         args[ac++] = "--files-from";
1231                         args[ac++] = remote_filesfrom_file;
1232                         if (eol_nulls)
1233                                 args[ac++] = "--from0";
1234                 } else {
1235                         args[ac++] = "--files-from=-";
1236                         args[ac++] = "--from0";
1237                 }
1238         }
1239
1240         *argc = ac;
1241         return;
1242
1243     oom:
1244         out_of_memory("server_options");
1245 }
1246
1247 /**
1248  * Return the position of a ':' IF it is not part of a filename (i.e. as
1249  * long as it doesn't occur after a slash.
1250  */
1251 char *find_colon(char *s)
1252 {
1253         char *p, *p2;
1254
1255         p = strchr(s,':');
1256         if (!p)
1257                 return NULL;
1258
1259         /* now check to see if there is a / in the string before the : - if there is then
1260            discard the colon on the assumption that the : is part of a filename */
1261         p2 = strchr(s,'/');
1262         if (p2 && p2 < p)
1263                 return NULL;
1264
1265         return p;
1266 }