X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/819bfe459919769c9ddae14affeaa79596c640bb..a76ba8b4257cc75e99c71da7f44c5e75393a3d43:/options.c diff --git a/options.c b/options.c index b63956f2..71fda24f 100644 --- a/options.c +++ b/options.c @@ -475,6 +475,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 }, @@ -1032,7 +1034,7 @@ int parse_arguments(int *argc_p, const char ***argv_p) case OPT_INCLUDE_FROM: arg = poptGetOptArg(pc); if (sanitize_paths) - arg = sanitize_path(NULL, arg, NULL, 0); + arg = sanitize_path(NULL, arg, NULL, 0, SP_DEFAULT); if (daemon_filter_list.head) { int rej; char *dir, *cp = strdup(arg); @@ -1042,7 +1044,7 @@ int parse_arguments(int *argc_p, const char ***argv_p) goto options_rejected; dir = cp + (*cp == '/' ? module_dirlen : 0); clean_fname(dir, CFN_COLLAPSE_DOT_DOT_DIRS); - rej = check_filter(&daemon_filter_list, dir, 0) < 0; + rej = check_filter(&daemon_filter_list, FLOG, dir, 0) < 0; free(cp); if (rej) goto options_rejected; @@ -1273,7 +1275,7 @@ int parse_arguments(int *argc_p, const char ***argv_p) } } - 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); @@ -1295,6 +1297,9 @@ int parse_arguments(int *argc_p, const char ***argv_p) 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) { snprintf(err_buf, sizeof err_buf, @@ -1382,8 +1387,16 @@ int parse_arguments(int *argc_p, const char ***argv_p) 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; @@ -1432,17 +1445,14 @@ int parse_arguments(int *argc_p, const char ***argv_p) 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 (daemon_filter_list.head && !am_sender) { struct filter_list_struct *elp = &daemon_filter_list; @@ -1452,7 +1462,7 @@ int parse_arguments(int *argc_p, const char ***argv_p) 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) { @@ -1461,7 +1471,7 @@ int parse_arguments(int *argc_p, const char ***argv_p) 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; } } @@ -1650,14 +1660,14 @@ int parse_arguments(int *argc_p, const char ***argv_p) } } else { if (sanitize_paths) - files_from = sanitize_path(NULL, files_from, NULL, 0); + 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(&daemon_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); @@ -1727,8 +1737,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) @@ -1798,25 +1808,40 @@ void server_options(char **args, int *argc_p) if (do_compression) argstr[x++] = 'z'; - /* We make use of the -e option to let the server know about any - * pre-release protocol version && some behavior flags. */ - argstr[x++] = 'e'; + set_allow_inc_recurse(); + + /* Checking the pre-negotiated value allows --protocol=29 override. */ + if (protocol_version >= 30) { + /* We make use of the -e option to let the server know about + * any pre-release protocol version && some behavior flags. */ + argstr[x++] = 'e'; #if SUBPROTOCOL_VERSION != 0 - if (protocol_version == PROTOCOL_VERSION) { - x += snprintf(argstr+x, sizeof argstr - x, - "%d.%d", PROTOCOL_VERSION, SUBPROTOCOL_VERSION); - } else + if (protocol_version == PROTOCOL_VERSION) { + x += snprintf(argstr+x, sizeof argstr - x, + "%d.%d", + PROTOCOL_VERSION, SUBPROTOCOL_VERSION); + } else #endif - argstr[x++] = '.'; - set_allow_inc_recurse(); - if (allow_inc_recurse) - argstr[x++] = 'i'; + argstr[x++] = '.'; + if (allow_inc_recurse) + argstr[x++] = 'i'; #if defined HAVE_LUTIMES && defined HAVE_UTIMES - argstr[x++] = 'L'; + argstr[x++] = 'L'; #endif +#ifdef ICONV_OPTION + argstr[x++] = 's'; +#endif + } + + if (x >= (int)sizeof argstr) { /* Not possible... */ + rprintf(FERROR, "argstr overflow in server_options().\n"); + exit_cleanup(RERR_MALLOC); + } + argstr[x] = '\0'; - args[ac++] = argstr; + if (x > 1) + args[ac++] = argstr; #ifdef ICONV_OPTION if (iconv_opt) { @@ -1998,7 +2023,6 @@ void server_options(char **args, int *argc_p) * 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]; @@ -2038,6 +2062,11 @@ 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); + } + *argc_p = ac; return;