Split code out into separate files and remove some global variables to
[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 int make_backups = 0;
25
26 /**
27  * Should we send the whole file as literal data rather than trying to
28  * create an incremental diff?  This is on by default when both source
29  * and destination are local and we're not doing a batch delta,
30  * because there it's no cheaper to read the whole basis file than to
31  * just rewrite it.
32  *
33  * If both are 0, then look at whether we're local or remote and go by
34  * that.
35  **/
36 int whole_file = 0;
37 int no_whole_file = 0;
38
39 int copy_links = 0;
40 int preserve_links = 0;
41 int preserve_hard_links = 0;
42 int preserve_perms = 0;
43 int preserve_devices = 0;
44 int preserve_uid = 0;
45 int preserve_gid = 0;
46 int preserve_times = 0;
47 int update_only = 0;
48 int cvs_exclude = 0;
49 int dry_run=0;
50 int local_server=0;
51 int ignore_times=0;
52 int delete_mode=0;
53 int delete_excluded=0;
54 int one_file_system=0;
55 int remote_version=0;
56 int sparse_files=0;
57 int do_compression=0;
58 int am_root=0;
59 int orig_umask=0;
60 int relative_paths=0;
61 int numeric_ids = 0;
62 int force_delete = 0;
63 int io_timeout = 0;
64 int io_error = 0;
65 int read_only = 0;
66 int module_id = -1;
67 int am_server = 0;
68 int am_sender = 0;
69 int recurse = 0;
70 int am_daemon=0;
71 int do_stats=0;
72 int do_progress=0;
73 int keep_partial=0;
74 int safe_symlinks=0;
75 int copy_unsafe_links=0;
76 int block_size=BLOCK_SIZE;
77 int size_only=0;
78 int bwlimit=0;
79 int delete_after=0;
80 int only_existing=0;
81 int opt_ignore_existing=0;
82 int max_delete=0;
83 int ignore_errors=0;
84 #ifdef _WIN32
85 int modify_window=2;
86 #else
87 int modify_window=0;
88 #endif
89 int blocking_io=-1;
90
91
92 /** Network address family. **/
93 #ifdef INET6
94 int default_af_hint = 0;        /* Any protocol */
95 #else
96 int default_af_hint = AF_INET;  /* Must use IPv4 */
97 #endif
98
99 /** Do not go into the background when run as --daemon.  Good
100  * for debugging and required for running as a service on W32,
101  * or under Unix process-monitors. **/
102 int no_detach = 0;
103
104 int write_batch = 0;
105 int read_batch = 0;
106
107 char *backup_suffix = BACKUP_SUFFIX;
108 char *tmpdir = NULL;
109 char *compare_dest = NULL;
110 char *config_file = RSYNCD_CONF;
111 char *shell_cmd = NULL;
112 char *log_format = NULL;
113 char *password_file = NULL;
114 char *rsync_path = RSYNC_PATH;
115 char *backup_dir = NULL;
116 int rsync_port = RSYNC_PORT;
117
118 int verbose = 0;
119 int quiet = 0;
120 int always_checksum = 0;
121 int list_only = 0;
122
123 char *batch_prefix = NULL;
124
125 static int modify_window_set;
126
127 /** Local address to bind.  As a character string because it's
128  * interpreted by the IPv6 layer: should be a numeric IP4 or ip6
129  * address, or a hostname. **/
130 char *bind_address;
131
132
133 static void print_rsync_version(enum logcode f)
134 {
135         char const *got_socketpair = "no ";
136         char const *hardlinks = "no ";
137         char const *links = "no ";
138         char const *ipv6 = "no ";
139         STRUCT_STAT *dumstat;
140
141 #ifdef HAVE_SOCKETPAIR
142         got_socketpair = "";
143 #endif
144
145 #if SUPPORT_HARD_LINKS
146         hardlinks = "";
147 #endif
148
149 #if SUPPORT_LINKS
150         links = "";
151 #endif
152
153 #if INET6
154         ipv6 = "";
155 #endif       
156
157         rprintf(f, "%s  version %s  protocol version %d\n",
158                 RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION);
159         rprintf(f,
160                 "Copyright (C) 1996-2002 by Andrew Tridgell and others\n");
161         rprintf(f, "<http://rsync.samba.org/>\n");
162         rprintf(f, "Capabilities: %d-bit files, %ssocketpairs, "
163                 "%shard links, %ssymlinks, batchfiles, \n",
164                 (int) (sizeof(OFF_T) * 8),
165                 got_socketpair, hardlinks, links);
166
167         /* Note that this field may not have type ino_t.  It depends
168          * on the complicated interaction between largefile feature
169          * macros. */
170         rprintf(f, "              %sIPv6, %d-bit system inums, %d-bit internal inums\n",
171                 ipv6, 
172                 (int) (sizeof(dumstat->st_ino) * 8),
173                 (int) (sizeof(INO64_T) * 8));
174
175 #ifdef NO_INT64
176         rprintf(f, "WARNING: no 64-bit integers on this platform!\n");
177 #endif
178
179         rprintf(f,
180 "\n"
181 "rsync comes with ABSOLUTELY NO WARRANTY.  This is free software, and you\n"
182 "are welcome to redistribute it under certain conditions.  See the GNU\n"
183 "General Public Licence for details.\n"
184                 );
185 }
186
187
188 void usage(enum logcode F)
189 {
190   print_rsync_version(F);
191
192   rprintf(F,"\nrsync is a file transfer program capable of efficient remote update\nvia a fast differencing algorithm.\n\n");
193
194   rprintf(F,"Usage: rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST\n");
195   rprintf(F,"  or   rsync [OPTION]... [USER@]HOST:SRC DEST\n");
196   rprintf(F,"  or   rsync [OPTION]... SRC [SRC]... DEST\n");
197   rprintf(F,"  or   rsync [OPTION]... [USER@]HOST::SRC [DEST]\n");
198   rprintf(F,"  or   rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST\n");
199   rprintf(F,"  or   rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST]\n");
200   rprintf(F,"SRC on single-colon remote HOST will be expanded by remote shell\n");
201   rprintf(F,"SRC on server remote HOST may contain shell wildcards or multiple\n");
202   rprintf(F,"  sources separated by space as long as they have same top-level\n");
203   rprintf(F,"\nOptions\n");
204   rprintf(F," -v, --verbose               increase verbosity\n");
205   rprintf(F," -q, --quiet                 decrease verbosity\n");
206   rprintf(F," -c, --checksum              always checksum\n");
207   rprintf(F," -a, --archive               archive mode\n");
208   rprintf(F," -r, --recursive             recurse into directories\n");
209   rprintf(F," -R, --relative              use relative path names\n");
210   rprintf(F," -b, --backup                make backups (default %s suffix)\n",BACKUP_SUFFIX);
211   rprintf(F,"     --backup-dir            make backups into this directory\n");
212   rprintf(F,"     --suffix=SUFFIX         override backup suffix\n");  
213   rprintf(F," -u, --update                update only (don't overwrite newer files)\n");
214   rprintf(F," -l, --links                 copy symlinks as symlinks\n");
215   rprintf(F," -L, --copy-links            copy the referent of symlinks\n");
216   rprintf(F,"     --copy-unsafe-links     copy links outside the source tree\n");
217   rprintf(F,"     --safe-links            ignore links outside the destination tree\n");
218   rprintf(F," -H, --hard-links            preserve hard links\n");
219   rprintf(F," -p, --perms                 preserve permissions\n");
220   rprintf(F," -o, --owner                 preserve owner (root only)\n");
221   rprintf(F," -g, --group                 preserve group\n");
222   rprintf(F," -D, --devices               preserve devices (root only)\n");
223   rprintf(F," -t, --times                 preserve times\n");  
224   rprintf(F," -S, --sparse                handle sparse files efficiently\n");
225   rprintf(F," -n, --dry-run               show what would have been transferred\n");
226   rprintf(F," -W, --whole-file            copy whole files, no incremental checks\n");
227   rprintf(F,"     --no-whole-file         turn off --whole-file\n");
228   rprintf(F," -x, --one-file-system       don't cross filesystem boundaries\n");
229   rprintf(F," -B, --block-size=SIZE       checksum blocking size (default %d)\n",BLOCK_SIZE);  
230   rprintf(F," -e, --rsh=COMMAND           specify rsh replacement\n");
231   rprintf(F,"     --rsync-path=PATH       specify path to rsync on the remote machine\n");
232   rprintf(F," -C, --cvs-exclude           auto ignore files in the same way CVS does\n");
233   rprintf(F,"     --existing              only update files that already exist\n");
234   rprintf(F,"     --ignore-existing       ignore files that already exist on the receiving side\n");
235   rprintf(F,"     --delete                delete files that don't exist on the sending side\n");
236   rprintf(F,"     --delete-excluded       also delete excluded files on the receiving side\n");
237   rprintf(F,"     --delete-after          delete after transferring, not before\n");
238   rprintf(F,"     --ignore-errors         delete even if there are IO errors\n");
239   rprintf(F,"     --max-delete=NUM        don't delete more than NUM files\n");
240   rprintf(F,"     --partial               keep partially transferred files\n");
241   rprintf(F,"     --force                 force deletion of directories even if not empty\n");
242   rprintf(F,"     --numeric-ids           don't map uid/gid values by user/group name\n");
243   rprintf(F,"     --timeout=TIME          set IO timeout in seconds\n");
244   rprintf(F," -I, --ignore-times          don't exclude files that match length and time\n");
245   rprintf(F,"     --size-only             only use file size when determining if a file should be transferred\n");
246   rprintf(F,"     --modify-window=NUM     Timestamp window (seconds) for file match (default=%d)\n",modify_window);
247   rprintf(F," -T  --temp-dir=DIR          create temporary files in directory DIR\n");
248   rprintf(F,"     --compare-dest=DIR      also compare destination files relative to DIR\n");
249   rprintf(F," -P                          equivalent to --partial --progress\n");
250   rprintf(F," -z, --compress              compress file data\n");
251   rprintf(F,"     --exclude=PATTERN       exclude files matching PATTERN\n");
252   rprintf(F,"     --exclude-from=FILE     exclude patterns listed in FILE\n");
253   rprintf(F,"     --include=PATTERN       don't exclude files matching PATTERN\n");
254   rprintf(F,"     --include-from=FILE     don't exclude patterns listed in FILE\n");
255   rprintf(F,"     --version               print version number\n");  
256   rprintf(F,"     --daemon                run as a rsync daemon\n");  
257   rprintf(F,"     --no-detach             do not detach from the parent\n");  
258   rprintf(F,"     --address=ADDRESS       bind to the specified address\n");  
259   rprintf(F,"     --config=FILE           specify alternate rsyncd.conf file\n");  
260   rprintf(F,"     --port=PORT             specify alternate rsyncd port number\n");
261   rprintf(F,"     --blocking-io           use blocking IO for the remote shell\n");  
262   rprintf(F,"     --no-blocking-io        turn off --blocking-io\n");  
263   rprintf(F,"     --stats                 give some file transfer stats\n");  
264   rprintf(F,"     --progress              show progress during transfer\n");  
265   rprintf(F,"     --log-format=FORMAT     log file transfers using specified format\n");  
266   rprintf(F,"     --password-file=FILE    get password from FILE\n");
267   rprintf(F,"     --bwlimit=KBPS          limit I/O bandwidth, KBytes per second\n");
268   rprintf(F,"     --write-batch=PREFIX    write batch fileset starting with PREFIX\n");
269   rprintf(F,"     --read-batch=PREFIX     read batch fileset starting with PREFIX\n");
270   rprintf(F," -h, --help                  show this help screen\n");
271 #ifdef INET6
272   rprintf(F," -4                          prefer IPv4\n");
273   rprintf(F," -6                          prefer IPv6\n");
274 #endif
275
276   rprintf(F,"\n");
277
278   rprintf(F,"\nPlease see the rsync(1) and rsyncd.conf(5) man pages for full documentation\n");
279   rprintf(F,"See http://rsync.samba.org/ for updates, bug reports, and answers\n");
280 }
281
282 enum {OPT_VERSION = 1000, OPT_SUFFIX, OPT_SENDER, OPT_SERVER, OPT_EXCLUDE,
283       OPT_EXCLUDE_FROM, OPT_DELETE, OPT_DELETE_EXCLUDED, OPT_NUMERIC_IDS,
284       OPT_RSYNC_PATH, OPT_FORCE, OPT_TIMEOUT, OPT_DAEMON, OPT_CONFIG, OPT_PORT,
285       OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_STATS, OPT_PARTIAL, OPT_PROGRESS,
286       OPT_COPY_UNSAFE_LINKS, OPT_SAFE_LINKS, OPT_COMPARE_DEST,
287       OPT_LOG_FORMAT, OPT_PASSWORD_FILE, OPT_SIZE_ONLY, OPT_ADDRESS,
288       OPT_DELETE_AFTER, OPT_EXISTING, OPT_MAX_DELETE, OPT_BACKUP_DIR, 
289       OPT_IGNORE_ERRORS, OPT_BWLIMIT, OPT_BLOCKING_IO,
290       OPT_NO_BLOCKING_IO, OPT_WHOLE_FILE, OPT_NO_WHOLE_FILE,
291       OPT_MODIFY_WINDOW, OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_IGNORE_EXISTING};
292
293 static struct poptOption long_options[] = {
294   /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
295   {"version",          0,  POPT_ARG_NONE,   0,             OPT_VERSION, 0, 0},
296   {"suffix",           0,  POPT_ARG_STRING, &backup_suffix,     0, 0, 0 },
297   {"rsync-path",       0,  POPT_ARG_STRING, &rsync_path,        0, 0, 0 },
298   {"password-file",    0,  POPT_ARG_STRING, &password_file,     0, 0, 0 },
299   {"ignore-times",    'I', POPT_ARG_NONE,   &ignore_times , 0, 0, 0 },
300   {"size-only",        0,  POPT_ARG_NONE,   &size_only , 0, 0, 0 },
301   {"modify-window",    0,  POPT_ARG_INT,    &modify_window, OPT_MODIFY_WINDOW, 0, 0 },
302   {"one-file-system", 'x', POPT_ARG_NONE,   &one_file_system , 0, 0, 0 },
303   {"delete",           0,  POPT_ARG_NONE,   &delete_mode , 0, 0, 0 },
304   {"existing",         0,  POPT_ARG_NONE,   &only_existing , 0, 0, 0 },
305   {"ignore-existing",  0,  POPT_ARG_NONE,   &opt_ignore_existing , 0, 0, 0 },
306   {"delete-after",     0,  POPT_ARG_NONE,   &delete_after , 0, 0, 0 },
307   {"delete-excluded",  0,  POPT_ARG_NONE,   0,              OPT_DELETE_EXCLUDED, 0, 0 },
308   {"force",            0,  POPT_ARG_NONE,   &force_delete , 0, 0, 0 },
309   {"numeric-ids",      0,  POPT_ARG_NONE,   &numeric_ids , 0, 0, 0 },
310   {"exclude",          0,  POPT_ARG_STRING, 0,              OPT_EXCLUDE, 0, 0 },
311   {"include",          0,  POPT_ARG_STRING, 0,              OPT_INCLUDE, 0, 0 },
312   {"exclude-from",     0,  POPT_ARG_STRING, 0,              OPT_EXCLUDE_FROM, 0, 0 },
313   {"include-from",     0,  POPT_ARG_STRING, 0,              OPT_INCLUDE_FROM, 0, 0 },
314   {"safe-links",       0,  POPT_ARG_NONE,   &safe_symlinks , 0, 0, 0 },
315   {"help",            'h', POPT_ARG_NONE,   0,              'h', 0, 0 },
316   {"backup",          'b', POPT_ARG_NONE,   &make_backups , 0, 0, 0 },
317   {"dry-run",         'n', POPT_ARG_NONE,   &dry_run , 0, 0, 0 },
318   {"sparse",          'S', POPT_ARG_NONE,   &sparse_files , 0, 0, 0 },
319   {"cvs-exclude",     'C', POPT_ARG_NONE,   &cvs_exclude , 0, 0, 0 },
320   {"update",          'u', POPT_ARG_NONE,   &update_only , 0, 0, 0 },
321   {"links",           'l', POPT_ARG_NONE,   &preserve_links , 0, 0, 0 },
322   {"copy-links",      'L', POPT_ARG_NONE,   &copy_links , 0, 0, 0 },
323   {"whole-file",      'W', POPT_ARG_NONE,   0,              OPT_WHOLE_FILE, 0, 0 },
324   {"no-whole-file",    0,  POPT_ARG_NONE,   0,              OPT_NO_WHOLE_FILE, 0, 0 },
325   {"copy-unsafe-links", 0, POPT_ARG_NONE,   &copy_unsafe_links , 0, 0, 0 },
326   {"perms",           'p', POPT_ARG_NONE,   &preserve_perms , 0, 0, 0 },
327   {"owner",           'o', POPT_ARG_NONE,   &preserve_uid , 0, 0, 0 },
328   {"group",           'g', POPT_ARG_NONE,   &preserve_gid , 0, 0, 0 },
329   {"devices",         'D', POPT_ARG_NONE,   &preserve_devices , 0, 0, 0 },
330   {"times",           't', POPT_ARG_NONE,   &preserve_times , 0, 0, 0 },
331   {"checksum",        'c', POPT_ARG_NONE,   &always_checksum , 0, 0, 0 },
332   {"verbose",         'v', POPT_ARG_NONE,   0,               'v', 0, 0 },
333   {"quiet",           'q', POPT_ARG_NONE,   0,               'q', 0, 0 },
334   {"archive",         'a', POPT_ARG_NONE,   0,               'a', 0, 0 }, 
335   {"server",           0,  POPT_ARG_NONE,   &am_server , 0, 0, 0 },
336   {"sender",           0,  POPT_ARG_NONE,   0,               OPT_SENDER, 0, 0 },
337   {"recursive",       'r', POPT_ARG_NONE,   &recurse , 0, 0, 0 },
338   {"relative",        'R', POPT_ARG_NONE,   &relative_paths , 0, 0, 0 },
339   {"rsh",             'e', POPT_ARG_STRING, &shell_cmd , 0, 0, 0 },
340   {"block-size",      'B', POPT_ARG_INT,    &block_size , 0, 0, 0 },
341   {"max-delete",       0,  POPT_ARG_INT,    &max_delete , 0, 0, 0 },
342   {"timeout",          0,  POPT_ARG_INT,    &io_timeout , 0, 0, 0 },
343   {"temp-dir",        'T', POPT_ARG_STRING, &tmpdir , 0, 0, 0 },
344   {"compare-dest",     0,  POPT_ARG_STRING, &compare_dest , 0, 0, 0 },
345   /* TODO: Should this take an optional int giving the compression level? */
346   {"compress",        'z', POPT_ARG_NONE,   &do_compression , 0, 0, 0 },
347   {"daemon",           0,  POPT_ARG_NONE,   &am_daemon , 0, 0, 0 },
348   {"no-detach",        0,  POPT_ARG_NONE,   &no_detach , 0, 0, 0 },
349   {"stats",            0,  POPT_ARG_NONE,   &do_stats , 0, 0, 0 },
350   {"progress",         0,  POPT_ARG_NONE,   &do_progress , 0, 0, 0 },
351   {"partial",          0,  POPT_ARG_NONE,   &keep_partial , 0, 0, 0 },
352   {"ignore-errors",    0,  POPT_ARG_NONE,   &ignore_errors , 0, 0, 0 },
353   {"blocking-io",      0,  POPT_ARG_NONE,   &blocking_io , 0, 0, 0 },
354   {"no-blocking-io",   0,  POPT_ARG_NONE,   0,               OPT_NO_BLOCKING_IO, 0, 0 },
355   {0,                 'P', POPT_ARG_NONE,   0,               'P', 0, 0 },
356   {"config",           0,  POPT_ARG_STRING, &config_file , 0, 0, 0 },
357   {"port",             0,  POPT_ARG_INT,    &rsync_port , 0, 0, 0 },
358   {"log-format",       0,  POPT_ARG_STRING, &log_format , 0, 0, 0 },
359   {"bwlimit",          0,  POPT_ARG_INT,    &bwlimit , 0, 0, 0 },
360   {"address",          0,  POPT_ARG_STRING, &bind_address, 0, 0, 0 },
361   {"backup-dir",       0,  POPT_ARG_STRING, &backup_dir , 0, 0, 0 },
362   {"hard-links",      'H', POPT_ARG_NONE,   &preserve_hard_links , 0, 0, 0 },
363   {"read-batch",       0,  POPT_ARG_STRING, &batch_prefix, OPT_READ_BATCH, 0, 0 },
364   {"write-batch",      0,  POPT_ARG_STRING, &batch_prefix, OPT_WRITE_BATCH, 0, 0 },
365 #ifdef INET6
366   {0,                 '4', POPT_ARG_VAL,    &default_af_hint,   AF_INET , 0, 0 },
367   {0,                 '6', POPT_ARG_VAL,    &default_af_hint,   AF_INET6 , 0, 0 },
368 #endif
369   {0,0,0,0, 0, 0, 0}
370 };
371
372
373 static char err_buf[100];
374
375
376 /* We store the option error message, if any, so that we can log the
377    connection attempt (which requires parsing the options), and then
378    show the error later on. */
379 void option_error(void)
380 {
381         if (err_buf[0]) {
382                 rprintf(FLOG, "%s", err_buf);
383                 rprintf(FERROR, "%s: %s", RSYNC_NAME, err_buf);
384         } else {
385                 rprintf (FERROR, "Error parsing options: "
386                          "option may be supported on client but not on server?\n");
387                 rprintf (FERROR, RSYNC_NAME ": Error parsing options: "
388                          "option may be supported on client but not on server?\n");
389         }
390 }
391
392 /* check to see if we should refuse this option */
393 static int check_refuse_options(char *ref, int opt)
394 {
395         int i, len;
396         char *p;
397         const char *name;
398
399         for (i=0; long_options[i].longName; i++) {
400                 if (long_options[i].val == opt) break;
401         }
402         
403         if (!long_options[i].longName) return 0;
404
405         name = long_options[i].longName;
406         len = strlen(name);
407
408         while ((p = strstr(ref,name))) {
409                 if ((p==ref || p[-1]==' ') &&
410                     (p[len] == ' ' || p[len] == 0)) {
411                         snprintf(err_buf,sizeof(err_buf),
412                                  "The '%s' option is not supported by this server\n", name);
413                         return 1;
414                 }
415                 ref += len;
416         }
417         return 0;
418 }
419
420
421 static int count_args(char const **argv)
422 {
423         int i = 0;
424
425         while (argv[i] != NULL)
426                 i++;
427         
428         return i;
429 }
430
431
432 /* Process command line arguments.  Called on both local and remote.
433  * Returns if all options are OK, otherwise fills in err_buf and
434  * returns 0. */
435 int parse_arguments(int *argc, const char ***argv, int frommain)
436 {
437         int opt;
438         char *ref = lp_refuse_options(module_id);
439         poptContext pc;
440
441         /* TODO: Call poptReadDefaultConfig; handle errors. */
442
443         /* The context leaks in case of an error, but if there's a
444          * problem we always exit anyhow. */
445         pc = poptGetContext(RSYNC_NAME, *argc, *argv, long_options, 0);
446
447         while ((opt = poptGetNextOpt(pc)) != -1) {
448                 if (ref) {
449                         if (check_refuse_options(ref, opt)) return 0;
450                 }
451
452                 /* most options are handled automatically by popt;
453                  * only special cases are returned and listed here. */
454
455                 switch (opt) {
456                 case OPT_VERSION:
457                         print_rsync_version(FINFO);
458                         exit_cleanup(0);
459                         
460                 case OPT_MODIFY_WINDOW:
461                         /* The value has already been set by popt, but
462                          * we need to remember that we're using a
463                          * non-default setting. */
464                         modify_window_set = 1;
465                         break;
466                         
467                 case OPT_DELETE_EXCLUDED:
468                         delete_excluded = 1;
469                         delete_mode = 1;
470                         break;
471
472                 case OPT_EXCLUDE:
473                         add_exclude(poptGetOptArg(pc), 0);
474                         break;
475
476                 case OPT_INCLUDE:
477                         add_exclude(poptGetOptArg(pc), 1);
478                         break;
479
480                 case OPT_EXCLUDE_FROM:
481                         add_exclude_file(poptGetOptArg(pc), 1, 0);
482                         break;
483
484                 case OPT_INCLUDE_FROM:
485                         add_exclude_file(poptGetOptArg(pc), 1, 1);
486                         break;
487
488                 case OPT_WHOLE_FILE:
489                         whole_file = 1;
490                         no_whole_file = 0;
491                         break;
492
493                 case OPT_NO_WHOLE_FILE:
494                         no_whole_file = 1;
495                         whole_file = 0;
496                         break;
497
498                 case OPT_NO_BLOCKING_IO:
499                         blocking_io = 0;
500                         break;
501
502                 case 'h':
503                         usage(FINFO);
504                         exit_cleanup(0);
505
506                 case 'H':
507 #if SUPPORT_HARD_LINKS
508                         preserve_hard_links=1;
509 #else
510                         /* FIXME: Don't say "server" if this is
511                          * happening on the client. */
512                         /* FIXME: Why do we have the duplicated
513                          * rprintf?  Everybody who gets this message
514                          * ought to send it to the client and also to
515                          * the logs. */
516                         snprintf(err_buf,sizeof(err_buf),
517                                  "hard links are not supported on this %s\n",
518                                  am_server ? "server" : "client");
519                         rprintf(FERROR,"ERROR: hard links not supported on this platform\n");
520                         return 0;
521 #endif /* SUPPORT_HARD_LINKS */
522                         break;
523
524                 case 'v':
525                         verbose++;
526                         break;
527
528                 case 'q':
529                         if (frommain) quiet++;
530                         break;
531
532                 case 'a':
533                         recurse=1;
534 #if SUPPORT_LINKS
535                         preserve_links=1;
536 #endif
537                         preserve_perms=1;
538                         preserve_times=1;
539                         preserve_gid=1;
540                         preserve_uid=1;
541                         preserve_devices=1;
542                         break;
543
544                 case OPT_SENDER:
545                         if (!am_server) {
546                                 usage(FERROR);
547                                 exit_cleanup(RERR_SYNTAX);
548                         }
549                         am_sender = 1;
550                         break;
551
552                 case 'P':
553                         do_progress = 1;
554                         keep_partial = 1;
555                         break;
556
557                 case OPT_WRITE_BATCH:
558                         /* popt stores the filename in batch_prefix for us */
559                         write_batch = 1;
560                         break;
561
562                 case OPT_READ_BATCH:
563                         /* popt stores the filename in batch_prefix for us */
564                         read_batch = 1;
565                         break;
566
567                 default:
568                         /* FIXME: If --daemon is specified, then errors for later
569                          * parameters seem to disappear. */
570                         snprintf(err_buf, sizeof(err_buf),
571                                  "%s%s: %s\n",
572                                  am_server ? "on remote machine: " : "",
573                                  poptBadOption(pc, POPT_BADOPTION_NOALIAS),
574                                  poptStrerror(opt));
575                         return 0;
576                 }
577         }
578
579         if (write_batch && read_batch) {
580             snprintf(err_buf,sizeof(err_buf),
581                 "write-batch and read-batch can not be used together\n");
582             rprintf(FERROR,"ERROR: write-batch and read-batch"
583                 " can not be used together\n");
584             return 0;
585         }
586
587         if (do_compression && (write_batch || read_batch)) {
588             snprintf(err_buf,sizeof(err_buf),
589                 "compress can not be used with write-batch or read-batch\n");
590             rprintf(FERROR,"ERROR: compress can not be used with"
591                 "  write-batch or read-batch\n");
592             return 0;
593         }
594
595         *argv = poptGetArgs(pc);
596         if (*argv)
597                 *argc = count_args(*argv);
598         else
599                 *argc = 0;
600
601         return 1;
602 }
603
604
605 /* Construct a filtered list of options to pass through from the
606  * client to the server */
607 void server_options(char **args,int *argc)
608 {
609         int ac = *argc;
610         static char argstr[50];
611         static char bsize[30];
612         static char iotime[30];
613         static char mdelete[30];
614         static char mwindow[30];
615         static char bw[50];
616         /* Leave room for ``--(write|read)-batch='' */
617         static char fext[MAXPATHLEN + 15];
618
619         int i, x;
620
621         if (blocking_io == -1)
622                 blocking_io = 0;
623
624         args[ac++] = "--server";
625
626         if (!am_sender)
627                 args[ac++] = "--sender";
628
629         x = 1;
630         argstr[0] = '-';
631         for (i=0;i<verbose;i++)
632                 argstr[x++] = 'v';
633
634         /* the -q option is intentionally left out */
635         if (make_backups)
636                 argstr[x++] = 'b';
637         if (update_only)
638                 argstr[x++] = 'u';
639         if (dry_run)
640                 argstr[x++] = 'n';
641         if (preserve_links)
642                 argstr[x++] = 'l';
643         if (copy_links)
644                 argstr[x++] = 'L';
645
646         assert(whole_file == 0 || whole_file == 1);
647         if (whole_file)
648                 argstr[x++] = 'W';
649         /* We don't need to send --no-whole-file, because it's the
650          * default for remote transfers, and in any case old versions
651          * of rsync will not understand it. */
652         
653         if (preserve_hard_links)
654                 argstr[x++] = 'H';
655         if (preserve_uid)
656                 argstr[x++] = 'o';
657         if (preserve_gid)
658                 argstr[x++] = 'g';
659         if (preserve_devices)
660                 argstr[x++] = 'D';
661         if (preserve_times)
662                 argstr[x++] = 't';
663         if (preserve_perms)
664                 argstr[x++] = 'p';
665         if (recurse)
666                 argstr[x++] = 'r';
667         if (always_checksum)
668                 argstr[x++] = 'c';
669         if (cvs_exclude)
670                 argstr[x++] = 'C';
671         if (ignore_times)
672                 argstr[x++] = 'I';
673         if (relative_paths)
674                 argstr[x++] = 'R';
675         if (one_file_system)
676                 argstr[x++] = 'x';
677         if (sparse_files)
678                 argstr[x++] = 'S';
679         if (do_compression)
680                 argstr[x++] = 'z';
681
682         /* this is a complete hack - blame Rusty 
683
684            this is a hack to make the list_only (remote file list)
685            more useful */
686         if (list_only && !recurse) 
687                 argstr[x++] = 'r';
688
689         argstr[x] = 0;
690
691         if (x != 1) args[ac++] = argstr;
692
693         if (block_size != BLOCK_SIZE) {
694                 snprintf(bsize,sizeof(bsize),"-B%d",block_size);
695                 args[ac++] = bsize;
696         }    
697
698         if (max_delete && am_sender) {
699                 snprintf(mdelete,sizeof(mdelete),"--max-delete=%d",max_delete);
700                 args[ac++] = mdelete;
701         }    
702         
703         if (batch_prefix != NULL) {
704                 char *fmt = "";
705                 if (write_batch)
706                     fmt = "--write-batch=%s";
707                 else
708                 if (read_batch)
709                     fmt = "--read-batch=%s";
710                 snprintf(fext,sizeof(fext),fmt,batch_prefix);
711                 args[ac++] = fext;
712         }
713
714         if (io_timeout) {
715                 snprintf(iotime,sizeof(iotime),"--timeout=%d",io_timeout);
716                 args[ac++] = iotime;
717         }    
718
719         if (bwlimit) {
720                 snprintf(bw,sizeof(bw),"--bwlimit=%d",bwlimit);
721                 args[ac++] = bw;
722         }
723
724         if (strcmp(backup_suffix, BACKUP_SUFFIX)) {
725                 args[ac++] = "--suffix";
726                 args[ac++] = backup_suffix;
727         }
728
729         if (delete_mode && !delete_excluded)
730                 args[ac++] = "--delete";
731
732         if (delete_excluded)
733                 args[ac++] = "--delete-excluded";
734
735         if (size_only)
736                 args[ac++] = "--size-only";
737
738         if (modify_window_set) {
739                 snprintf(mwindow,sizeof(mwindow),"--modify-window=%d",
740                          modify_window);
741                 args[ac++] = mwindow;
742         }
743
744         if (keep_partial)
745                 args[ac++] = "--partial";
746
747         if (force_delete)
748                 args[ac++] = "--force";
749
750         if (delete_after)
751                 args[ac++] = "--delete-after";
752
753         if (ignore_errors)
754                 args[ac++] = "--ignore-errors";
755
756         if (copy_unsafe_links)
757                 args[ac++] = "--copy-unsafe-links";
758
759         if (safe_symlinks)
760                 args[ac++] = "--safe-links";
761
762         if (numeric_ids)
763                 args[ac++] = "--numeric-ids";
764
765         if (only_existing && am_sender)
766                 args[ac++] = "--existing";
767
768         if (opt_ignore_existing && am_sender) 
769                 args[ac++] = "--ignore-existing";
770
771         if (tmpdir) {
772                 args[ac++] = "--temp-dir";
773                 args[ac++] = tmpdir;
774         }
775
776         if (backup_dir && am_sender) {
777                 /* only the receiver needs this option, if we are the sender
778                  *   then we need to send it to the receiver.
779                  */
780                 args[ac++] = "--backup-dir";
781                 args[ac++] = backup_dir;
782         }
783
784         if (compare_dest && am_sender) {
785                 /* the server only needs this option if it is not the sender,
786                  *   and it may be an older version that doesn't know this
787                  *   option, so don't send it if client is the sender.
788                  */
789                 args[ac++] = "--compare-dest";
790                 args[ac++] = compare_dest;
791         }
792
793         *argc = ac;
794 }
795