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