#define CPRES_NONE 0
#define CPRES_ZLIB 1
+#define CPRES_ZLIBX 2
struct name_num_obj valid_compressions = {
"compress", NULL, NULL, 0, 0, {
+#ifndef EXTERNAL_ZLIB
{ CPRES_ZLIB, "zlib", NULL },
+#endif
+ { CPRES_ZLIBX, "zlibx", NULL },
+#ifdef EXTERNAL_ZLIB
+ { CPRES_ZLIB, "zlib", NULL },
+#endif
{ CPRES_NONE, "none", NULL },
{ 0, NULL, NULL }
}
allow_inc_recurse = 0;
}
+void parse_compress_choice(int final_call)
+{
+ int num;
+
+ if (valid_compressions.negotiated_name)
+ num = valid_compressions.negotiated_num;
+ else if (compress_choice) {
+ struct name_num_item *nni = get_nni_by_name(&valid_compressions, compress_choice, -1);
+ if (!nni) {
+ rprintf(FERROR, "unknown compress name: %s\n", compress_choice);
+ exit_cleanup(RERR_UNSUPPORTED);
+ }
+ num = nni->num;
+ } else
+ num = CPRES_NONE;
+
+ if (num == CPRES_NONE) {
+ do_compression = 0;
+ compress_choice = NULL;
+ } else if (num > 0)
+ do_compression = num != CPRES_ZLIB ? 2 : 1;
+
+ if (final_call && DEBUG_GTE(NSTR, am_server ? 2 : 1)) {
+ const char *c_s = am_server ? "Server" : "Client";
+ if (valid_compressions.negotiated_name)
+ rprintf(FINFO, "%s negotiated compress: %s\n", c_s, valid_compressions.negotiated_name);
+ else
+ rprintf(FINFO, "%s compress: %s\n", c_s, do_compression ? compress_choice : "none");
+ }
+}
+
struct name_num_item *get_nni_by_name(struct name_num_obj *nno, const char *name, int len)
{
struct name_num_item *nni;
OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_ONLY_WRITE_BATCH, OPT_MAX_SIZE,
OPT_NO_D, OPT_APPEND, OPT_NO_ICONV, OPT_INFO, OPT_DEBUG,
OPT_USERMAP, OPT_GROUPMAP, OPT_CHOWN, OPT_BWLIMIT,
+ OPT_OLD_COMPRESS, OPT_NEW_COMPRESS, OPT_NO_COMPRESS,
OPT_SERVER, OPT_REFUSED_BASE = 9000};
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 },
{"no-c", 0, POPT_ARG_VAL, &always_checksum, 0, 0, 0 },
+ {"checksum-choice", 0, POPT_ARG_STRING, &checksum_choice, 0, 0, 0 },
+ {"cc", 0, POPT_ARG_STRING, &checksum_choice, 0, 0, 0 },
{"block-size", 'B', POPT_ARG_LONG, &block_size, 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 },
{"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 },
+ {"old-compress", 0, POPT_ARG_NONE, 0, OPT_OLD_COMPRESS, 0, 0 },
+ {"new-compress", 0, POPT_ARG_NONE, 0, OPT_NEW_COMPRESS, 0, 0 },
+ {"no-compress", 0, POPT_ARG_NONE, 0, OPT_NO_COMPRESS, 0, 0 },
+ {"no-z", 0, POPT_ARG_NONE, 0, OPT_NO_COMPRESS, 0, 0 },
+ {"compress-choice", 0, POPT_ARG_STRING, &compress_choice, 0, 0, 0 },
+ {"zz", 0, POPT_ARG_STRING, &compress_choice, 0, 0, 0 },
{"skip-compress", 0, POPT_ARG_STRING, &skip_compress, 0, 0, 0 },
{"compress-level", 0, POPT_ARG_INT, &def_compress_level, 0, 0, 0 },
{0, 'P', POPT_ARG_NONE, 0, 'P', 0, 0 },
do_compression++;
break;
+ case OPT_OLD_COMPRESS:
+ compress_choice = "zlib";
+ break;
+
+ case OPT_NEW_COMPRESS:
+ compress_choice = "zlibx";
+ break;
+
+ case OPT_NO_COMPRESS:
+ do_compression = 0;
+ compress_choice = NULL;
+ break;
+
case 'M':
arg = poptGetOptArg(pc);
if (*arg != '-') {
exit_cleanup(0);
}
+ if (!compress_choice && do_compression > 1)
+ compress_choice = "zlibx";
+ if (compress_choice && strcasecmp(compress_choice, "auto") != 0)
+ parse_compress_choice(0); /* Can twiddle do_compression and possibly NULL-out compress_choice */
+ else
+ compress_choice = NULL;
+
if (do_compression || def_compress_level != NOT_SPECIFIED) {
if (def_compress_level == NOT_SPECIFIED)
def_compress_level = Z_DEFAULT_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)
+ } else if (def_compress_level == Z_NO_COMPRESSION) {
do_compression = 0;
- else if (!do_compression)
+ compress_choice = NULL;
+ } 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
args[ac++] = arg;
}
+ if ((!compress_choice && do_compression > 1) || (compress_choice && strcasecmp(compress_choice, "zlibx") == 0))
+ args[ac++] = "--new-compress";
+ else if (compress_choice && strcasecmp(compress_choice, "zlib") == 0)
+ args[ac++] = "--old-compress";
+ else if (compress_choice) {
+ if (asprintf(&arg, "--compress-choice=%s", compress_choice) < 0)
+ goto oom;
+ args[ac++] = arg;
+ }
+
if (am_sender) {
if (max_delete > 0) {
if (asprintf(&arg, "--max-delete=%d", max_delete) < 0)
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) {
the source and destination are specified as local paths, but only if no
batch-writing option is in effect.
-dit(bf(--checksum-choice=STR)) This option overrides the checksum algorithms.
+dit(bf(--checksum-choice=STR, --cc=STR)) This option overrides the checksum algorithms.
If one algorithm name is specified, it is used for both the transfer checksums
and (assuming bf(--checksum) is specified) the pre-transfer checksums. If two
comma-separated names are supplied, the first name affects the transfer
separately from the pre-transfer checksum, and it ignores "auto" and all
unknown checksum names. If the remote rsync is not new enough to handle a
checksum negotiation list, the list is silently ignored unless it contains the
-string "FAIL" in it.
+string "FAIL".
The use of the bf(--checksum-choice) option overrides this environment list.
as it is sent to the destination machine, which reduces the amount of data
being transmitted -- something that is useful over a slow connection.
-Note that this option typically achieves better compression ratios than can
-be achieved by using a compressing remote shell or a compressing transport
+The "zlib" compression method typically achieves better compression ratios than
+can be achieved by using a compressing remote shell or a compressing transport
because it takes advantage of the implicit information in the matching data
blocks that are not explicitly sent over the connection. This matching-data
-compression comes at a cost of CPU, though, and can be disabled by repeating
-the bf(-z) option, but only if both sides are at least version 3.1.1.
+compression comes at a cost of CPU, though, and can be disabled by using the
+"zlibx" compresson method instead. This can be selected by repeating the
+bf(-z) option or specifying bf(--compress-choice=zlibx), but it only works if
+both sides of the transfer are at least version 3.1.1.
Note that if your version of rsync was compiled with an external zlib (instead
-of the zlib that comes packaged with rsync) then it will not support the
-old-style compression, only the new-style (repeated-option) compression. In
-the future this new-style compression will likely become the default.
-
-The client rsync requests new-style compression on the server via the
-bf(--new-compress) option, so if you see that option rejected it means that
-the server is not new enough to support bf(-zz). Rsync also accepts the
-bf(--old-compress) option for a future time when new-style compression
-becomes the default.
+of the zlib that comes packaged with rsync) then it will give preference to
+using the "zlibx" algorithm over the "zlib" algorithm since the external zlib
+code doesn't seem to handle the extra compression properly. You can try
+forcing the regular algorithm via bf(--zz=zlib) and be on the lookout for
+transfer failures. If all else fails, disable compression altogether.
+
+Note that if you see an error about an option named bf(--old-compress) or
+bf(--new-compress), this is rsync trying to send the bf(--compress-choice=zlib)
+or bf(--compress-choice=zlibx) option in a backward-compatible manner that more
+rsync versions understand. This error indicates that the older rsync version
+will not allow you to force the compression type.
See the bf(--skip-compress) option for the default list of file suffixes
that will not be compressed.
+dit(bf(--compress-choice=STR, --zz=STR)) This option can be used to override the
+automatic selection of the compression algorithm that is the default when
+bf(--compress) is used.
+
+Currently the STR can be "zlib", "zlibx", or "none".
+
+The "zlib" algorithm is given preference over "zlibx" if your rsync was
+compiled with the internal zlib code, otherwise that preference is reversed.
+These 2 algorithms are the stame except that "zlibx" does not try to include
+matched data that was not transferred in the compression computations.
+
+If "none" is specified, that is equivalent to using bf(--no-compress).
+
+This option implies bf(--compress) unless "none" was specified.
+
+You can also override the compression negotation using the RSYNC_COMPRESS_LIST
+environment variable by setting it to a space-separated list of compression
+names that you consider acceptable. If no common compress choice is found, the
+client exits with an error. It ignores "auto" and all unknown compression
+names. If the remote rsync is not new enough to handle a compression
+negotiation list, the list is silently ignored unless it contains the string
+"FAIL".
+
dit(bf(--compress-level=NUM)) Explicitly set the compression level to use
(see bf(--compress)) instead of letting it default. If NUM is non-zero,
the bf(--compress) option is implied.