Added more local-network IPs to the "hosts allow" rsyncd config
[rsync/rsync.git] / options.c
index 77d52f3..b6eab10 100644 (file)
--- a/options.c
+++ b/options.c
@@ -56,7 +56,6 @@ int preserve_specials = 0;
 int preserve_uid = 0;
 int preserve_gid = 0;
 int preserve_times = 0;
-int omit_dir_times = 0;
 int update_only = 0;
 int cvs_exclude = 0;
 int dry_run = 0;
@@ -91,6 +90,7 @@ char *files_from = NULL;
 int filesfrom_fd = -1;
 char *filesfrom_host = NULL;
 int eol_nulls = 0;
+int protect_args = 0;
 int human_readable = 0;
 int recurse = 0;
 int allow_inc_recurse = 1;
@@ -192,6 +192,7 @@ char *iconv_opt = ICONV_OPTION;
 struct chmod_mode_struct *chmod_modes = NULL;
 
 static int daemon_opt;   /* sets am_daemon after option error-reporting */
+static int omit_dir_times = 0;
 static int F_option_cnt = 0;
 static int modify_window_set;
 static int itemize_changes = 0;
@@ -319,6 +320,7 @@ void usage(enum logcode F)
   rprintf(F," -u, --update                skip files that are newer on the receiver\n");
   rprintf(F,"     --inplace               update destination files in-place (SEE MAN PAGE)\n");
   rprintf(F,"     --append                append data onto shorter files\n");
+  rprintf(F,"     --append-verify         like --append, but with old data in file checksum\n");
   rprintf(F," -d, --dirs                  transfer directories without recursing\n");
   rprintf(F," -l, --links                 copy symlinks as symlinks\n");
   rprintf(F," -L, --copy-links            transform symlink into referent file/dir\n");
@@ -396,6 +398,7 @@ void usage(enum logcode F)
   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/filter files are delimited by 0s\n");
+  rprintf(F," -s, --protect-args          no space-splitting; only wildcard special-chars\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,"     --sockopts=OPTIONS      specify custom TCP options\n");
@@ -434,7 +437,7 @@ enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
       OPT_FILTER, OPT_COMPARE_DEST, OPT_COPY_DEST, OPT_LINK_DEST, OPT_HELP,
       OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW, OPT_MIN_SIZE, OPT_CHMOD,
       OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_ONLY_WRITE_BATCH, OPT_MAX_SIZE,
-      OPT_NO_D,
+      OPT_NO_D, OPT_APPEND,
       OPT_SERVER, OPT_REFUSED_BASE = 9000};
 
 static struct poptOption long_options[] = {
@@ -473,10 +476,12 @@ static struct poptOption long_options[] = {
   {"xattrs",          'X', POPT_ARG_NONE,   0, 'X', 0, 0 },
   {"no-xattrs",        0,  POPT_ARG_VAL,    &preserve_xattrs, 0, 0, 0 },
   {"no-X",             0,  POPT_ARG_VAL,    &preserve_xattrs, 0, 0, 0 },
-  {"times",           't', POPT_ARG_VAL,    &preserve_times, 1, 0, 0 },
+  {"times",           't', POPT_ARG_VAL,    &preserve_times, 2, 0, 0 },
   {"no-times",         0,  POPT_ARG_VAL,    &preserve_times, 0, 0, 0 },
   {"no-t",             0,  POPT_ARG_VAL,    &preserve_times, 0, 0, 0 },
-  {"omit-dir-times",  'O', POPT_ARG_VAL,    &omit_dir_times, 2, 0, 0 },
+  {"omit-dir-times",  'O', POPT_ARG_VAL,    &omit_dir_times, 1, 0, 0 },
+  {"no-omit-dir-times",0,  POPT_ARG_VAL,    &omit_dir_times, 0, 0, 0 },
+  {"no-O",             0,  POPT_ARG_VAL,    &omit_dir_times, 0, 0, 0 },
   {"modify-window",    0,  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 },
@@ -521,7 +526,9 @@ static struct poptOption long_options[] = {
   {"min-size",         0,  POPT_ARG_STRING, &min_size_arg, OPT_MIN_SIZE, 0, 0 },
   {"sparse",          'S', POPT_ARG_NONE,   &sparse_files, 0, 0, 0 },
   {"inplace",          0,  POPT_ARG_NONE,   &inplace, 0, 0, 0 },
-  {"append",           0,  POPT_ARG_VAL,    &append_mode, 1, 0, 0 },
+  {"append",           0,  POPT_ARG_NONE,   0, OPT_APPEND, 0, 0 },
+  {"append-verify",    0,  POPT_ARG_VAL,    &append_mode, 2, 0, 0 },
+  {"no-append",        0,  POPT_ARG_VAL,    &append_mode, 0, 0, 0 },
   {"del",              0,  POPT_ARG_NONE,   &delete_during, 0, 0, 0 },
   {"delete",           0,  POPT_ARG_NONE,   &delete_mode, 0, 0, 0 },
   {"delete-before",    0,  POPT_ARG_NONE,   &delete_before, 0, 0, 0 },
@@ -586,6 +593,9 @@ static struct poptOption long_options[] = {
   {"files-from",       0,  POPT_ARG_STRING, &files_from, 0, 0, 0 },
   {"from0",           '0', POPT_ARG_VAL,    &eol_nulls, 1, 0, 0},
   {"no-from0",         0,  POPT_ARG_VAL,    &eol_nulls, 0, 0, 0},
+  {"protect-args",    's', POPT_ARG_VAL,    &protect_args, 1, 0, 0},
+  {"no-protect-args",  0,  POPT_ARG_VAL,    &protect_args, 0, 0, 0},
+  {"no-s",             0,  POPT_ARG_VAL,    &protect_args, 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 },
@@ -851,12 +861,13 @@ static void create_refuse_error(int which)
  *
  * @retval 0 on error, with err_buf containing an explanation
  **/
-int parse_arguments(int *argc, const char ***argv, int frommain)
+int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
 {
-       int opt;
+       static poptContext pc;
        char *ref = lp_refuse_options(module_id);
-       const char *arg;
-       poptContext pc;
+       const char *arg, **argv = *argv_p;
+       int argc = *argc_p;
+       int opt;
 
        if (ref && *ref)
                set_refuse_options(ref);
@@ -872,8 +883,11 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
 
        /* The context leaks in case of an error, but if there's a
         * problem we always exit anyhow. */
-       pc = poptGetContext(RSYNC_NAME, *argc, *argv, long_options, 0);
-       poptReadDefaultConfig(pc, 0);
+       if (pc)
+               poptFreeContext(pc);
+       pc = poptGetContext(RSYNC_NAME, argc, argv, long_options, 0);
+       if (!am_server)
+               poptReadDefaultConfig(pc, 0);
 
        while ((opt = poptGetNextOpt(pc)) != -1) {
                /* most options are handled automatically by popt;
@@ -889,7 +903,7 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
                                /* Disable popt aliases on the server side and
                                 * then start parsing the options again. */
                                poptFreeContext(pc);
-                               pc = poptGetContext(RSYNC_NAME, *argc, *argv,
+                               pc = poptGetContext(RSYNC_NAME, argc, argv,
                                                    long_options, 0);
                                am_server = 1;
                        }
@@ -917,7 +931,7 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
                        iconv_opt = NULL;
 #endif
                        poptFreeContext(pc);
-                       pc = poptGetContext(RSYNC_NAME, *argc, *argv,
+                       pc = poptGetContext(RSYNC_NAME, argc, argv,
                                            long_daemon_options, 0);
                        while ((opt = poptGetNextOpt(pc)) != -1) {
                                switch (opt) {
@@ -952,8 +966,8 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
                                exit_cleanup(RERR_SYNTAX);
                        }
 
-                       *argv = poptGetArgs(pc);
-                       *argc = count_args(*argv);
+                       *argv_p = argv = poptGetArgs(pc);
+                       *argc_p = argc = count_args(argv);
                        am_starting_up = 0;
                        daemon_opt = 0;
                        am_daemon = 1;
@@ -1012,7 +1026,7 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
                        preserve_links = 1;
 #endif
                        preserve_perms = 1;
-                       preserve_times = 1;
+                       preserve_times = 2;
                        preserve_gid = 1;
                        preserve_uid = 1;
                        preserve_devices = 1;
@@ -1121,6 +1135,13 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
                        }
                        break;
 
+               case OPT_APPEND:
+                       if (am_server)
+                               append_mode++;
+                       else
+                               append_mode = 1;
+                       break;
+
                case OPT_LINK_DEST:
 #ifdef SUPPORT_HARD_LINKS
                        link_dest = 1;
@@ -1210,12 +1231,19 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
                }
        }
 
-       if (human_readable && *argc == 2) {
+       if (human_readable && argc == 2) {
                /* Allow the old meaning of 'h' (--help) on its own. */
                usage(FINFO);
                exit_cleanup(0);
        }
 
+       if (protect_args) {
+               if (!frommain)
+                       protect_args = 0;
+               else if (am_server)
+                       return 1;
+       }
+
 #ifdef ICONV_OPTION
        if (iconv_opt) {
                if (!am_server && strcmp(iconv_opt, "-") == 0)
@@ -1355,13 +1383,13 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
                need_messages_from_generator = 1;
        }
 
-       *argv = poptGetArgs(pc);
-       *argc = count_args(*argv);
+       *argv_p = argv = poptGetArgs(pc);
+       *argc_p = argc = count_args(argv);
 
        if (sanitize_paths) {
                int i;
-               for (i = *argc; i-- > 0; )
-                       (*argv)[i] = sanitize_path(NULL, (*argv)[i], "", 0, NULL);
+               for (i = argc; i-- > 0; )
+                       argv[i] = sanitize_path(NULL, argv[i], "", 0, NULL);
                if (tmpdir)
                        tmpdir = sanitize_path(NULL, tmpdir, NULL, 0, NULL);
                if (backup_dir)
@@ -1417,8 +1445,15 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
                        "P *%s", backup_suffix);
                parse_rule(&filter_list, backup_dir_buf, 0, 0);
        }
-       if (make_backups && !backup_dir)
-               omit_dir_times = 1;
+
+       if (make_backups && !backup_dir) {
+               omit_dir_times = 0; /* Implied, so avoid -O to sender. */
+               if (preserve_times > 1)
+                       preserve_times = 1;
+       } else if (omit_dir_times) {
+               if (preserve_times > 1)
+                       preserve_times = 1;
+       }
 
        if (stdout_format) {
                if (am_server && log_format_has(stdout_format, 'I'))
@@ -1539,7 +1574,7 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
        if (files_from) {
                char *h, *p;
                int q;
-               if (*argc > 2 || (!am_daemon && *argc == 1)) {
+               if (argc > 2 || (!am_daemon && argc == 1)) {
                        usage(FERROR);
                        exit_cleanup(RERR_SYNTAX);
                }
@@ -1599,10 +1634,10 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
  * behave, and also filtering out options that are processed only
  * locally.
  **/
-void server_options(char **args,int *argc)
+void server_options(char **args, int *argc_p)
 {
        static char argstr[64];
-       int ac = *argc;
+       int ac = *argc_p;
        char *arg;
 
        int i, x;
@@ -1615,7 +1650,7 @@ void server_options(char **args,int *argc)
 
        if (daemon_over_rsh > 0) {
                args[ac++] = "--daemon";
-               *argc = ac;
+               *argc_p = ac;
                /* if we're passing --daemon, we're done */
                return;
        }
@@ -1644,7 +1679,7 @@ void server_options(char **args,int *argc)
                        argstr[x++] = 'K';
                if (prune_empty_dirs)
                        argstr[x++] = 'm';
-               if (omit_dir_times == 2)
+               if (omit_dir_times)
                        argstr[x++] = 'O';
        } else {
                if (copy_links)
@@ -1912,9 +1947,11 @@ void server_options(char **args,int *argc)
                }
        }
 
-       if (append_mode)
+       if (append_mode) {
+               if (append_mode > 1)
+                       args[ac++] = "--append";
                args[ac++] = "--append";
-       else if (inplace)
+       else if (inplace)
                args[ac++] = "--inplace";
 
        if (files_from && (!am_sender || filesfrom_host)) {
@@ -1941,7 +1978,7 @@ void server_options(char **args,int *argc)
        else if (remove_source_files)
                args[ac++] = "--remove-sent-files";
 
-       *argc = ac;
+       *argc_p = ac;
        return;
 
     oom: