Don't omit the -4/-6 options if no IPv6 support was compiled into
[rsync/rsync.git] / options.c
index 084f5c3..77d52f3 100644 (file)
--- a/options.c
+++ b/options.c
@@ -6,8 +6,9 @@
  * Copyright (C) 2002-2007 Wayne Davison
  *
  * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,8 +16,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+ * with this program; if not, visit the http://fsf.org website.
  */
 
 #include "rsync.h"
@@ -25,6 +25,7 @@
 
 extern int module_id;
 extern int sanitize_paths;
+extern int daemon_over_rsh;
 extern struct filter_list_struct filter_list;
 extern struct filter_list_struct server_filter_list;
 
@@ -85,6 +86,7 @@ int force_delete = 0;
 int io_timeout = 0;
 int allowed_lull = 0;
 int prune_empty_dirs = 0;
+int use_qsort = 0;
 char *files_from = NULL;
 int filesfrom_fd = -1;
 char *filesfrom_host = NULL;
@@ -94,7 +96,6 @@ int recurse = 0;
 int allow_inc_recurse = 1;
 int xfer_dirs = -1;
 int am_daemon = 0;
-int daemon_over_rsh = 0;
 int do_stats = 0;
 int do_progress = 0;
 int keep_partial = 0;
@@ -108,7 +109,7 @@ size_t bwlimit_writemax = 0;
 int ignore_existing = 0;
 int ignore_non_existing = 0;
 int need_messages_from_generator = 0;
-int max_delete = -1;
+int max_delete = INT_MIN;
 OFF_T max_size = 0;
 OFF_T min_size = 0;
 int ignore_errors = 0;
@@ -118,12 +119,18 @@ int checksum_seed = 0;
 int inplace = 0;
 int delay_updates = 0;
 long block_size = 0; /* "long" because popt can't set an int32. */
+char *skip_compress = NULL;
 
 /** Network address family. **/
+int default_af_hint
 #ifdef INET6
-int default_af_hint = 0;       /* Any protocol */
+       = 0;            /* Any protocol */
 #else
-int default_af_hint = AF_INET; /* Must use IPv4 */
+       = AF_INET;      /* Must use IPv4 */
+# ifdef AF_INET6
+#  undef AF_INET6
+# endif
+# define AF_INET6 AF_INET /* make -6 option a no-op */
 #endif
 
 /** Do not go into the background when run as --daemon.  Good
@@ -327,15 +334,15 @@ void usage(enum logcode F)
   rprintf(F," -A, --acls                  preserve ACLs (implies --perms)\n");
 #endif
 #ifdef SUPPORT_XATTRS
-  rprintf(F," -X, --xattrs                preserve extended attributes (implies --perms)\n");
+  rprintf(F," -X, --xattrs                preserve extended attributes\n");
 #endif
   rprintf(F," -o, --owner                 preserve owner (super-user only)\n");
   rprintf(F," -g, --group                 preserve group\n");
   rprintf(F,"     --devices               preserve device files (super-user only)\n");
   rprintf(F,"     --specials              preserve special files\n");
   rprintf(F," -D                          same as --devices --specials\n");
-  rprintf(F," -t, --times                 preserve times\n");
-  rprintf(F," -O, --omit-dir-times        omit directories when preserving times\n");
+  rprintf(F," -t, --times                 preserve modification times\n");
+  rprintf(F," -O, --omit-dir-times        omit directories from --times\n");
   rprintf(F,"     --super                 receiver attempts super-user activities\n");
 #ifdef SUPPORT_XATTRS
   rprintf(F,"     --fake-super            store/recover privileged attrs using xattrs\n");
@@ -378,6 +385,7 @@ void usage(enum logcode F)
   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,"     --compress-level=NUM    explicitly set compression level\n");
+  rprintf(F,"     --skip-compress=LIST    skip compressing files with a suffix in LIST\n");
   rprintf(F," -C, --cvs-exclude           auto-ignore files the same way CVS does\n");
   rprintf(F," -f, --filter=RULE           add a file-filtering RULE\n");
   rprintf(F," -F                          same as --filter='dir-merge /.rsync-filter'\n");
@@ -411,10 +419,8 @@ void usage(enum logcode F)
 #ifdef ICONV_OPTION
   rprintf(F,"     --iconv=CONVERT_SPEC    request charset conversion of filesnames\n");
 #endif
-#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 (-h works with no other options)\n");
 
@@ -443,15 +449,17 @@ static struct poptOption long_options[] = {
   {"no-motd",          0,  POPT_ARG_VAL,    &output_motd, 0, 0, 0 },
   {"stats",            0,  POPT_ARG_NONE,   &do_stats, 0, 0, 0 },
   {"human-readable",  'h', POPT_ARG_NONE,   0, 'h', 0, 0},
+  {"no-human-readable",0,  POPT_ARG_VAL,    &human_readable, 0, 0, 0},
+  {"no-h",             0,  POPT_ARG_VAL,    &human_readable, 0, 0, 0},
   {"dry-run",         'n', POPT_ARG_NONE,   &dry_run, 0, 0, 0 },
   {"archive",         'a', POPT_ARG_NONE,   0, 'a', 0, 0 },
   {"recursive",       'r', POPT_ARG_VAL,    &recurse, 2, 0, 0 },
   {"no-recursive",     0,  POPT_ARG_VAL,    &recurse, 0, 0, 0 },
-  {"ir",               0,  POPT_ARG_VAL,    &allow_inc_recurse, 1, 0, 0 },
+  {"no-r",             0,  POPT_ARG_VAL,    &recurse, 0, 0, 0 },
   {"inc-recursive",    0,  POPT_ARG_VAL,    &allow_inc_recurse, 1, 0, 0 },
-  {"no-ir",            0,  POPT_ARG_VAL,    &allow_inc_recurse, 0, 0, 0 },
   {"no-inc-recursive", 0,  POPT_ARG_VAL,    &allow_inc_recurse, 0, 0, 0 },
-  {"no-r",             0,  POPT_ARG_VAL,    &recurse, 0, 0, 0 },
+  {"ir",               0,  POPT_ARG_VAL,    &allow_inc_recurse, 1, 0, 0 },
+  {"no-ir",            0,  POPT_ARG_VAL,    &allow_inc_recurse, 0, 0, 0 },
   {"dirs",            'd', POPT_ARG_VAL,    &xfer_dirs, 2, 0, 0 },
   {"no-dirs",          0,  POPT_ARG_VAL,    &xfer_dirs, 0, 0, 0 },
   {"no-d",             0,  POPT_ARG_VAL,    &xfer_dirs, 0, 0, 0 },
@@ -536,13 +544,18 @@ static struct poptOption long_options[] = {
   {"whole-file",      'W', POPT_ARG_VAL,    &whole_file, 1, 0, 0 },
   {"no-whole-file",    0,  POPT_ARG_VAL,    &whole_file, 0, 0, 0 },
   {"no-W",             0,  POPT_ARG_VAL,    &whole_file, 0, 0, 0 },
-  {"checksum",        'c', POPT_ARG_NONE,   &always_checksum, 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 },
   {"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 },
   {"link-dest",        0,  POPT_ARG_STRING, 0, OPT_LINK_DEST, 0, 0 },
   {"fuzzy",           'y', POPT_ARG_NONE,   &fuzzy_basis, 0, 0, 0 },
   {"compress",        'z', POPT_ARG_NONE,   0, 'z', 0, 0 },
+  {"no-compress",      0,  POPT_ARG_VAL,    &do_compression, 0, 0, 0 },
+  {"skip-compress",    0,  POPT_ARG_STRING, &skip_compress, 0, 0, 0 },
+  {"no-z",             0,  POPT_ARG_VAL,    &do_compression, 0, 0, 0 },
   {"compress-level",   0,  POPT_ARG_INT,    &def_compress_level, 'z', 0, 0 },
   {0,                 'P', POPT_ARG_NONE,   0, 'P', 0, 0 },
   {"progress",         0,  POPT_ARG_VAL,    &do_progress, 1, 0, 0 },
@@ -550,15 +563,20 @@ static struct poptOption long_options[] = {
   {"partial",          0,  POPT_ARG_VAL,    &keep_partial, 1, 0, 0 },
   {"no-partial",       0,  POPT_ARG_VAL,    &keep_partial, 0, 0, 0 },
   {"partial-dir",      0,  POPT_ARG_STRING, &partial_dir, 0, 0, 0 },
-  {"delay-updates",    0,  POPT_ARG_NONE,   &delay_updates, 0, 0, 0 },
+  {"delay-updates",    0,  POPT_ARG_VAL,    &delay_updates, 1, 0, 0 },
+  {"no-delay-updates", 0,  POPT_ARG_VAL,    &delay_updates, 0, 0, 0 },
   {"prune-empty-dirs",'m', POPT_ARG_NONE,   &prune_empty_dirs, 0, 0, 0 },
   {"log-file",         0,  POPT_ARG_STRING, &logfile_name, 0, 0, 0 },
   {"log-file-format",  0,  POPT_ARG_STRING, &logfile_format, 0, 0, 0 },
   {"out-format",       0,  POPT_ARG_STRING, &stdout_format, 0, 0, 0 },
   {"log-format",       0,  POPT_ARG_STRING, &stdout_format, 0, 0, 0 }, /* DEPRECATED */
   {"itemize-changes", 'i', POPT_ARG_NONE,   0, 'i', 0, 0 },
+  {"no-itemize-changes",0, POPT_ARG_VAL,    &itemize_changes, 0, 0, 0 },
+  {"no-i",             0,  POPT_ARG_VAL,    &itemize_changes, 0, 0, 0 },
   {"bwlimit",          0,  POPT_ARG_INT,    &bwlimit, 0, 0, 0 },
-  {"backup",          'b', POPT_ARG_NONE,   &make_backups, 0, 0, 0 },
+  {"no-bwlimit",       0,  POPT_ARG_VAL,    &bwlimit, 0, 0, 0 },
+  {"backup",          'b', POPT_ARG_VAL,    &make_backups, 1, 0, 0 },
+  {"no-backup",        0,  POPT_ARG_VAL,    &make_backups, 0, 0, 0 },
   {"backup-dir",       0,  POPT_ARG_STRING, &backup_dir, 0, 0, 0 },
   {"suffix",           0,  POPT_ARG_STRING, &backup_suffix, 0, 0, 0 },
   {"list-only",        0,  POPT_ARG_VAL,    &list_only, 2, 0, 0 },
@@ -566,20 +584,22 @@ static struct poptOption long_options[] = {
   {"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},
-  {"numeric-ids",      0,  POPT_ARG_NONE,   &numeric_ids, 0, 0, 0 },
+  {"from0",           '0', POPT_ARG_VAL,    &eol_nulls, 1, 0, 0},
+  {"no-from0",         0,  POPT_ARG_VAL,    &eol_nulls, 0, 0, 0},
+  {"numeric-ids",      0,  POPT_ARG_VAL,    &numeric_ids, 1, 0, 0 },
+  {"no-numeric-ids",   0,  POPT_ARG_VAL,    &numeric_ids, 0, 0, 0 },
   {"timeout",          0,  POPT_ARG_INT,    &io_timeout, 0, 0, 0 },
+  {"no-timeout",       0,  POPT_ARG_VAL,    &io_timeout, 0, 0, 0 },
   {"rsh",             'e', POPT_ARG_STRING, &shell_cmd, 0, 0, 0 },
   {"rsync-path",       0,  POPT_ARG_STRING, &rsync_path, 0, 0, 0 },
   {"temp-dir",        'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
 #ifdef ICONV_OPTION
   {"iconv",            0,  POPT_ARG_STRING, &iconv_opt, 0, 0, 0 },
 #endif
-#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
   {"8-bit-output",    '8', POPT_ARG_NONE,   &allow_8bit_chars, 0, 0, 0 },
+  {"qsort",            0,  POPT_ARG_NONE,   &use_qsort, 0, 0, 0 },
   {"address",          0,  POPT_ARG_STRING, &bind_address, 0, 0, 0 },
   {"port",             0,  POPT_ARG_INT,    &rsync_port, 0, 0, 0 },
   {"sockopts",         0,  POPT_ARG_STRING, &sockopts, 0, 0, 0 },
@@ -613,10 +633,8 @@ static void daemon_usage(enum logcode F)
   rprintf(F,"     --log-file-format=FMT   override the \"log format\" setting\n");
   rprintf(F,"     --sockopts=OPTIONS      specify custom TCP options\n");
   rprintf(F," -v, --verbose               increase verbosity\n");
-#ifdef INET6
   rprintf(F," -4, --ipv4                  prefer IPv4\n");
   rprintf(F," -6, --ipv6                  prefer IPv6\n");
-#endif
   rprintf(F,"     --help                  show this help screen\n");
 
   rprintf(F,"\n");
@@ -630,14 +648,12 @@ static struct poptOption long_daemon_options[] = {
   {"bwlimit",          0,  POPT_ARG_INT,    &daemon_bwlimit, 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
   {"detach",           0,  POPT_ARG_VAL,    &no_detach, 0, 0, 0 },
+  {"no-detach",        0,  POPT_ARG_VAL,    &no_detach, 1, 0, 0 },
   {"log-file",         0,  POPT_ARG_STRING, &logfile_name, 0, 0, 0 },
   {"log-file-format",  0,  POPT_ARG_STRING, &logfile_format, 0, 0, 0 },
-  {"no-detach",        0,  POPT_ARG_VAL,    &no_detach, 1, 0, 0 },
   {"port",             0,  POPT_ARG_INT,    &rsync_port, 0, 0, 0 },
   {"sockopts",         0,  POPT_ARG_STRING, &sockopts, 0, 0, 0 },
   {"protocol",         0,  POPT_ARG_INT,    &protocol_version, 0, 0, 0 },
@@ -1170,8 +1186,7 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
 
                case 'X':
 #ifdef SUPPORT_XATTRS
-                       preserve_xattrs = 1;
-                       preserve_perms = 1;
+                       preserve_xattrs++;
                        break;
 #else
                        snprintf(err_buf,sizeof(err_buf),
@@ -1272,6 +1287,11 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
                return 0;
        }
 
+       if (max_delete < 0 && max_delete != INT_MIN) {
+               /* Negative numbers are treated as "no deletions". */
+               max_delete = 0;
+       }
+
        if (compare_dest + copy_dest + link_dest > 1) {
                snprintf(err_buf, sizeof err_buf,
                        "You may not mix --compare-dest, --copy-dest, and --link-dest.\n");
@@ -1593,7 +1613,7 @@ void server_options(char **args,int *argc)
        /* This should always remain first on the server's command-line. */
        args[ac++] = "--server";
 
-       if (daemon_over_rsh) {
+       if (daemon_over_rsh > 0) {
                args[ac++] = "--daemon";
                *argc = ac;
                /* if we're passing --daemon, we're done */
@@ -1661,8 +1681,11 @@ void server_options(char **args,int *argc)
                argstr[x++] = 'A';
 #endif
 #ifdef SUPPORT_XATTRS
-       if (preserve_xattrs)
+       if (preserve_xattrs) {
                argstr[x++] = 'X';
+               if (preserve_xattrs > 1)
+                       argstr[x++] = 'X';
+       }
 #endif
        if (recurse)
                argstr[x++] = 'r';
@@ -1758,22 +1781,6 @@ void server_options(char **args,int *argc)
                args[ac++] = arg;
        }
 
-       if (max_delete >= 0 && am_sender) {
-               if (asprintf(&arg, "--max-delete=%d", max_delete) < 0)
-                       goto oom;
-               args[ac++] = arg;
-       }
-
-       if (min_size && am_sender) {
-               args[ac++] = "--min-size";
-               args[ac++] = min_size_arg;
-       }
-
-       if (max_size && am_sender) {
-               args[ac++] = "--max-size";
-               args[ac++] = max_size_arg;
-       }
-
        if (io_timeout) {
                if (asprintf(&arg, "--timeout=%d", io_timeout) < 0)
                        goto oom;
@@ -1800,6 +1807,20 @@ void server_options(char **args,int *argc)
        }
 
        if (am_sender) {
+               if (max_delete > 0) {
+                       if (asprintf(&arg, "--max-delete=%d", max_delete) < 0)
+                               goto oom;
+                       args[ac++] = arg;
+               } else if (max_delete == 0)
+                       args[ac++] = "--max_delete=-1";
+               if (min_size) {
+                       args[ac++] = "--min-size";
+                       args[ac++] = min_size_arg;
+               }
+               if (max_size) {
+                       args[ac++] = "--max-size";
+                       args[ac++] = max_size_arg;
+               }
                if (delete_before)
                        args[ac++] = "--delete-before";
                else if (delete_during == 2)
@@ -1820,6 +1841,12 @@ void server_options(char **args,int *argc)
                        args[ac++] = "--super";
                if (size_only)
                        args[ac++] = "--size-only";
+       } else {
+               if (skip_compress) {
+                       if (asprintf(&arg, "--skip-compress=%s", skip_compress) < 0)
+                               goto oom;
+                       args[ac++] = arg;
+               }
        }
 
        if (modify_window_set) {
@@ -1856,35 +1883,40 @@ void server_options(char **args,int *argc)
        if (numeric_ids)
                args[ac++] = "--numeric-ids";
 
-       if (ignore_existing && am_sender)
-               args[ac++] = "--ignore-existing";
+       if (!allow_inc_recurse)
+               args[ac++] = "--no-ir";
 
-       /* Backward compatibility: send --existing, not --ignore-non-existing. */
-       if (ignore_non_existing && am_sender)
-               args[ac++] = "--existing";
+       if (am_sender) {
+               if (ignore_existing)
+                       args[ac++] = "--ignore-existing";
 
-       if (append_mode)
-               args[ac++] = "--append";
-       else if (inplace)
-               args[ac++] = "--inplace";
+               /* Backward compatibility: send --existing, not --ignore-non-existing. */
+               if (ignore_non_existing)
+                       args[ac++] = "--existing";
 
-       if (tmpdir && am_sender) {
-               args[ac++] = "--temp-dir";
-               args[ac++] = tmpdir;
-       }
+               if (tmpdir) {
+                       args[ac++] = "--temp-dir";
+                       args[ac++] = tmpdir;
+               }
 
-       if (basis_dir[0] && am_sender) {
-               /* the server only needs this option if it is not the sender,
-                *   and it may be an older version that doesn't know this
-                *   option, so don't send it if client is the sender.
-                */
-               int i;
-               for (i = 0; i < basis_dir_cnt; i++) {
-                       args[ac++] = dest_option;
-                       args[ac++] = basis_dir[i];
+               if (basis_dir[0]) {
+                       /* the server only needs this option if it is not the sender,
+                        *   and it may be an older version that doesn't know this
+                        *   option, so don't send it if client is the sender.
+                        */
+                       int i;
+                       for (i = 0; i < basis_dir_cnt; i++) {
+                               args[ac++] = dest_option;
+                               args[ac++] = basis_dir[i];
+                       }
                }
        }
 
+       if (append_mode)
+               args[ac++] = "--append";
+       else if (inplace)
+               args[ac++] = "--inplace";
+
        if (files_from && (!am_sender || filesfrom_host)) {
                if (filesfrom_host) {
                        args[ac++] = "--files-from";
@@ -1945,7 +1977,7 @@ char *check_for_hostspec(char *s, char **host_ptr, int *port_ptr)
                        if (p[1] == ':')
                                *port_ptr = atoi(p+2);
                } else {
-                       if ((p = strchr(s, ':')) != NULL) {
+                       if ((p = strchr(s, ':')) != NULL && p < s + hostlen) {
                                hostlen = p - s;
                                *port_ptr = atoi(p+1);
                        }