X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/cbbd8e2e8bf72aa46c84c7de43e19da40f040fa7..7a2eca415b0d7f40618dd67aa30bafef810b3724:/options.c diff --git a/options.c b/options.c index 4ac8846d..a79c5537 100644 --- a/options.c +++ b/options.c @@ -25,11 +25,12 @@ #include "zlib/zlib.h" extern int module_id; +extern int local_server; extern int sanitize_paths; extern int daemon_over_rsh; extern unsigned int module_dirlen; extern struct filter_list_struct filter_list; -extern struct filter_list_struct server_filter_list; +extern struct filter_list_struct daemon_filter_list; int make_backups = 0; @@ -173,6 +174,10 @@ int link_dest = 0; int basis_dir_cnt = 0; char *dest_option = NULL; +static int remote_option_alloc = 0; +int remote_option_cnt = 0; +const char **remote_options = NULL; + int verbose = 0; int quiet = 0; int output_motd = 1; @@ -386,6 +391,7 @@ void usage(enum logcode F) rprintf(F," --timeout=SECONDS set I/O timeout in seconds\n"); rprintf(F," --contimeout=SECONDS set daemon connection timeout in seconds\n"); 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," -T, --temp-dir=DIR create temporary files in directory DIR\n"); @@ -474,6 +480,8 @@ static struct poptOption long_options[] = { {"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 }, + {"old-dirs", 0, POPT_ARG_VAL, &xfer_dirs, 4, 0, 0 }, + {"old-d", 0, POPT_ARG_VAL, &xfer_dirs, 4, 0, 0 }, {"perms", 'p', POPT_ARG_VAL, &preserve_perms, 1, 0, 0 }, {"no-perms", 0, POPT_ARG_VAL, &preserve_perms, 0, 0, 0 }, {"no-p", 0, POPT_ARG_VAL, &preserve_perms, 0, 0, 0 }, @@ -577,6 +585,7 @@ static struct poptOption long_options[] = { {"link-dest", 0, POPT_ARG_STRING, 0, OPT_LINK_DEST, 0, 0 }, {"fuzzy", 'y', POPT_ARG_VAL, &fuzzy_basis, 1, 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 }, {"no-compress", 0, POPT_ARG_VAL, &do_compression, 0, 0, 0 }, {"no-z", 0, POPT_ARG_VAL, &do_compression, 0, 0, 0 }, @@ -641,6 +650,7 @@ static struct poptOption long_options[] = { {"password-file", 0, POPT_ARG_STRING, &password_file, 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 }, + {"remote-option", 'M', POPT_ARG_STRING, 0, 'M', 0, 0 }, {"protocol", 0, POPT_ARG_INT, &protocol_version, 0, 0, 0 }, {"checksum-seed", 0, POPT_ARG_INT, &checksum_seed, 0, 0, 0 }, {"server", 0, POPT_ARG_NONE, 0, OPT_SERVER, 0, 0 }, @@ -888,7 +898,7 @@ static void create_refuse_error(int which) * * @retval 0 on error, with err_buf containing an explanation **/ -int parse_arguments(int *argc_p, const char ***argv_p, int frommain) +int parse_arguments(int *argc_p, const char ***argv_p) { static poptContext pc; char *ref = lp_refuse_options(module_id); @@ -900,8 +910,10 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain) set_refuse_options(ref); if (am_daemon) { set_refuse_options("log-file*"); +#ifdef ICONV_OPTION if (!*lp_charset(module_id)) set_refuse_options("iconv"); +#endif } #ifdef ICONV_OPTION @@ -1028,8 +1040,8 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain) case OPT_INCLUDE_FROM: arg = poptGetOptArg(pc); if (sanitize_paths) - arg = sanitize_path(NULL, arg, NULL, 0); - if (server_filter_list.head) { + arg = sanitize_path(NULL, arg, NULL, 0, SP_DEFAULT); + if (daemon_filter_list.head) { int rej; char *dir, *cp = strdup(arg); if (!cp) @@ -1038,7 +1050,7 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain) goto options_rejected; dir = cp + (*cp == '/' ? module_dirlen : 0); clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS); - rej = check_filter(&server_filter_list, dir, 0) < 0; + rej = check_filter(&daemon_filter_list, FLOG, dir, 0) < 0; free(cp); if (rej) goto options_rejected; @@ -1091,8 +1103,7 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain) break; case 'q': - if (frommain) - quiet++; + quiet++; break; case 'x': @@ -1135,6 +1146,26 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain) } break; + case 'M': + arg = poptGetOptArg(pc); + if (*arg != '-') { + snprintf(err_buf, sizeof err_buf, + "Remote option must start with a dash: %s\n", arg); + return 0; + } + if (remote_option_cnt+2 >= remote_option_alloc) { + remote_option_alloc += 16; + remote_options = realloc_array(remote_options, + const char *, remote_option_alloc); + if (!remote_options) + out_of_memory("parse_arguments"); + if (!remote_option_cnt) + remote_options[0] = "ARG0"; + } + remote_options[++remote_option_cnt] = arg; + remote_options[remote_option_cnt+1] = NULL; + break; + case OPT_WRITE_BATCH: /* batch_name is already set */ write_batch = 1; @@ -1270,7 +1301,7 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain) } } - if (human_readable && argc == 2) { + if (human_readable && argc == 2 && !am_server) { /* Allow the old meaning of 'h' (--help) on its own. */ usage(FINFO); exit_cleanup(0); @@ -1289,12 +1320,11 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain) } #endif - if (protect_args == 1) { - if (!frommain) - protect_args = 0; - else if (am_server) - return 1; - } + if (protect_args == 1 && am_server) + return 1; + + *argv_p = argv = poptGetArgs(pc); + *argc_p = argc = count_args(argv); #ifndef SUPPORT_LINKS if (preserve_links && !am_sender) { @@ -1383,8 +1413,16 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain) xfer_dirs = 1; } - if (xfer_dirs < 1) - xfer_dirs = recurse || list_only; + if (argc < 2 && !read_batch && !am_server) + list_only |= 1; + + if (xfer_dirs >= 4) { + parse_rule(&filter_list, "- /*/*", 0, 0); + recurse = xfer_dirs = 1; + } else if (recurse) + xfer_dirs = 1; + else if (xfer_dirs < 0) + xfer_dirs = list_only ? 1 : 0; if (relative_paths < 0) relative_paths = files_from? 1 : 0; @@ -1433,27 +1471,24 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain) need_messages_from_generator = 1; } - *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); + argv[i] = sanitize_path(NULL, argv[i], "", 0, SP_KEEP_DOT_DIRS); if (tmpdir) - tmpdir = sanitize_path(NULL, tmpdir, NULL, 0); + tmpdir = sanitize_path(NULL, tmpdir, NULL, 0, SP_DEFAULT); if (backup_dir) - backup_dir = sanitize_path(NULL, backup_dir, NULL, 0); + backup_dir = sanitize_path(NULL, backup_dir, NULL, 0, SP_DEFAULT); } - if (server_filter_list.head && !am_sender) { - struct filter_list_struct *elp = &server_filter_list; + if (daemon_filter_list.head && !am_sender) { + struct filter_list_struct *elp = &daemon_filter_list; if (tmpdir) { char *dir; if (!*tmpdir) goto options_rejected; dir = tmpdir + (*tmpdir == '/' ? module_dirlen : 0); clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS); - if (check_filter(elp, dir, 1) < 0) + if (check_filter(elp, FLOG, dir, 1) < 0) goto options_rejected; } if (backup_dir) { @@ -1462,7 +1497,7 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain) goto options_rejected; dir = backup_dir + (*backup_dir == '/' ? module_dirlen : 0); clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS); - if (check_filter(elp, dir, 1) < 0) + if (check_filter(elp, FLOG, dir, 1) < 0) goto options_rejected; } } @@ -1523,8 +1558,12 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain) log_before_transfer = !am_server; } - if (do_progress && !verbose && !log_before_transfer && !am_server) - verbose = 1; + if (do_progress) { + if (am_server) + do_progress = 0; + else if (!verbose && !log_before_transfer && !am_server) + verbose = 1; + } if (dry_run) do_xfers = 0; @@ -1651,14 +1690,14 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain) } } else { if (sanitize_paths) - files_from = sanitize_path(NULL, files_from, NULL, 0); - if (server_filter_list.head) { + files_from = sanitize_path(NULL, files_from, NULL, 0, SP_DEFAULT); + if (daemon_filter_list.head) { char *dir; if (!*files_from) goto options_rejected; dir = files_from + (*files_from == '/' ? module_dirlen : 0); clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS); - if (check_filter(&server_filter_list, dir, 0) < 0) + if (check_filter(&daemon_filter_list, FLOG, dir, 0) < 0) goto options_rejected; } filesfrom_fd = open(files_from, O_RDONLY|O_BINARY); @@ -1728,8 +1767,8 @@ void server_options(char **args, int *argc_p) argstr[x++] = 'n'; if (preserve_links) argstr[x++] = 'l'; - if ((list_only && !recurse) || xfer_dirs > 1 - || (xfer_dirs && !recurse && delete_mode && am_sender)) + if ((xfer_dirs >= 2 && xfer_dirs < 4) + || (xfer_dirs && !recurse && (list_only || (delete_mode && am_sender)))) argstr[x++] = 'd'; if (am_sender) { if (keep_dirlinks) @@ -1817,6 +1856,11 @@ void server_options(char **args, int *argc_p) #endif argstr[x] = '\0'; + if (x > (int)sizeof argstr) { /* Not possible... */ + rprintf(FERROR, "argstr overflow in server_options().\n"); + exit_cleanup(RERR_MALLOC); + } + args[ac++] = argstr; #ifdef ICONV_OPTION @@ -1832,7 +1876,7 @@ void server_options(char **args, int *argc_p) } #endif - if (protect_args) /* initial args break here */ + if (protect_args && !local_server) /* unprotected args stop here */ args[ac++] = NULL; if (list_only > 1) @@ -2039,6 +2083,21 @@ void server_options(char **args, int *argc_p) else if (remove_source_files) args[ac++] = "--remove-sent-files"; + if (ac > MAX_SERVER_ARGS) { /* Not possible... */ + rprintf(FERROR, "argc overflow in server_options().\n"); + exit_cleanup(RERR_MALLOC); + } + + if (remote_option_cnt) { + int j; + if (ac + remote_option_cnt > MAX_SERVER_ARGS) { + rprintf(FERROR, "too many remote options specified.\n"); + exit_cleanup(RERR_SYNTAX); + } + for (j = 1; j <= remote_option_cnt; j++) + args[ac++] = (char*)remote_options[j]; + } + *argc_p = ac; return;