X-Git-Url: http://git.samba.org/samba.git/?p=rsync.git;a=blobdiff_plain;f=options.c;h=e5b0cb68280ed5e1d5cfea93e314c1c67c74ebe9;hp=c556617d124db9d5898a9ec3daa79bc7158350da;hb=3e2e4b5a33c72ef428ff40989a1ba03b4d24c9fb;hpb=0dfd2a64ec7c2ae1cfd9c97ec37b9d17c4c42977 diff --git a/options.c b/options.c index c556617d..e5b0cb68 100644 --- a/options.c +++ b/options.c @@ -3,7 +3,7 @@ * * Copyright (C) 1998-2001 Andrew Tridgell * Copyright (C) 2000, 2001, 2002 Martin Pool - * Copyright (C) 2002-2011 Wayne Davison + * Copyright (C) 2002-2019 Wayne Davison * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -32,6 +32,8 @@ extern unsigned int module_dirlen; extern filter_rule_list filter_list; extern filter_rule_list daemon_filter_list; +#define NOT_SPECIFIED (-42) + int make_backups = 0; /** @@ -75,7 +77,7 @@ int protocol_version = PROTOCOL_VERSION; int sparse_files = 0; int preallocate_files = 0; int do_compression = 0; -int def_compress_level = Z_DEFAULT_COMPRESSION; +int def_compress_level = NOT_SPECIFIED; int am_root = 0; /* 0 = normal, 1 = root, 2 = --super, -1 = --fake-super */ int am_server = 0; int am_sender = 0; @@ -123,7 +125,6 @@ int checksum_seed = 0; int inplace = 0; int delay_updates = 0; long block_size = 0; /* "long" because popt can't set an int32. */ -char number_separator; char *skip_compress = NULL; item_list dparam_list = EMPTY_ITEM_LIST; @@ -181,6 +182,7 @@ char *dest_option = NULL; static int remote_option_alloc = 0; int remote_option_cnt = 0; const char **remote_options = NULL; +const char *checksum_choice = NULL; int quiet = 0; int output_motd = 1; @@ -303,7 +305,9 @@ static int refused_partial, refused_progress, refused_delete_before; static int refused_delete_during; static int refused_inplace, refused_no_iconv; static BOOL usermap_via_chown, groupmap_via_chown; +#ifdef HAVE_SETVBUF static char *outbuf_mode; +#endif static char *bwlimit_arg, *max_size_arg, *min_size_arg; static char tmp_partialdir[] = ".~tmp~"; @@ -408,16 +412,17 @@ static void parse_output_words(struct output_struct *words, short *levels, const char *s; int j, len, lev; - if (!str) - return; - - while (*str) { + for ( ; str; str = s) { if ((s = strchr(str, ',')) != NULL) len = s++ - str; else len = strlen(str); - while (len && isDigit(str+len-1)) - len--; + if (!len) + continue; + if (!isDigit(str)) { + while (len && isDigit(str+len-1)) + len--; + } lev = isDigit(str+len) ? atoi(str+len) : 1; if (lev > MAX_OUT_LEVEL) lev = MAX_OUT_LEVEL; @@ -445,9 +450,6 @@ static void parse_output_words(struct output_struct *words, short *levels, words[j].help, len, str); exit_cleanup(RERR_SYNTAX); } - if (!s) - break; - str = s; } } @@ -610,7 +612,7 @@ static void print_rsync_version(enum logcode f) rprintf(f, "%s version %s protocol version %d%s\n", RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol); - rprintf(f, "Copyright (C) 1996-2011 by Andrew Tridgell, Wayne Davison, and others.\n"); + rprintf(f, "Copyright (C) 1996-2019 by Andrew Tridgell, Wayne Davison, and others.\n"); rprintf(f, "Web site: http://rsync.samba.org/\n"); rprintf(f, "Capabilities:\n"); rprintf(f, " %d-bit files, %d-bit inums, %d-bit timestamps, %d-bit long ints,\n", @@ -712,7 +714,7 @@ void usage(enum logcode F) #ifdef SUPPORT_XATTRS rprintf(F," --fake-super store/recover privileged attrs using xattrs\n"); #endif - rprintf(F," -S, --sparse handle sparse files efficiently\n"); + rprintf(F," -S, --sparse turn sequences of nulls into sparse blocks\n"); #ifdef SUPPORT_PREALLOCATION rprintf(F," --preallocate allocate dest files before writing them\n"); #else @@ -720,6 +722,7 @@ void usage(enum logcode F) #endif rprintf(F," -n, --dry-run perform a trial run with no changes made\n"); rprintf(F," -W, --whole-file copy files whole (without delta-xfer algorithm)\n"); + rprintf(F," --checksum-choice=STR choose the checksum algorithms\n"); 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"); @@ -754,7 +757,7 @@ void usage(enum logcode F) rprintf(F," -I, --ignore-times don't skip files that match in size and mod-time\n"); rprintf(F," -M, --remote-option=OPTION send OPTION to the remote side only\n"); rprintf(F," --size-only skip files that match in size\n"); - rprintf(F," --modify-window=NUM compare mod-times with reduced accuracy\n"); + rprintf(F," -@, --modify-window=NUM set the accuracy for mod-time comparisons\n"); 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"); @@ -800,6 +803,7 @@ void usage(enum logcode F) #ifdef ICONV_OPTION rprintf(F," --iconv=CONVERT_SPEC request charset conversion of filenames\n"); #endif + rprintf(F," --checksum-seed=NUM set block/file checksum seed (advanced)\n"); rprintf(F," -4, --ipv4 prefer IPv4\n"); rprintf(F," -6, --ipv6 prefer IPv6\n"); rprintf(F," --version print version number\n"); @@ -869,7 +873,7 @@ static struct poptOption long_options[] = { {"omit-link-times", 'J', POPT_ARG_VAL, &omit_link_times, 1, 0, 0 }, {"no-omit-link-times",0, POPT_ARG_VAL, &omit_link_times, 0, 0, 0 }, {"no-J", 0, POPT_ARG_VAL, &omit_link_times, 0, 0, 0 }, - {"modify-window", 0, POPT_ARG_INT, &modify_window, OPT_MODIFY_WINDOW, 0, 0 }, + {"modify-window", '@', POPT_ARG_INT, &modify_window, OPT_MODIFY_WINDOW, 0, 0 }, {"super", 0, POPT_ARG_VAL, &am_root, 2, 0, 0 }, {"no-super", 0, POPT_ARG_VAL, &am_root, 0, 0, 0 }, {"fake-super", 0, POPT_ARG_VAL, &am_root, -1, 0, 0 }, @@ -951,6 +955,7 @@ static struct poptOption long_options[] = { {"cvs-exclude", 'C', POPT_ARG_NONE, &cvs_exclude, 0, 0, 0 }, {"whole-file", 'W', POPT_ARG_VAL, &whole_file, 1, 0, 0 }, {"no-whole-file", 0, POPT_ARG_VAL, &whole_file, 0, 0, 0 }, + {"checksum-choice", 0, POPT_ARG_STRING, &checksum_choice, 0, 0, 0 }, {"no-W", 0, POPT_ARG_VAL, &whole_file, 0, 0, 0 }, {"checksum", 'c', POPT_ARG_VAL, &always_checksum, 1, 0, 0 }, {"no-checksum", 0, POPT_ARG_VAL, &always_checksum, 0, 0, 0 }, @@ -963,10 +968,12 @@ static struct poptOption long_options[] = { {"no-fuzzy", 0, POPT_ARG_VAL, &fuzzy_basis, 0, 0, 0 }, {"no-y", 0, POPT_ARG_VAL, &fuzzy_basis, 0, 0, 0 }, {"compress", 'z', POPT_ARG_NONE, 0, 'z', 0, 0 }, + {"old-compress", 0, POPT_ARG_VAL, &do_compression, 1, 0, 0 }, + {"new-compress", 0, POPT_ARG_VAL, &do_compression, 2, 0, 0 }, {"no-compress", 0, POPT_ARG_VAL, &do_compression, 0, 0, 0 }, {"no-z", 0, POPT_ARG_VAL, &do_compression, 0, 0, 0 }, {"skip-compress", 0, POPT_ARG_STRING, &skip_compress, 0, 0, 0 }, - {"compress-level", 0, POPT_ARG_INT, &def_compress_level, 'z', 0, 0 }, + {"compress-level", 0, POPT_ARG_INT, &def_compress_level, 0, 0, 0 }, {0, 'P', POPT_ARG_NONE, 0, 'P', 0, 0 }, {"progress", 0, POPT_ARG_VAL, &do_progress, 1, 0, 0 }, {"no-progress", 0, POPT_ARG_VAL, &do_progress, 0, 0, 0 }, @@ -1274,6 +1281,22 @@ static void create_refuse_error(int which) } } +/* This is used to make sure that --daemon & --server cannot be aliased to + * something else. These options have always disabled popt aliases for the + * parsing of a daemon or server command-line, but we have to make sure that + * these options cannot vanish so that the alias disabling can take effect. */ +static void popt_unalias(poptContext con, const char *opt) +{ + struct poptAlias unalias; + + unalias.longName = opt + 2; /* point past the leading "--" */ + unalias.shortName = '\0'; + unalias.argc = 1; + unalias.argv = new_array(const char*, 1); + unalias.argv[0] = strdup(opt); + + poptAddAlias(con, unalias, 0); +} /** * Process command line arguments. Called on both local and remote. @@ -1290,7 +1313,12 @@ int parse_arguments(int *argc_p, const char ***argv_p) const char *arg, **argv = *argv_p; int argc = *argc_p; int opt; + int orig_protect_args = protect_args; + if (argc == 0) { + strlcpy(err_buf, "argc is zero!\n", sizeof err_buf); + return 0; + } if (ref && *ref) set_refuse_options(ref); if (am_daemon) { @@ -1313,8 +1341,11 @@ int parse_arguments(int *argc_p, const char ***argv_p) if (pc) poptFreeContext(pc); pc = poptGetContext(RSYNC_NAME, argc, argv, long_options, 0); - if (!am_server) + if (!am_server) { poptReadDefaultConfig(pc, 0); + popt_unalias(pc, "--daemon"); + popt_unalias(pc, "--server"); + } while ((opt = poptGetNextOpt(pc)) != -1) { /* most options are handled automatically by popt; @@ -1541,18 +1572,7 @@ int parse_arguments(int *argc_p, const char ***argv_p) break; case 'z': - if (def_compress_level < Z_DEFAULT_COMPRESSION - || def_compress_level > Z_BEST_COMPRESSION) { - snprintf(err_buf, sizeof err_buf, - "--compress-level value is invalid: %d\n", - def_compress_level); - return 0; - } - do_compression = def_compress_level != Z_NO_COMPRESSION; - if (do_compression && refused_compress) { - create_refuse_error(refused_compress); - return 0; - } + do_compression++; break; case 'M': @@ -1821,12 +1841,48 @@ int parse_arguments(int *argc_p, const char ***argv_p) } } + if (checksum_choice && strcmp(checksum_choice, "auto") != 0 && strcmp(checksum_choice, "auto,auto") != 0) { + /* Call this early to verify the args and figure out if we need to force + * --whole-file. Note that the parse function will get called again later, + * just in case an "auto" choice needs to know the protocol_version. */ + if (parse_checksum_choice()) + whole_file = 1; + } else + checksum_choice = NULL; + if (human_readable > 1 && argc == 2 && !am_server) { /* Allow the old meaning of 'h' (--help) on its own. */ usage(FINFO); exit_cleanup(0); } + if (do_compression || def_compress_level != NOT_SPECIFIED) { + if (def_compress_level == NOT_SPECIFIED) + def_compress_level = Z_DEFAULT_COMPRESSION; + else if (def_compress_level < Z_DEFAULT_COMPRESSION || def_compress_level > Z_BEST_COMPRESSION) { + snprintf(err_buf, sizeof err_buf, "--compress-level value is invalid: %d\n", + def_compress_level); + return 0; + } else if (def_compress_level == Z_NO_COMPRESSION) + do_compression = 0; + else if (!do_compression) + do_compression = 1; + if (do_compression && refused_compress) { + create_refuse_error(refused_compress); + return 0; + } +#ifdef EXTERNAL_ZLIB + if (do_compression == 1) { + snprintf(err_buf, sizeof err_buf, + "This rsync lacks old-style --compress due to its external zlib. Try -zz.\n"); + if (am_server) + return 0; + fprintf(stderr, "%s" "Continuing without compression.\n\n", err_buf); + do_compression = 0; + } +#endif + } + #ifdef HAVE_SETVBUF if (outbuf_mode && !am_server) { int mode = *(uchar *)outbuf_mode; @@ -1867,15 +1923,6 @@ int parse_arguments(int *argc_p, const char ***argv_p) verbose > 1 ? "stats3" : "stats2", DEFAULT_PRIORITY); } - if (human_readable) { - char buf[32]; - snprintf(buf, sizeof buf, "%f", 3.14); - if (strchr(buf, '.') != NULL) - number_separator = ','; - else - number_separator = '.'; - } - #ifdef ICONV_OPTION if (iconv_opt && protect_args != 2) { if (!am_server && strcmp(iconv_opt, "-") == 0) @@ -1892,6 +1939,10 @@ int parse_arguments(int *argc_p, const char ***argv_p) if (fuzzy_basis > 1) fuzzy_basis = basis_dir_cnt + 1; + /* Don't let the client reset protect_args if it was already processed */ + if (orig_protect_args == 2 && am_server) + protect_args = orig_protect_args; + if (protect_args == 1 && am_server) return 1; @@ -2214,14 +2265,6 @@ int parse_arguments(int *argc_p, const char ***argv_p) bwlimit_writemax = 512; } - if (sparse_files && inplace) { - /* Note: we don't check for this below, because --append is - * OK with --sparse (as long as redos are handled right). */ - snprintf(err_buf, sizeof err_buf, - "--sparse cannot be used with --inplace\n"); - return 0; - } - if (append_mode) { if (whole_file > 0) { snprintf(err_buf, sizeof err_buf, @@ -2458,16 +2501,20 @@ void server_options(char **args, int *argc_p) } if (sparse_files) argstr[x++] = 'S'; - if (do_compression) + if (do_compression == 1) argstr[x++] = 'z'; set_allow_inc_recurse(); - /* Checking the pre-negotiated value allows --protocol=29 override. */ + /* We don't really know the actual protocol_version at this point, + * but checking the pre-negotiated value allows the user to use a + * --protocol=29 override to avoid the use of this -eFLAGS opt. */ if (protocol_version >= 30) { + /* Use "eFlags" alias so that cull_options doesn't think that these are no-arg option letters. */ +#define eFlags argstr /* We make use of the -e option to let the server know about * any pre-release protocol version && some behavior flags. */ - argstr[x++] = 'e'; + eFlags[x++] = 'e'; #if SUBPROTOCOL_VERSION != 0 if (protocol_version == PROTOCOL_VERSION) { x += snprintf(argstr+x, sizeof argstr - x, @@ -2475,15 +2522,19 @@ void server_options(char **args, int *argc_p) PROTOCOL_VERSION, SUBPROTOCOL_VERSION); } else #endif - argstr[x++] = '.'; + eFlags[x++] = '.'; if (allow_inc_recurse) - argstr[x++] = 'i'; + eFlags[x++] = 'i'; #ifdef CAN_SET_SYMLINK_TIMES - argstr[x++] = 'L'; + eFlags[x++] = 'L'; /* symlink time-setting support */ #endif #ifdef ICONV_OPTION - argstr[x++] = 's'; + eFlags[x++] = 's'; /* symlink iconv translation support */ #endif + eFlags[x++] = 'f'; /* flist I/O-error safety support */ + eFlags[x++] = 'x'; /* xattr hardlink optimization not desired */ + eFlags[x++] = 'C'; /* support checksum seed order fix */ +#undef eFlags } if (x >= (int)sizeof argstr) { /* Not possible... */ @@ -2578,6 +2629,12 @@ void server_options(char **args, int *argc_p) args[ac++] = arg; } + if (checksum_choice) { + if (asprintf(&arg, "--checksum-choice=%s", checksum_choice) < 0) + goto oom; + args[ac++] = arg; + } + if (am_sender) { if (max_delete > 0) { if (asprintf(&arg, "--max-delete=%d", max_delete) < 0) @@ -2630,8 +2687,9 @@ void server_options(char **args, int *argc_p) else if (missing_args == 1 && !am_sender) args[ac++] = "--ignore-missing-args"; - if (modify_window_set) { - if (asprintf(&arg, "--modify-window=%d", modify_window) < 0) + if (modify_window_set && am_sender) { + char *fmt = modify_window < 0 ? "-@%d" : "--modify-window=%d"; + if (asprintf(&arg, fmt, modify_window) < 0) goto oom; args[ac++] = arg; } @@ -2751,6 +2809,9 @@ void server_options(char **args, int *argc_p) exit_cleanup(RERR_MALLOC); } + if (do_compression > 1) + args[ac++] = "--new-compress"; + if (remote_option_cnt) { int j; if (ac + remote_option_cnt > MAX_SERVER_ARGS) {