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