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