Accept only position-sensitive (file-selection) options in file list files.

Using such options as -f, -z, etc. is senseless in the file list file
and bypasses the option consistency checks in decode_options.  Therefore,
only options related to file selection (a.k.a position-sensitive options)
are allowed in files.

* doc/tar.texi: Document changes.
* src/common.h (tar_args): Move from tar.c
(TAR_ARGS_INITIALIZER): New macro.
* src/names.c: Declare option group identifiers as an enum.
(names_parse_opt): Special handling for ARGP_KEY_ERROR.
(names_argp): Remove static qualifier.
(names_argp_children): Remove.
* src/tar.c: Declare option group identifiers as an enum.
(parse_opt): Special handling for ARGP_KEY_INIT.
(argp_children): New static variable.
(args): Remove static variable.
(more_options): Allow only options from names_argp.
(parse_default_options): Take a pointer to struct tar_args as argument.
Replace the loc member during the call to argp_parse and restore it
afterwards.
(decode_options): Use automatic variable for args.
This commit is contained in:
Sergey Poznyakoff
2020-06-24 16:43:26 +03:00
parent 34d15af170
commit 1ff0b63f48
4 changed files with 443 additions and 369 deletions

View File

@@ -7730,9 +7730,12 @@ any leading and trailing whitespace. If the resulting string begins
with @samp{-} character, it is considered a @command{tar} option and is
processed accordingly@footnote{Versions of @GNUTAR{} up to 1.15.1
recognized only @option{-C} option in file lists, and only if the
option and its argument occupied two consecutive lines.}. For example,
the common use of this feature is to change to another directory by
specifying @option{-C} option:
option and its argument occupied two consecutive lines.}. Only a
subset of @GNUTAR{} options is allowed for use in file lists. For
a list of such options, @ref{Position-Sensitive Options}.
For example, the common use of this feature is to change to another
directory by specifying @option{-C} option:
@smallexample
@group

View File

@@ -834,6 +834,24 @@ struct option_locus
class */
};
struct tar_args /* Variables used during option parsing */
{
struct option_locus *loc;
struct textual_date *textual_date; /* Keeps the arguments to --newer-mtime
and/or --date option if they are
textual dates */
bool o_option; /* True if -o option was given */
bool pax_option; /* True if --pax-option was given */
bool compress_autodetect; /* True if compression autodetection should
be attempted when creating archives */
char const *backup_suffix_string; /* --suffix option argument */
char const *version_control_string; /* --backup option argument */
};
#define TAR_ARGS_INITIALIZER(loc) \
{ loc, NULL, false, false, false, NULL, NULL }
void more_options (int argc, char **argv, struct option_locus *loc);
/* Module update.c. */

View File

@@ -62,89 +62,93 @@ enum
WILDCARDS_OPTION
};
enum
{
GRH_LOCAL,
GRID_LOCAL,
GRH_MATCH,
GRID_MATCH,
};
static struct argp_option names_options[] = {
#define GRID 100
{NULL, 0, NULL, 0,
N_("Local file name selection:"), GRID },
N_("Local file name selection:"), GRH_LOCAL },
{"add-file", ADD_FILE_OPTION, N_("FILE"), 0,
N_("add given FILE to the archive (useful if its name starts with a dash)"), GRID+1 },
N_("add given FILE to the archive (useful if its name starts with a dash)"), GRID_LOCAL },
{"directory", 'C', N_("DIR"), 0,
N_("change to directory DIR"), GRID+1 },
N_("change to directory DIR"), GRID_LOCAL },
{"files-from", 'T', N_("FILE"), 0,
N_("get names to extract or create from FILE"), GRID+1 },
N_("get names to extract or create from FILE"), GRID_LOCAL },
{"null", NULL_OPTION, 0, 0,
N_("-T reads null-terminated names; implies --verbatim-files-from"),
GRID+1 },
GRID_LOCAL },
{"no-null", NO_NULL_OPTION, 0, 0,
N_("disable the effect of the previous --null option"), GRID+1 },
N_("disable the effect of the previous --null option"), GRID_LOCAL },
{"unquote", UNQUOTE_OPTION, 0, 0,
N_("unquote input file or member names (default)"), GRID+1 },
N_("unquote input file or member names (default)"), GRID_LOCAL },
{"no-unquote", NO_UNQUOTE_OPTION, 0, 0,
N_("do not unquote input file or member names"), GRID+1 },
N_("do not unquote input file or member names"), GRID_LOCAL },
{"verbatim-files-from", VERBATIM_FILES_FROM_OPTION, 0, 0,
N_("-T reads file names verbatim (no escape or option handling)"), GRID+1 },
N_("-T reads file names verbatim (no escape or option handling)"), GRID_LOCAL },
{"no-verbatim-files-from", NO_VERBATIM_FILES_FROM_OPTION, 0, 0,
N_("-T treats file names starting with dash as options (default)"),
GRID+1 },
GRID_LOCAL },
{"exclude", EXCLUDE_OPTION, N_("PATTERN"), 0,
N_("exclude files, given as a PATTERN"), GRID+1 },
N_("exclude files, given as a PATTERN"), GRID_LOCAL },
{"exclude-from", 'X', N_("FILE"), 0,
N_("exclude patterns listed in FILE"), GRID+1 },
N_("exclude patterns listed in FILE"), GRID_LOCAL },
{"exclude-caches", EXCLUDE_CACHES_OPTION, 0, 0,
N_("exclude contents of directories containing CACHEDIR.TAG, "
"except for the tag file itself"), GRID+1 },
"except for the tag file itself"), GRID_LOCAL },
{"exclude-caches-under", EXCLUDE_CACHES_UNDER_OPTION, 0, 0,
N_("exclude everything under directories containing CACHEDIR.TAG"),
GRID+1 },
GRID_LOCAL },
{"exclude-caches-all", EXCLUDE_CACHES_ALL_OPTION, 0, 0,
N_("exclude directories containing CACHEDIR.TAG"), GRID+1 },
N_("exclude directories containing CACHEDIR.TAG"), GRID_LOCAL },
{"exclude-tag", EXCLUDE_TAG_OPTION, N_("FILE"), 0,
N_("exclude contents of directories containing FILE, except"
" for FILE itself"), GRID+1 },
" for FILE itself"), GRID_LOCAL },
{"exclude-ignore", EXCLUDE_IGNORE_OPTION, N_("FILE"), 0,
N_("read exclude patterns for each directory from FILE, if it exists"),
GRID+1 },
GRID_LOCAL },
{"exclude-ignore-recursive", EXCLUDE_IGNORE_RECURSIVE_OPTION, N_("FILE"), 0,
N_("read exclude patterns for each directory and its subdirectories "
"from FILE, if it exists"), GRID+1 },
"from FILE, if it exists"), GRID_LOCAL },
{"exclude-tag-under", EXCLUDE_TAG_UNDER_OPTION, N_("FILE"), 0,
N_("exclude everything under directories containing FILE"), GRID+1 },
N_("exclude everything under directories containing FILE"), GRID_LOCAL },
{"exclude-tag-all", EXCLUDE_TAG_ALL_OPTION, N_("FILE"), 0,
N_("exclude directories containing FILE"), GRID+1 },
N_("exclude directories containing FILE"), GRID_LOCAL },
{"exclude-vcs", EXCLUDE_VCS_OPTION, NULL, 0,
N_("exclude version control system directories"), GRID+1 },
N_("exclude version control system directories"), GRID_LOCAL },
{"exclude-vcs-ignores", EXCLUDE_VCS_IGNORES_OPTION, NULL, 0,
N_("read exclude patterns from the VCS ignore files"), GRID+1 },
N_("read exclude patterns from the VCS ignore files"), GRID_LOCAL },
{"exclude-backups", EXCLUDE_BACKUPS_OPTION, NULL, 0,
N_("exclude backup and lock files"), GRID+1 },
N_("exclude backup and lock files"), GRID_LOCAL },
{"recursion", RECURSION_OPTION, 0, 0,
N_("recurse into directories (default)"), GRID+1 },
N_("recurse into directories (default)"), GRID_LOCAL },
{"no-recursion", NO_RECURSION_OPTION, 0, 0,
N_("avoid descending automatically in directories"), GRID+1 },
#undef GRID
N_("avoid descending automatically in directories"), GRID_LOCAL },
#define GRID 120
{NULL, 0, NULL, 0,
N_("File name matching options (affect both exclude and include patterns):"),
GRID },
GRH_MATCH },
{"anchored", ANCHORED_OPTION, 0, 0,
N_("patterns match file name start"), GRID+1 },
N_("patterns match file name start"), GRID_MATCH },
{"no-anchored", NO_ANCHORED_OPTION, 0, 0,
N_("patterns match after any '/' (default for exclusion)"), GRID+1 },
N_("patterns match after any '/' (default for exclusion)"), GRID_MATCH },
{"ignore-case", IGNORE_CASE_OPTION, 0, 0,
N_("ignore case"), GRID+1 },
N_("ignore case"), GRID_MATCH },
{"no-ignore-case", NO_IGNORE_CASE_OPTION, 0, 0,
N_("case sensitive matching (default)"), GRID+1 },
N_("case sensitive matching (default)"), GRID_MATCH },
{"wildcards", WILDCARDS_OPTION, 0, 0,
N_("use wildcards (default for exclusion)"), GRID+1 },
N_("use wildcards (default for exclusion)"), GRID_MATCH },
{"no-wildcards", NO_WILDCARDS_OPTION, 0, 0,
N_("verbatim string matching"), GRID+1 },
N_("verbatim string matching"), GRID_MATCH },
{"wildcards-match-slash", WILDCARDS_MATCH_SLASH_OPTION, 0, 0,
N_("wildcards match '/' (default for exclusion)"), GRID+1 },
N_("wildcards match '/' (default for exclusion)"), GRID_MATCH },
{"no-wildcards-match-slash", NO_WILDCARDS_MATCH_SLASH_OPTION, 0, 0,
N_("wildcards do not match '/'"), GRID+1 },
#undef GRID
N_("wildcards do not match '/'"), GRID_MATCH },
{NULL}
};
@@ -195,12 +199,25 @@ names_parse_opt (int key, char *arg, struct argp_state *state)
case ADD_FILE_OPTION:
name_add_name (arg);
break;
case ARGP_KEY_ERROR:
{
struct tar_args *args = state->input;
if (args->loc->source == OPTS_FILE)
{
error (0, 0, _("%s:%lu: unrecognized option"), args->loc->name,
(unsigned long) args->loc->line);
set_exit_status (TAREXIT_FAILURE);
}
return ARGP_ERR_UNKNOWN;
}
default:
if (is_file_selection_option (key))
name_add_option (key, arg);
else
return ARGP_ERR_UNKNOWN;
}
return 0;
}
@@ -419,7 +436,7 @@ handle_file_selection_option (int key, const char *arg)
}
}
static struct argp names_argp = {
struct argp names_argp = {
names_options,
names_parse_opt,
NULL,
@@ -429,10 +446,6 @@ static struct argp names_argp = {
NULL
};
struct argp_child names_argp_children[] = {
{ &names_argp, 0, "", 0 },
{ NULL }
};
/* User and group names. */

686
src/tar.c

File diff suppressed because it is too large Load Diff