]> git.ipfire.org Git - thirdparty/tar.git/commitdiff
tar: --one-top-level=DIR must be relative master
authorPaul Eggert <eggert@cs.ucla.edu>
Fri, 30 Jan 2026 20:48:48 +0000 (12:48 -0800)
committerPaul Eggert <eggert@cs.ucla.edu>
Fri, 30 Jan 2026 20:56:30 +0000 (12:56 -0800)
* src/tar.c (decode_options): Require --one-top-level operand
to be relative.

NEWS
doc/tar.texi
src/tar.c

diff --git a/NEWS b/NEWS
index 99a22896844363887e40c2ce9a28941232895f0e..083d5831fe9c44c7381cbdf71cbae52ab3f9d7e0 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-GNU tar NEWS - User visible changes. 2025-11-26
+GNU tar NEWS - User visible changes. 2026-01-30
 Please send GNU tar bug reports to <bug-tar@gnu.org>
 \f
 version 1.35.90 (git)
@@ -24,7 +24,9 @@ as argument to --mtime option (see GNU tar manual, chapter 4
 Defines output format for the COMMAND set by the above option.  If
 used, command output will be parsed using strptime(3).
 
-* Skip file or archive member if transformed name is empty
+* Changes to behavior
+
+** Skip file or archive member if transformed name is empty
 
 If applying file name transformations (--transform and
 --strip-component options) to a file or member name results in an
@@ -33,6 +35,9 @@ empty string that file or member is skipped and a warning is printed.
 The warning can be suppressed using the --warning=empty-transform
 option.
 
+** --one-top-level=DIR now requires DIR to be relative.
+   Previously this restriction was alluded to in the manual but not enforced.
+
 * Bug fixes
 
 ** When extracting, tar no longer follows symbolic links to targets
index 211b5960e64b96464f5307b994f01715513e5709..c1b6f7d2eb1a6a22e54b8624202d7234d72cf39d 100644 (file)
@@ -3274,10 +3274,14 @@ directory.
 @opsummary{one-top-level}
 @item --one-top-level[=@var{dir}]
 Tells @command{tar} to create a new directory beneath the extraction directory
-(or the one passed to @option{-C}) and use it to guard against
-tarbombs.  In the absence of @var{dir} argument, the name of the new directory
-will be equal to the base name of the archive (file name minus the
-archive suffix, if recognized).  Any member names that do not begin
+(or the one passed to @option{-C}) and use it to prevent @command{tar}
+from modifying files outside that directory.
+If @var{dir} is present, it must be a relative file name.
+If it is absent, the name of the new directory
+is the base name of the archive minus any recognized archive suffix.
+If multiple @option{-C} options are present,
+each has its own subdirectory with the same name.
+Any member names that do not begin
 with that directory name (after
 transformations from @option{--transform} and
 @option{--strip-components}) will be prefixed with it.  Recognized
index 9c53bdbd77f21e0815591deb4f5a3769c221a0c0..9376b59b74e57f1770c3209de7c3f5ad92e938df 100644 (file)
--- a/src/tar.c
+++ b/src/tar.c
@@ -2675,7 +2675,7 @@ decode_options (int argc, char **argv)
            one_top_level_option = false;
        }
 
-      if (one_top_level_option && !one_top_level_dir)
+      if (!one_top_level_dir && one_top_level_option)
        {
          /* If the user wants to guarantee that everything is under one
             directory, determine its name now and let it be created later.  */
@@ -2687,6 +2687,9 @@ decode_options (int argc, char **argv)
            paxusage (_("Cannot deduce top-level directory name; "
                        "please set it explicitly with --one-top-level=DIR"));
        }
+
+      if (one_top_level_dir && !IS_RELATIVE_FILE_NAME (one_top_level_dir))
+       paxusage(_("--one-top-level=DIR must use a relative file name"));
     }
 
   /* If ready to unlink hierarchies, so we are for simpler files.  */