tar: reject -C x --one-top-dir=/abs/olute

It’s not clear what ‘-C x --one-top-dir=/abs/olute’ should mean,
so for now let’s play it safe and reject that combination.
* src/misc.c (chdir_arg): Diagnose attempts to combine
-C with --one-top-level=/abs/olute.
* tests/onetop06.at: Move last test to onetop07.at,
since it now differs in behavior and it’s better to
test it separately.
* tests/onetop07.at: New file.
* tests/Makefile.am (TESTSUITE_AT): Add it.
* tests/testsuite.at: Include it.
This commit is contained in:
Paul Eggert
2026-08-20 15:46:21 -07:00
parent 961e48a903
commit 94391c4bf1
7 changed files with 59 additions and 19 deletions
+5 -4
View File
@@ -38,10 +38,11 @@ option.
** The --one-top-level option now requires either -x or -d mode.
Previously the behavior was unspecified in other operation modes.
** If DIR is absolute, the --one-top-level=DIR option now extracts all
files relative to DIR, without stripping leading DIR from file names.
Any -C options are ignored. Formerly, the behavior was
undocumented and differed from one tar version to the next.
** If DIR is absolute, the --one-top-level=DIR option is now incompatible
with the --directory (-C) option, and it now extracts all files
relative to DIR, without stripping leading DIR from file names.
Formerly, the behavior was undocumented and differed from one tar
version to the next.
* Bug fixes
+5 -5
View File
@@ -3291,8 +3291,7 @@ Extract files relative to @var{dir},
ignoring any @var{dir} prefixes in the archive.
An absent @var{dir} defaults to
the base name of the archive minus any recognized archive suffix.
If @var{dir} is relative, it is relative to the working directory;
if absolute, any @option{--directory} (@option{-C}) options are irrelevant.
If @var{dir} is relative, it is relative to the working directory.
@xref{directory}.
@opsummary{overwrite}
@@ -9465,8 +9464,7 @@ Recognized file name suffixes are @samp{.tar},
and any compression suffixes recognizable by @xref{--auto-compress}.
If @var{dir} is absolute, extract all files under that directory;
any @option{-C} options are irrelevant,
and @var{dir} itself is exempt from the usual safety rules
@var{dir} itself is exempt from the usual safety rules
prohibiting extraction outside the working directory.
The two main differences between @samp{--one-top-level=/abs/olute}
and @samp{-C /abs/olute} are that the former affects all files
@@ -9477,7 +9475,9 @@ whereas in the latter @file{/abs/olute} must already exist.
The @option{--one-top-level} option can be used only when extracting,
comparing, or reading from the archive.
It is incompatible with the @option{--absolute-names} (@option{-P}) option.
It is incompatible with the @option{--absolute-names} (@option{-P}) option,
and if @var{dir} is absolute it is incompatible with the
@option{--directory} (@option{-C}) option.
@end table
All filename arguments appearing after a
+12 -8
View File
@@ -979,7 +979,10 @@ struct wd
directory. Ordinarily the remaining entries are for -C options.
But if --one-top-level, each entry is followed by another entry for
its --one-top-level counterpart, so that ordinary entries are
even-numbered and --one-top-level entries are odd-numbered. */
even-numbered and --one-top-level entries are odd-numbered.
And if --one-top-level specifies an absolute directory,
there are just two entries, one for the initial working directory
and one for the absolute directory. */
static struct wd *wd;
/* The number of working directories in the vector. */
@@ -1046,13 +1049,18 @@ ensure_wd (void)
}
/* DIR is the operand of a -C option; add it to vector of chdir targets,
and return the index of its location. If --one-top-level-dir, add
two targets to the vector. However, if DIR is "." or an equivalent,
or if --one-top-level-dir is an absolute file name,
and return the index of its location. If --one-top-level-dir=ONETOP
is specified, add two targets to the vector if ONETOP is relative
and report an error otherwise. However, if DIR is "." or an equivalent,
just reuse the last item in the vector. */
idx_t
chdir_arg (char *dir)
{
/* Unless this is the trivial chdir_arg (".") at start, this is an
error when combined with --one-top-level=X where X is absolute. */
if (wd && one_top_level_dir && IS_ABSOLUTE_FILE_NAME (one_top_level_dir))
paxfatal (0, _("-C and --one-top-level='/...' are incompatible"));
ensure_wd ();
/* Optimize the common special case of the working directory,
@@ -1064,10 +1072,6 @@ chdir_arg (char *dir)
return wd_count - 1;
}
/* Optimize --one-top-level=X where X is an absolute file name. */
if (one_top_level_dir && IS_ABSOLUTE_FILE_NAME (one_top_level_dir))
return wd_count - 1;
ptrdiff_t shortage = 1 + !!one_top_level_dir - (wd_alloc - wd_count);
if (0 < shortage)
wd = xpalloc (wd, &wd_alloc, shortage, -1, sizeof *wd);
+1
View File
@@ -205,6 +205,7 @@ TESTSUITE_AT = \
onetop04.at\
onetop05.at\
onetop06.at\
onetop07.at\
opcomp01.at\
opcomp02.at\
opcomp03.at\
-2
View File
@@ -32,8 +32,6 @@ diff d e/d/d || exit
tar -cf test1.tar e/c || exit
tar -xf test1.tar -C f --one-top-level=e/c || exit
diff e/c/d f/e/c/d || exit
tar -xf test1.tar -C f --one-top-level=$PWD/g || exit
diff e/c/d g/e/c/d || exit
])
AT_CLEANUP
+35
View File
@@ -0,0 +1,35 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
#
# Test suite for GNU tar.
# Copyright 2026 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([tar -C and --one-top-level=/abs/olute])
AT_KEYWORDS([extract onetop onetop07])
AT_TAR_CHECK([
mkdir d f && genfile --file d/file || framework_failure_
tar -cf test.tar d || exit
tar -xf test.tar -C f --one-top-level=$PWD/g
],
[2],
[],
[tar: -C and --one-top-level='/...' are incompatible
tar: Error is not recoverable: exiting now
])
AT_CLEANUP
+1
View File
@@ -544,6 +544,7 @@ m4_include([onetop03.at])
m4_include([onetop04.at])
m4_include([onetop05.at])
m4_include([onetop06.at])
m4_include([onetop07.at])
AT_BANNER([Star tests])
m4_include([star/gtarfail.at])