X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/58b1999e086721ff77d8f3d5e0d29e1e58c70a94..3610c4583a6b187fa6fc98ad0025340c6f840d53:/options.c diff --git a/options.c b/options.c index ec42bf8d..97e1daed 100644 --- a/options.c +++ b/options.c @@ -232,7 +232,7 @@ void usage(enum logcode F) rprintf(F," -v, --verbose increase verbosity\n"); rprintf(F," -q, --quiet decrease verbosity\n"); rprintf(F," -c, --checksum always checksum\n"); - rprintf(F," -a, --archive archive mode, equivalent to -rlptgoD\n"); + rprintf(F," -a, --archive archive mode, equivalent to -rlptgoD (no -H)\n"); rprintf(F," -r, --recursive recurse into directories\n"); rprintf(F," -R, --relative use relative path names\n"); rprintf(F," --no-relative turn off --relative\n"); @@ -289,11 +289,6 @@ void usage(enum logcode F) rprintf(F," --files-from=FILE read FILE for list of source-file names\n"); rprintf(F," -0, --from0 all *-from file lists are delimited by nulls\n"); rprintf(F," --version print version number\n"); - rprintf(F," --daemon run as an rsync daemon\n"); - rprintf(F," --no-detach do not detach from the parent\n"); - rprintf(F," --address=ADDRESS bind to the specified address\n"); - rprintf(F," --config=FILE specify alternate rsyncd.conf file\n"); - rprintf(F," --port=PORT specify alternate rsyncd port number\n"); rprintf(F," --blocking-io use blocking I/O for the remote shell\n"); rprintf(F," --no-blocking-io turn off --blocking-io\n"); rprintf(F," --stats give some file transfer stats\n"); @@ -303,20 +298,18 @@ void usage(enum logcode F) rprintf(F," --bwlimit=KBPS limit I/O bandwidth, KBytes per second\n"); rprintf(F," --write-batch=FILE write a batch to FILE\n"); rprintf(F," --read-batch=FILE read a batch from FILE\n"); - rprintf(F," --checksum-seed=NUM set block/file checksum seed\n"); #ifdef INET6 rprintf(F," -4, --ipv4 prefer IPv4\n"); rprintf(F," -6, --ipv6 prefer IPv6\n"); #endif rprintf(F," -h, --help show this help screen\n"); - rprintf(F,"\n"); - - rprintf(F,"\nPlease see the rsync(1) and rsyncd.conf(5) man pages for full documentation\n"); + rprintf(F,"\nUse \"rsync --daemon --help\" to see the daemon-mode command-line options.\n"); + rprintf(F,"Please see the rsync(1) and rsyncd.conf(5) man pages for full documentation.\n"); rprintf(F,"See http://rsync.samba.org/ for updates, bug reports, and answers\n"); } -enum {OPT_VERSION = 1000, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM, +enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM, OPT_DELETE_AFTER, OPT_DELETE_EXCLUDED, OPT_LINK_DEST, OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW, OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_TIMEOUT, @@ -324,7 +317,7 @@ enum {OPT_VERSION = 1000, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM, static struct poptOption long_options[] = { /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */ - {"version", 0, POPT_ARG_NONE, 0, OPT_VERSION, 0, 0}, + {"version", 0, POPT_ARG_NONE, 0, OPT_VERSION, 0, 0}, {"suffix", 0, POPT_ARG_STRING, &backup_suffix, 0, 0, 0 }, {"rsync-path", 0, POPT_ARG_STRING, &rsync_path, 0, 0, 0 }, {"password-file", 0, POPT_ARG_STRING, &password_file, 0, 0, 0 }, @@ -335,16 +328,16 @@ static struct poptOption long_options[] = { {"delete", 0, POPT_ARG_NONE, &delete_mode, 0, 0, 0 }, {"existing", 0, POPT_ARG_NONE, &only_existing, 0, 0, 0 }, {"ignore-existing", 0, POPT_ARG_NONE, &opt_ignore_existing, 0, 0, 0 }, - {"delete-after", 0, POPT_ARG_NONE, 0, OPT_DELETE_AFTER, 0, 0 }, - {"delete-excluded", 0, POPT_ARG_NONE, 0, OPT_DELETE_EXCLUDED, 0, 0 }, + {"delete-after", 0, POPT_ARG_NONE, 0, OPT_DELETE_AFTER, 0, 0 }, + {"delete-excluded", 0, POPT_ARG_NONE, 0, OPT_DELETE_EXCLUDED, 0, 0 }, {"force", 0, POPT_ARG_NONE, &force_delete, 0, 0, 0 }, {"numeric-ids", 0, POPT_ARG_NONE, &numeric_ids, 0, 0, 0 }, - {"exclude", 0, POPT_ARG_STRING, 0, OPT_EXCLUDE, 0, 0 }, - {"include", 0, POPT_ARG_STRING, 0, OPT_INCLUDE, 0, 0 }, - {"exclude-from", 0, POPT_ARG_STRING, 0, OPT_EXCLUDE_FROM, 0, 0 }, - {"include-from", 0, POPT_ARG_STRING, 0, OPT_INCLUDE_FROM, 0, 0 }, + {"exclude", 0, POPT_ARG_STRING, 0, OPT_EXCLUDE, 0, 0 }, + {"include", 0, POPT_ARG_STRING, 0, OPT_INCLUDE, 0, 0 }, + {"exclude-from", 0, POPT_ARG_STRING, 0, OPT_EXCLUDE_FROM, 0, 0 }, + {"include-from", 0, POPT_ARG_STRING, 0, OPT_INCLUDE_FROM, 0, 0 }, {"safe-links", 0, POPT_ARG_NONE, &safe_symlinks, 0, 0, 0 }, - {"help", 'h', POPT_ARG_NONE, 0, 'h', 0, 0 }, + {"help", 'h', POPT_ARG_NONE, 0, 'h', 0, 0 }, {"backup", 'b', POPT_ARG_NONE, &make_backups, 0, 0, 0 }, {"dry-run", 'n', POPT_ARG_NONE, &dry_run, 0, 0, 0 }, {"sparse", 'S', POPT_ARG_NONE, &sparse_files, 0, 0, 0 }, @@ -363,11 +356,11 @@ static struct poptOption long_options[] = { {"devices", 'D', POPT_ARG_NONE, &preserve_devices, 0, 0, 0 }, {"times", 't', POPT_ARG_NONE, &preserve_times, 0, 0, 0 }, {"checksum", 'c', POPT_ARG_NONE, &always_checksum, 0, 0, 0 }, - {"verbose", 'v', POPT_ARG_NONE, 0, 'v', 0, 0 }, - {"quiet", 'q', POPT_ARG_NONE, 0, 'q', 0, 0 }, + {"verbose", 'v', POPT_ARG_NONE, 0, 'v', 0, 0 }, + {"quiet", 'q', POPT_ARG_NONE, 0, 'q', 0, 0 }, {"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 }, + {"sender", 0, POPT_ARG_NONE, 0, OPT_SENDER, 0, 0 }, {"recursive", 'r', POPT_ARG_NONE, &recurse, 0, 0, 0 }, {"relative", 'R', POPT_ARG_VAL, &relative_paths, 1, 0, 0 }, {"no-relative", 0, POPT_ARG_VAL, &relative_paths, 0, 0, 0 }, @@ -377,11 +370,9 @@ static struct poptOption long_options[] = { {"timeout", 0, POPT_ARG_INT, &io_timeout, OPT_TIMEOUT, 0, 0 }, {"temp-dir", 'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 }, {"compare-dest", 0, POPT_ARG_STRING, &compare_dest, 0, 0, 0 }, - {"link-dest", 0, POPT_ARG_STRING, &compare_dest, OPT_LINK_DEST, 0, 0 }, + {"link-dest", 0, POPT_ARG_STRING, &compare_dest, OPT_LINK_DEST, 0, 0 }, /* TODO: Should this take an optional int giving the compression level? */ {"compress", 'z', POPT_ARG_NONE, &do_compression, 0, 0, 0 }, - {"daemon", 0, POPT_ARG_NONE, &daemon_opt, 0, 0, 0 }, - {"no-detach", 0, POPT_ARG_NONE, &no_detach, 0, 0, 0 }, {"stats", 0, POPT_ARG_NONE, &do_stats, 0, 0, 0 }, {"progress", 0, POPT_ARG_NONE, &do_progress, 0, 0, 0 }, {"partial", 0, POPT_ARG_NONE, &keep_partial, 0, 0, 0 }, @@ -389,16 +380,13 @@ static struct poptOption long_options[] = { {"ignore-errors", 0, POPT_ARG_NONE, &ignore_errors, 0, 0, 0 }, {"blocking-io", 0, POPT_ARG_VAL, &blocking_io, 1, 0, 0 }, {"no-blocking-io", 0, POPT_ARG_VAL, &blocking_io, 0, 0, 0 }, - {0, 'P', POPT_ARG_NONE, 0, 'P', 0, 0 }, - {"config", 0, POPT_ARG_STRING, &config_file, 0, 0, 0 }, - {"port", 0, POPT_ARG_INT, &rsync_port, 0, 0, 0 }, + {0, 'P', POPT_ARG_NONE, 0, 'P', 0, 0 }, {"log-format", 0, POPT_ARG_STRING, &log_format, 0, 0, 0 }, {"bwlimit", 0, POPT_ARG_INT, &bwlimit, 0, 0, 0 }, - {"address", 0, POPT_ARG_STRING, &bind_address, 0, 0, 0 }, {"backup-dir", 0, POPT_ARG_STRING, &backup_dir, 0, 0, 0 }, {"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 }, + {"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 }, {"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 }, @@ -408,6 +396,48 @@ static struct poptOption long_options[] = { {"ipv4", '4', POPT_ARG_VAL, &default_af_hint, AF_INET, 0, 0 }, {"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 }, + {"no-detach", 0, POPT_ARG_NONE, 0, OPT_DAEMON, 0, 0 }, + {"port", 0, POPT_ARG_INT, 0, OPT_DAEMON, 0, 0 }, + {0,0,0,0, 0, 0, 0} +}; + +static void daemon_usage(enum logcode F) +{ + print_rsync_version(F); + + rprintf(F,"\nUsage: rsync --daemon [OPTION]...\n"); + rprintf(F," --address=ADDRESS bind to the specified address\n"); + rprintf(F," --config=FILE specify alternate rsyncd.conf file\n"); + rprintf(F," --no-detach do not detach from the parent\n"); + rprintf(F," --port=PORT specify alternate rsyncd port number\n"); +#ifdef INET6 + rprintf(F," -4, --ipv4 prefer IPv4\n"); + rprintf(F," -6, --ipv6 prefer IPv6\n"); +#endif + rprintf(F," -h, --help show this help screen\n"); + + rprintf(F,"\nIf you were not trying to invoke rsync as a daemon, avoid using any of the\n"); + rprintf(F,"daemon-specific rsync options. See also the rsyncd.conf(5) man page.\n"); +} + +static struct poptOption long_daemon_options[] = { + /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */ + {"address", 0, POPT_ARG_STRING, &bind_address, 0, 0, 0 }, + {"config", 0, POPT_ARG_STRING, &config_file, 0, 0, 0 }, + {"daemon", 0, POPT_ARG_NONE, &daemon_opt, 0, 0, 0 }, +#ifdef INET6 + {"ipv4", '4', POPT_ARG_VAL, &default_af_hint, AF_INET, 0, 0 }, + {"ipv6", '6', POPT_ARG_VAL, &default_af_hint, AF_INET6, 0, 0 }, +#endif + {"no-detach", 0, POPT_ARG_NONE, &no_detach, 0, 0, 0 }, + {"port", 0, POPT_ARG_INT, &rsync_port, 0, 0, 0 }, + {"protocol", 0, POPT_ARG_INT, &protocol_version, 0, 0, 0 }, + {"server", 0, POPT_ARG_NONE, &am_server, 0, 0, 0 }, + {"help", 'h', POPT_ARG_NONE, 0, 'h', 0, 0 }, {0,0,0,0, 0, 0, 0} }; @@ -478,12 +508,14 @@ static void set_refuse_options(char *bp) } -static int count_args(char const **argv) +static int count_args(const char **argv) { int i = 0; - while (argv[i] != NULL) - i++; + if (argv) { + while (argv[i] != NULL) + i++; + } return i; } @@ -522,6 +554,41 @@ int parse_arguments(int *argc, const char ***argv, int frommain) print_rsync_version(FINFO); exit_cleanup(0); + case OPT_DAEMON: + if (am_daemon) { + strcpy(err_buf, "Attempt to hack rsync thwarted!\n"); + return 0; + } + poptFreeContext(pc); + pc = poptGetContext(RSYNC_NAME, *argc, *argv, + long_daemon_options, 0); + while ((opt = poptGetNextOpt(pc)) != -1) { + switch (opt) { + case 'h': + daemon_usage(FINFO); + exit_cleanup(0); + + default: + rprintf(FERROR, + "rsync: %s: %s (in daemon mode)\n", + poptBadOption(pc, POPT_BADOPTION_NOALIAS), + poptStrerror(opt)); + goto daemon_error; + } + } + if (!daemon_opt) { + rprintf(FERROR, "Daemon option(s) used without --daemon.\n"); + daemon_error: + rprintf(FERROR, + "(Type \"rsync --daemon --help\" for assistance with daemon mode.)\n"); + exit_cleanup(RERR_SYNTAX); + } + *argv = poptGetArgs(pc); + *argc = count_args(*argv); + daemon_opt = 0; + am_daemon = 1; + return 1; + case OPT_MODIFY_WINDOW: /* The value has already been set by popt, but * we need to remember that we're using a @@ -540,32 +607,28 @@ int parse_arguments(int *argc, const char ***argv, int frommain) break; case OPT_EXCLUDE: - if (am_server || sanitize_paths) - return 0; /* Impossible... */ add_exclude(&exclude_list, poptGetOptArg(pc), 0); break; case OPT_INCLUDE: - if (am_server || sanitize_paths) - return 0; /* Impossible... */ add_exclude(&exclude_list, poptGetOptArg(pc), XFLG_DEF_INCLUDE); break; case OPT_EXCLUDE_FROM: - if (am_server || sanitize_paths) - return 0; /* Impossible... */ - arg = poptGetOptArg(pc); - add_exclude_file(&exclude_list, arg, - XFLG_FATAL_ERRORS); - break; - case OPT_INCLUDE_FROM: - if (am_server || sanitize_paths) - return 0; /* Impossible... */ arg = poptGetOptArg(pc); - add_exclude_file(&exclude_list, arg, - XFLG_FATAL_ERRORS | XFLG_DEF_INCLUDE); + if (sanitize_paths) + arg = sanitize_path(NULL, arg, NULL, 0); + if (server_exclude_list.head) { + char *cp = (char *)arg; + clean_fname(cp, 1); + if (check_exclude(&server_exclude_list, cp, 0) < 0) + goto options_rejected; + } + add_exclude_file(&exclude_list, arg, XFLG_FATAL_ERRORS + | (opt == OPT_INCLUDE_FROM + ? XFLG_DEF_INCLUDE : 0)); break; case 'h': @@ -627,15 +690,14 @@ int parse_arguments(int *argc, const char ***argv, int frommain) struct poptOption *op = &long_options[opt-OPT_REFUSED_BASE]; int n = snprintf(err_buf, sizeof err_buf, - "This server does not support --%s\n", + "The server is configured to refuse --%s\n", op->longName) - 1; if (op->shortName) { snprintf(err_buf+n, sizeof err_buf-n, " (-%c)\n", op->shortName); } } else { - snprintf(err_buf, sizeof err_buf, - "%s%s: %s\n", + snprintf(err_buf, sizeof err_buf, "%s%s: %s\n", am_server ? "on remote machine: " : "", poptBadOption(pc, POPT_BADOPTION_NOALIAS), poptStrerror(opt)); @@ -720,10 +782,7 @@ int parse_arguments(int *argc, const char ***argv, int frommain) relative_paths = files_from? 1 : 0; *argv = poptGetArgs(pc); - if (*argv) - *argc = count_args(*argv); - else - *argc = 0; + *argc = count_args(*argv); if (sanitize_paths) { int i; @@ -773,12 +832,6 @@ int parse_arguments(int *argc, const char ***argv, int frommain) } } - if (daemon_opt) { - daemon_opt = 0; - am_daemon = 1; - return 1; - } - if (!backup_suffix) backup_suffix = backup_dir ? "" : BACKUP_SUFFIX; backup_suffix_len = strlen(backup_suffix); @@ -831,10 +884,24 @@ int parse_arguments(int *argc, const char ***argv, int frommain) am_server ? "server" : "client"); return 0; #endif - } else if (partial_dir) { - if (strcmp(partial_dir, ".") == 0) - partial_dir = NULL; - keep_partial = 1; + if (compare_dest) { + snprintf(err_buf, sizeof err_buf, + "--inplace does not yet work with %s\n", + link_dest ? "--link-dest" : "--compare-dest"); + return 0; + } + } else { + if (keep_partial && !partial_dir) + partial_dir = getenv("RSYNC_PARTIAL_DIR"); + if (partial_dir) { + if (!*partial_dir || strcmp(partial_dir, ".") == 0) + partial_dir = NULL; + else if (*partial_dir != '/') { + add_exclude(&exclude_list, partial_dir, + XFLG_DIRECTORY); + } + keep_partial = 1; + } } if (files_from) { @@ -1011,8 +1078,7 @@ void server_options(char **args,int *argc) if (am_sender) { if (delete_excluded) args[ac++] = "--delete-excluded"; - else if (delete_mode - && (!delete_after || protocol_version < 27)) + else if (delete_mode) args[ac++] = "--delete"; if (delete_after)