X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/c60b7056b2750c6d8ff476d37cc2724b2bd15461..bdedced84b7f446f818efd4d25b8985285a50009:/options.c diff --git a/options.c b/options.c index 8a02d4f7..2d752bf8 100644 --- a/options.c +++ b/options.c @@ -23,7 +23,6 @@ extern int module_id; extern int sanitize_paths; -extern int select_timeout; extern struct filter_list_struct filter_list; extern struct filter_list_struct server_filter_list; @@ -53,6 +52,7 @@ int omit_dir_times = 0; int update_only = 0; int cvs_exclude = 0; int dry_run = 0; +int do_xfers = 1; int ignore_times = 0; int delete_mode = 0; int delete_during = 0; @@ -75,6 +75,7 @@ int implied_dirs = 1; int numeric_ids = 0; int force_delete = 0; int io_timeout = 0; +int allowed_lull = 0; char *files_from = NULL; int filesfrom_fd = -1; char *filesfrom_host = NULL; @@ -143,12 +144,13 @@ char *backup_dir = NULL; char backup_dir_buf[MAXPATHLEN]; int rsync_port = 0; int compare_dest = 0; +int copy_dest = 0; int link_dest = 0; int basis_dir_cnt = 0; +char *dest_option = NULL; int verbose = 0; int quiet = 0; -int itemize_changes = 0; int log_before_transfer = 0; int log_format_has_i = 0; int log_format_has_o_or_i = 0; @@ -161,9 +163,9 @@ char *batch_name = NULL; static int daemon_opt; /* sets am_daemon after option error-reporting */ static int F_option_cnt = 0; static int modify_window_set; +static int itemize_changes = 0; static int refused_delete, refused_archive_part; static int refused_partial, refused_progress, refused_delete_before; -static char *dest_option = NULL; static char *max_size_arg; static char partialdir_for_delayupdate[] = ".~tmp~"; @@ -249,7 +251,7 @@ void usage(enum logcode F) rprintf(F,"\nrsync is a file transfer program capable of efficient remote update\nvia a fast differencing algorithm.\n\n"); rprintf(F,"Usage: rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST\n"); - rprintf(F," or rsync [OPTION]... [USER@]HOST:SRC DEST\n"); + rprintf(F," or rsync [OPTION]... [USER@]HOST:SRC [DEST]\n"); rprintf(F," or rsync [OPTION]... SRC [SRC]... DEST\n"); rprintf(F," or rsync [OPTION]... [USER@]HOST::SRC [DEST]\n"); rprintf(F," or rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST\n"); @@ -292,7 +294,7 @@ void usage(enum logcode F) rprintf(F," -x, --one-file-system don't cross filesystem boundaries\n"); rprintf(F," -B, --block-size=SIZE force a fixed checksum block-size\n"); rprintf(F," -e, --rsh=COMMAND specify the remote shell to use\n"); - rprintf(F," --rsync-path=PATH specify path to rsync on the remote machine\n"); + rprintf(F," --rsync-path=PROGRAM specify the rsync to run on the remote machine\n"); rprintf(F," --existing only update files that already exist on receiver\n"); rprintf(F," --ignore-existing ignore files that already exist on receiving side\n"); rprintf(F," --remove-sent-files sent files/symlinks are removed from sending side\n"); @@ -317,6 +319,7 @@ void usage(enum logcode F) rprintf(F," -T, --temp-dir=DIR create temporary files in directory DIR\n"); rprintf(F," -y, --fuzzy find similar file for basis if no dest file\n"); rprintf(F," --compare-dest=DIR also compare destination files relative to DIR\n"); + rprintf(F," --copy-dest=DIR ... and include copies of unchanged files\n"); rprintf(F," --link-dest=DIR hardlink to files in DIR when unchanged\n"); rprintf(F," -z, --compress compress file data during the transfer\n"); rprintf(F," -C, --cvs-exclude auto-ignore files the same way CVS does\n"); @@ -328,8 +331,8 @@ void usage(enum logcode F) rprintf(F," --include=PATTERN don't exclude files matching PATTERN\n"); rprintf(F," --include-from=FILE read include patterns from FILE\n"); rprintf(F," --files-from=FILE read list of source-file names from FILE\n"); - rprintf(F," -0, --from0 all *-from file lists are delimited by nulls\n"); - rprintf(F," --version print version number\n"); + rprintf(F," -0, --from0 all *-from/filter files are delimited by 0s\n"); + rprintf(F," --address=ADDRESS bind address for outgoing socket to daemon\n"); rprintf(F," --port=PORT specify double-colon alternate port number\n"); rprintf(F," --blocking-io use blocking I/O for the remote shell\n"); rprintf(F," --no-blocking-io turn off blocking I/O when it is the default\n"); @@ -337,16 +340,19 @@ void usage(enum logcode F) rprintf(F," --progress show progress during transfer\n"); rprintf(F," -P same as --partial --progress\n"); rprintf(F," -i, --itemize-changes output a change-summary for all updates\n"); - rprintf(F," --log-format=FORMAT log file-transfers using specified format\n"); + rprintf(F," --log-format=FORMAT output filenames using the specified format\n"); rprintf(F," --password-file=FILE read password from FILE\n"); rprintf(F," --list-only list the files instead of copying them\n"); rprintf(F," --bwlimit=KBPS limit I/O bandwidth; KBytes per second\n"); rprintf(F," --write-batch=FILE write a batched update to FILE\n"); + rprintf(F," --only-write-batch=FILE like --write-batch but w/o updating destination\n"); rprintf(F," --read-batch=FILE read a batched update from FILE\n"); + rprintf(F," --protocol=NUM force an older protocol version to be used\n"); #ifdef INET6 rprintf(F," -4, --ipv4 prefer IPv4\n"); rprintf(F," -6, --ipv6 prefer IPv6\n"); #endif + rprintf(F," --version print version number\n"); rprintf(F," -h, --help show this help screen\n"); rprintf(F,"\nUse \"rsync --daemon --help\" to see the daemon-mode command-line options.\n"); @@ -355,9 +361,9 @@ void usage(enum logcode F) } enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM, - OPT_FILTER, OPT_COMPARE_DEST, OPT_LINK_DEST, + OPT_FILTER, OPT_COMPARE_DEST, OPT_COPY_DEST, OPT_LINK_DEST, OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW, - OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_TIMEOUT, OPT_MAX_SIZE, + OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_ONLY_WRITE_BATCH, OPT_MAX_SIZE, OPT_REFUSED_BASE = 9000}; static struct poptOption long_options[] = { @@ -413,7 +419,7 @@ static struct poptOption long_options[] = { {"archive", 'a', POPT_ARG_NONE, &archive_mode, 0, 0, 0 }, {"server", 0, POPT_ARG_NONE, &am_server, 0, 0, 0 }, {"sender", 0, POPT_ARG_NONE, 0, OPT_SENDER, 0, 0 }, - {"recursive", 'r', POPT_ARG_VAL, &recurse, -1, 0, 0 }, + {"recursive", 'r', POPT_ARG_NONE, &recurse, 0, 0, 0 }, {"list-only", 0, POPT_ARG_VAL, &list_only, 2, 0, 0 }, {"relative", 'R', POPT_ARG_VAL, &relative_paths, 1, 0, 0 }, {"no-relative", 0, POPT_ARG_VAL, &relative_paths, 0, 0, 0 }, @@ -421,9 +427,10 @@ static struct poptOption long_options[] = { {"block-size", 'B', POPT_ARG_LONG, &block_size, 0, 0, 0 }, {"max-delete", 0, POPT_ARG_INT, &max_delete, 0, 0, 0 }, {"max-size", 0, POPT_ARG_STRING, &max_size_arg, OPT_MAX_SIZE, 0, 0 }, - {"timeout", 0, POPT_ARG_INT, &io_timeout, OPT_TIMEOUT, 0, 0 }, + {"timeout", 0, POPT_ARG_INT, &io_timeout, 0, 0, 0 }, {"temp-dir", 'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 }, {"compare-dest", 0, POPT_ARG_STRING, 0, OPT_COMPARE_DEST, 0, 0 }, + {"copy-dest", 0, POPT_ARG_STRING, 0, OPT_COPY_DEST, 0, 0 }, {"link-dest", 0, POPT_ARG_STRING, 0, OPT_LINK_DEST, 0, 0 }, {"fuzzy", 'y', POPT_ARG_NONE, &fuzzy_basis, 0, 0, 0 }, /* TODO: Should this take an optional int giving the compression level? */ @@ -438,6 +445,7 @@ static struct poptOption long_options[] = { {"no-blocking-io", 0, POPT_ARG_VAL, &blocking_io, 0, 0, 0 }, {0, 'F', POPT_ARG_NONE, 0, 'F', 0, 0 }, {0, 'P', POPT_ARG_NONE, 0, 'P', 0, 0 }, + {"address", 0, POPT_ARG_STRING, &bind_address, 0, 0, 0 }, {"port", 0, POPT_ARG_INT, &rsync_port, 0, 0, 0 }, {"log-format", 0, POPT_ARG_STRING, &log_format, 0, 0, 0 }, {"itemize-changes", 'i', POPT_ARG_NONE, &itemize_changes, 0, 0, 0 }, @@ -446,6 +454,7 @@ static struct poptOption long_options[] = { {"hard-links", 'H', POPT_ARG_NONE, &preserve_hard_links, 0, 0, 0 }, {"read-batch", 0, POPT_ARG_STRING, &batch_name, OPT_READ_BATCH, 0, 0 }, {"write-batch", 0, POPT_ARG_STRING, &batch_name, OPT_WRITE_BATCH, 0, 0 }, + {"only-write-batch", 0, POPT_ARG_STRING, &batch_name, OPT_ONLY_WRITE_BATCH, 0, 0 }, {"files-from", 0, POPT_ARG_STRING, &files_from, 0, 0, 0 }, {"from0", '0', POPT_ARG_NONE, &eol_nulls, 0, 0, 0}, {"no-implied-dirs", 0, POPT_ARG_VAL, &implied_dirs, 0, 0, 0 }, @@ -456,7 +465,6 @@ static struct poptOption long_options[] = { {"ipv6", '6', POPT_ARG_VAL, &default_af_hint, AF_INET6, 0, 0 }, #endif /* All these options switch us into daemon-mode option-parsing. */ - {"address", 0, POPT_ARG_STRING, 0, OPT_DAEMON, 0, 0 }, {"config", 0, POPT_ARG_STRING, 0, OPT_DAEMON, 0, 0 }, {"daemon", 0, POPT_ARG_NONE, 0, OPT_DAEMON, 0, 0 }, {"detach", 0, POPT_ARG_NONE, 0, OPT_DAEMON, 0, 0 }, @@ -613,6 +621,35 @@ static int count_args(const char **argv) } +static OFF_T parse_size_arg(const char *size_arg) +{ + const char *arg; + OFF_T size; + + for (arg = size_arg; isdigit(*(uchar*)arg); arg++) {} + if (*arg == '.') + for (arg++; isdigit(*(uchar*)arg); arg++) {} + switch (*arg) { + case 'k': case 'K': + size = atof(size_arg) * 1024; + break; + case 'm': case 'M': + size = atof(size_arg) * 1024*1024; + break; + case 'g': case 'G': + size = atof(size_arg) * 1024*1024*1024; + break; + case '\0': + size = atof(size_arg); + break; + default: + size = 0; + break; + } + return size; +} + + static void create_refuse_error(int which) { /* The "which" value is the index + OPT_REFUSED_BASE. */ @@ -787,33 +824,18 @@ int parse_arguments(int *argc, const char ***argv, int frommain) write_batch = 1; break; + case OPT_ONLY_WRITE_BATCH: + /* batch_name is already set */ + write_batch = -1; + break; + case OPT_READ_BATCH: /* batch_name is already set */ read_batch = 1; break; case OPT_MAX_SIZE: - for (arg = max_size_arg; isdigit(*(uchar*)arg); arg++) {} - if (*arg == '.') - for (arg++; isdigit(*(uchar*)arg); arg++) {} - switch (*arg) { - case 'k': case 'K': - max_size = atof(max_size_arg) * 1024; - break; - case 'm': case 'M': - max_size = atof(max_size_arg) * 1024*1024; - break; - case 'g': case 'G': - max_size = atof(max_size_arg) * 1024*1024*1024; - break; - case '\0': - max_size = atof(max_size_arg); - break; - default: - max_size = 0; - break; - } - if (max_size <= 0) { + if ((max_size = parse_size_arg(max_size_arg)) <= 0) { snprintf(err_buf, sizeof err_buf, "--max-size value is invalid: %s\n", max_size_arg); @@ -821,11 +843,6 @@ int parse_arguments(int *argc, const char ***argv, int frommain) } break; - case OPT_TIMEOUT: - if (io_timeout && io_timeout < select_timeout) - select_timeout = io_timeout; - break; - case OPT_LINK_DEST: #ifdef HAVE_LINK link_dest = 1; @@ -838,6 +855,11 @@ int parse_arguments(int *argc, const char ***argv, int frommain) return 0; #endif + case OPT_COPY_DEST: + copy_dest = 1; + dest_option = "--copy-dest"; + goto set_dest_dir; + case OPT_COMPARE_DEST: compare_dest = 1; dest_option = "--compare-dest"; @@ -892,13 +914,7 @@ int parse_arguments(int *argc, const char ***argv, int frommain) "--write-batch and --read-batch can not be used together\n"); return 0; } - if (write_batch || read_batch) { - if (dry_run) { - snprintf(err_buf, sizeof err_buf, - "--%s-batch cannot be used with --dry_run (-n)\n", - write_batch ? "write" : "read"); - return 0; - } + if (write_batch > 0 || read_batch) { if (am_server) { rprintf(FINFO, "ignoring --%s-batch option sent to server\n", @@ -908,7 +924,8 @@ int parse_arguments(int *argc, const char ***argv, int frommain) * batch args to server. */ read_batch = write_batch = 0; batch_name = NULL; - } + } else if (dry_run) + write_batch = 0; } if (read_batch && files_from) { snprintf(err_buf, sizeof err_buf, @@ -928,9 +945,9 @@ int parse_arguments(int *argc, const char ***argv, int frommain) return 0; } - if (compare_dest + link_dest > 1) { + if (compare_dest + copy_dest + link_dest > 1) { snprintf(err_buf, sizeof err_buf, - "You may not mix --compare-dest and --link-dest.\n"); + "You may not mix --compare-dest, --copy-dest, and --link-dest.\n"); return 0; } @@ -940,7 +957,7 @@ int parse_arguments(int *argc, const char ***argv, int frommain) return 0; } if (!files_from) - recurse = -1; /* infinite recursion */ + recurse = 1; #ifdef SUPPORT_LINKS preserve_links = 1; #endif @@ -1074,10 +1091,10 @@ int parse_arguments(int *argc, const char ***argv, int frommain) omit_dir_times = 1; if (log_format) { - if (strstr(log_format, "%i") != NULL) + if (log_format_has(log_format, 'i')) log_format_has_i = 1; - if (strstr(log_format, "%b") == NULL - && strstr(log_format, "%c") == NULL) + if (!log_format_has(log_format, 'b') + && !log_format_has(log_format, 'c')) log_before_transfer = !am_server; } else if (itemize_changes) { log_format = "%i %n%L"; @@ -1089,12 +1106,16 @@ int parse_arguments(int *argc, const char ***argv, int frommain) && !am_server) verbose = 1; + if (dry_run) + do_xfers = 0; + + set_io_timeout(io_timeout); + if (verbose && !log_format) { log_format = "%n%L"; log_before_transfer = !am_server; } - if (log_format_has_i - || (log_format && strstr(log_format, "%o") != NULL)) + if (log_format_has_i || log_format_has(log_format, 'o')) log_format_has_o_or_i = 1; if (daemon_bwlimit && (!bwlimit || bwlimit > daemon_bwlimit)) @@ -1211,7 +1232,7 @@ int parse_arguments(int *argc, const char ***argv, int frommain) **/ void server_options(char **args,int *argc) { - static char argstr[50+MAX_BASIS_DIRS*2]; + static char argstr[64]; int ac = *argc; char *arg; @@ -1242,7 +1263,7 @@ void server_options(char **args,int *argc) argstr[x++] = 'b'; if (update_only) argstr[x++] = 'u'; - if (dry_run) + if (!do_xfers) /* NOT "dry_run"! */ argstr[x++] = 'n'; if (preserve_links) argstr[x++] = 'l'; @@ -1273,7 +1294,7 @@ void server_options(char **args,int *argc) argstr[x++] = 'O'; if (preserve_perms) argstr[x++] = 'p'; - if (recurse < 0) + if (recurse) argstr[x++] = 'r'; if (always_checksum) argstr[x++] = 'c'; @@ -1293,7 +1314,7 @@ void server_options(char **args,int *argc) /* This is a complete hack - blame Rusty. FIXME! * This hack is only needed for older rsync versions that * don't understand the --list-only option. */ - if (list_only == 1 && recurse >= 0) + if (list_only == 1 && !recurse) argstr[x++] = 'r'; argstr[x] = 0; @@ -1370,6 +1391,8 @@ void server_options(char **args,int *argc) args[ac++] = "--delete-after"; if (force_delete) args[ac++] = "--force"; + if (write_batch < 0) + args[ac++] = "--only-write-batch=X"; } if (size_only)