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