diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2016-05-27 10:39:49 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2016-05-27 11:50:19 +0300 |
commit | 9a33077a7b7ad7d32815a21dee54eba63b38a81c (patch) | |
tree | 3b9336b1b23725ab9814eaf2ec8a6629843c8b02 | |
parent | 20b55f0679d314568ec21ae6db1ea635494e292b (diff) | |
download | tar-9a33077a7b7ad7d32815a21dee54eba63b38a81c.tar.gz |
Report positional options that were used but had no effect during archive creation
* src/names.c (file_selection_option)
(file_selection_option_name): New functions.
(unconsumed_option_push, unconsumed_option_free)
(unconsumed_option_report): New functions.
(name_list_advance): Maintain a list
of eventually unconsumed options during archive creation.
Report unconsumed options, if any.
* tests/positional01.at: New test case.
* tests/positional02.at: New test case.
* tests/positional03.at: New test case.
* tests/Makefile.am: Add new test cases.
* tests/testsuite.at: Likewise.
* NEWS: Document the changes.
* configure.ac: Version 1.29.90
* doc/tar.texi: Document the changes.
-rw-r--r-- | NEWS | 24 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | doc/tar.texi | 17 | ||||
-rw-r--r-- | src/names.c | 114 | ||||
-rw-r--r-- | tests/Makefile.am | 3 | ||||
-rw-r--r-- | tests/positional01.at | 54 | ||||
-rw-r--r-- | tests/positional02.at | 49 | ||||
-rw-r--r-- | tests/positional03.at | 47 | ||||
-rw-r--r-- | tests/testsuite.at | 5 |
9 files changed, 308 insertions, 7 deletions
@@ -1,7 +1,29 @@ -GNU tar NEWS - User visible changes. 2016-05-16 +GNU tar NEWS - User visible changes. 2016-05-27 Please send GNU tar bug reports to <bug-tar@gnu.org> +version 1.29.90 (Git) + +* Report erroneous use of positional options. + +During archive creation or update, tar keeps track of positional +options (see the manual, subsection 3.4.4 "Position-Sensitive +Options"), and reports those that had no effect. For example, when +invoked as + + tar -cf a.tar . --exclude '*.o' + +tar will create the archive, but will exit with status 2, having +issued the following error message + + tar: The following options were used after any non-optional + arguments in archive create or update mode. These options are + positional and affect only arguments that follow them. Please, + rearrange them properly. + tar: --exclude '*.o' has no effect + tar: Exiting with failure status due to previous errors + + version 1.29 - Sergey Poznyakoff, 2016-05-16 * New options: --verbatim-files-from, --no-verbatim-files-from diff --git a/configure.ac b/configure.ac index 50fbae51..715a3661 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -AC_INIT([GNU tar], [1.29], [bug-tar@gnu.org]) +AC_INIT([GNU tar], [1.29.90], [bug-tar@gnu.org]) AC_CONFIG_SRCDIR([src/tar.c]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_HEADERS([config.h]) diff --git a/doc/tar.texi b/doc/tar.texi index a8969e08..51ed159b 100644 --- a/doc/tar.texi +++ b/doc/tar.texi @@ -3879,6 +3879,23 @@ tar -cf a.tar /usr --no-recursion /var/* tar -cf a.tar --recursion /usr --no-recursion /var/* @end example +During archive creation, @GNUTAR{} keeps track of positional options +used and arguments affected by them. If it finds out that any such +options are used in an obviously erroneous way, the fact is reported +and exit code is set to 2. E.g.: + +@example +@group +$ @kbd{tar -cf a.tar . --exclude '*.o'} +tar: The following options were used after any non-optional +arguments in archive create or update mode. These options are +positional and affect only arguments that follow them. Please, +rearrange them properly. +tar: --exclude '*.o' has no effect +tar: Exiting with failure status due to previous errors +@end group +@end example + The following table summarizes all position-sensitive options. @table @option diff --git a/src/names.c b/src/names.c index 037b869d..e3be7569 100644 --- a/src/names.c +++ b/src/names.c @@ -149,16 +149,29 @@ static struct argp_option names_options[] = { {NULL} }; -static bool -is_file_selection_option (int key) +static struct argp_option const * +file_selection_option (int key) { struct argp_option *p; for (p = names_options; !(p->name == NULL && p->key == 0 && p->doc == NULL); p++) if (p->key == key) - return true; - return false; + return p; + return NULL; +} + +static char const * +file_selection_option_name (int key) +{ + struct argp_option const *opt = file_selection_option (key); + return opt ? opt->name : NULL; +} + +static bool +is_file_selection_option (int key) +{ + return file_selection_option (key) != NULL; } /* Either NL or NUL, as decided by the --null option. */ @@ -670,7 +683,85 @@ name_list_adjust (void) while (name_head->prev) name_head = name_head->prev; } + +/* For error-reporting purposes, keep a doubly-linked list of unconsumed file + selection options. The option is deemed unconsumed unless followed by one + or more file/member name arguments. When archive creation is requested, + each file selection option encountered is pushed into the list. The list + is cleared upon encountering a file name argument. + + If the list is not empty when all arguments have been processed, an error + message is issued reporting the options that had no effect. + + For simplicity, only a tail pointer of the list is maintained. +*/ + +struct name_elt *unconsumed_option_tail; + +/* Push an option to the list */ +static void +unconsumed_option_push (struct name_elt *elt) +{ + elt->prev = unconsumed_option_tail; + if (unconsumed_option_tail) + unconsumed_option_tail->next = elt; + unconsumed_option_tail = elt; +} + +/* Clear the unconsumed option list */ +static void +unconsumed_option_free (void) +{ + while (unconsumed_option_tail) + { + struct name_elt *elt = unconsumed_option_tail; + unconsumed_option_tail = unconsumed_option_tail->prev; + free (elt); + } +} + +/* Report any options that have not been consumed */ +static void +unconsumed_option_report (void) +{ + if (unconsumed_option_tail) + { + struct name_elt *elt; + + ERROR ((0, 0, _("The following options were used after any non-optional arguments in archive create or update mode. These options are positional and affect only arguments that follow them. Please, rearrange them properly."))); + + elt = unconsumed_option_tail; + while (elt->prev) + elt = elt->prev; + while (elt) + { + switch (elt->type) + { + case NELT_CHDIR: + ERROR ((0, 0, _("-C %s has no effect"), quote (elt->v.name))); + break; + + case NELT_OPTION: + if (elt->v.opt.arg) + ERROR ((0, 0, _("--%s %s has no effect"), + file_selection_option_name (elt->v.opt.option), + quote (elt->v.opt.arg))); + else + ERROR ((0, 0, _("--%s has no effect"), + file_selection_option_name (elt->v.opt.option))); + break; + + default: + break; + } + elt = elt->next; + } + + unconsumed_option_free (); + } +} + static void name_list_advance (void) { @@ -678,7 +769,18 @@ name_list_advance (void) name_head = elt->next; if (name_head) name_head->prev = NULL; - free (elt); + if (elt->type == NELT_OPTION || elt->type == NELT_CHDIR) + { + if (subcommand_option == CREATE_SUBCOMMAND + || subcommand_option == UPDATE_SUBCOMMAND) + unconsumed_option_push (elt); + } + else + { + if (elt->type != NELT_NOOP) + unconsumed_option_free (); + free (elt); + } } @@ -1013,6 +1115,8 @@ name_next_elt (int change_dirs) } } + unconsumed_option_report (); + return NULL; } diff --git a/tests/Makefile.am b/tests/Makefile.am index 3e942769..0ea6d172 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -166,6 +166,9 @@ TESTSUITE_AT = \ opcomp04.at\ opcomp05.at\ opcomp06.at\ + positional01.at\ + positional02.at\ + positional03.at\ options.at\ options02.at\ owner.at\ diff --git a/tests/positional01.at b/tests/positional01.at new file mode 100644 index 00000000..37b14db6 --- /dev/null +++ b/tests/positional01.at @@ -0,0 +1,54 @@ +# Process this file with autom4te to create testsuite. -*- Autotest -*- + +# Test suite for GNU tar. +# Copyright 2016 Free Software Foundation, Inc. + +# This file is part of GNU tar. + +# GNU tar is free software; you can redistribute it and/or modify +# 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. + +# GNU tar is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# 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, see <http://www.gnu.org/licenses/>. + +AT_SETUP([Exclude]) +AT_KEYWORDS([options positional positional01 exclude]) + +AT_CHECK([ +AT_SORT_PREREQ +mkdir dir +> dir/A.a +> dir/B.a +> dir/A.b +tar -cf a.tar --exclude '*.b' dir +echo $? +tar -tf a.tar | sort +tar -cf a.tar dir --exclude '*.b' +echo $? +tar -tf a.tar | sort +], +[0], +[0 +dir/ +dir/A.a +dir/B.a +2 +dir/ +dir/A.a +dir/A.b +dir/B.a +], +[tar: The following options were used after any non-optional arguments in archive create or update mode. These options are positional and affect only arguments that follow them. Please, rearrange them properly. +tar: --exclude '*.b' has no effect +tar: Exiting with failure status due to previous errors +]) + +AT_CLEANUP + diff --git a/tests/positional02.at b/tests/positional02.at new file mode 100644 index 00000000..352b62cf --- /dev/null +++ b/tests/positional02.at @@ -0,0 +1,49 @@ +# Process this file with autom4te to create testsuite. -*- Autotest -*- + +# Test suite for GNU tar. +# Copyright 2016 Free Software Foundation, Inc. + +# This file is part of GNU tar. + +# GNU tar is free software; you can redistribute it and/or modify +# 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. + +# GNU tar is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# 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, see <http://www.gnu.org/licenses/>. + +AT_SETUP([Directory]) +AT_KEYWORDS([options positional positional02 directory chdir]) + +AT_CHECK([ +AT_SORT_PREREQ +mkdir dir +> dir/A.a +> dir/B.a +> dir/A.b +tar -cf a.tar -C dir . +echo $? +tar -tf a.tar | sort +tar -cf a.tar . -C dir +], +[2], +[0 +./ +./A.a +./A.b +./B.a +], +[tar: ./a.tar: file is the archive; not dumped +tar: The following options were used after any non-optional arguments in archive create or update mode. These options are positional and affect only arguments that follow them. Please, rearrange them properly. +tar: -C 'dir' has no effect +tar: Exiting with failure status due to previous errors +]) + +AT_CLEANUP + diff --git a/tests/positional03.at b/tests/positional03.at new file mode 100644 index 00000000..9a03671d --- /dev/null +++ b/tests/positional03.at @@ -0,0 +1,47 @@ +# Process this file with autom4te to create testsuite. -*- Autotest -*- + +# Test suite for GNU tar. +# Copyright 2016 Free Software Foundation, Inc. + +# This file is part of GNU tar. + +# GNU tar is free software; you can redistribute it and/or modify +# 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. + +# GNU tar is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# 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, see <http://www.gnu.org/licenses/>. + +AT_SETUP([Several options]) +AT_KEYWORDS([options positional positional03]) + +AT_CHECK([ +AT_SORT_PREREQ +mkdir t +cd t +mkdir dir +> dir/A.a +> dir/B.a +> dir/A.b +tar -vcf ../a.tar --exclude '*.b' . -C dir --exclude '*.c' | sort +], +[0], +[./ +./dir/ +./dir/A.a +./dir/B.a +], +[tar: The following options were used after any non-optional arguments in archive create or update mode. These options are positional and affect only arguments that follow them. Please, rearrange them properly. +tar: -C 'dir' has no effect +tar: --exclude '*.c' has no effect +tar: Exiting with failure status due to previous errors +]) + +AT_CLEANUP + diff --git a/tests/testsuite.at b/tests/testsuite.at index cf4b2fd5..11c39c9f 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -213,6 +213,11 @@ m4_include([opcomp04.at]) m4_include([opcomp05.at]) m4_include([opcomp06.at]) +AT_BANNER([Positional options]) +m4_include([positional01.at]) +m4_include([positional02.at]) +m4_include([positional03.at]) + AT_BANNER([The -T option]) m4_include([T-mult.at]) m4_include([T-nest.at]) |