3448 Commits
Author SHA1 Message Date
Darren CarrerasandSergey Poznyakoff d1df7f403d tar: invalidate directory cache after failed open
fdbase_opendir copies a requested directory name into the cache before
opening it.  If open_subdir fails, this leaves the new name associated
with the old file descriptor.  A retry after tar creates the missing
parent can then extract into the old directory.

Close an unowned old descriptor before trying to open the new dir and
invalidate the cache entry if that fails.  Add a regression test using
equal-length sibling directory names.

* src/misc.c (fdbase_opendir): Invalidate the cache after a failed
replacement open.
* tests/extrac35.at: New test.
* tests/Makefile.am (TESTSUITE_AT): Add it.
* tests/testsuite.at: Include it.
2026-08-06 08:35:37 +03:00
Paul Eggert 9371d36cc7 tar: reuse FD when extracting hard links
* src/extract.c (rename_directory): Redo to accommodate
new semantics of fdbase1, and to use fds more intelligently.
* src/misc.c (fdbase_opendir): If ALTERNATE, it is now OK to use,
though not update, the main cache.  This makes it possible for the
caller to do linkat (N, "A", N, "B") instead of the
linkat (N, "A", N + 1, "B") it previously did, and this
saves some open and close calls on directories.
2026-07-29 23:12:46 -07:00
Paul Eggert e54e505a92 tar: open directories more efficiently
Without this patch, tar would open the parent of a directory
for search, then open the directory itself for search.
It's more efficient to just open the directory for search.
* src/create.c (create_archive, restore_parent_fd, chdir_do):
Use open_searchdir instead of opening by hand.
* src/misc.c (chdir_do): Use fdbase_opendir and fdbase_close
instead of openat and close, so that the fd is cached properly.
(chdirable): New function.
(fdbase_clear): Use it to avoid closing chdirable FDs.
(fdbase_close): New function.
(open_subdir): New arg OFLAGS.  All callers changed.
(fdbase_opendir): New arg CHILD_OFLAGS.  All callers changed.
Prefer AT_FDCWD for absolute file names, so that we need not
worry about chdir_fd == BADFD in that case.
Do not allow empty file names.
When replacing an old directory, do not close its fd if it
is chdirable.
(open_searchdir): New function.
* src/tar.c (decode_options): Do not worry about one_top_level_dir
and IS_ABSOLUTE_FILE_NAME (one_top_level_dir), as fdbase_opendir
now prefers AT_FDCWD for absolute file names.
(tar_stat_close): Use fdbase_close instead of close,
so that the fd is cached properly.
2026-07-29 23:12:46 -07:00
Paul Eggert 941f62b24d --one-top-level clarifications
Bring back documentation for --one-top-level absolute file names,
and clarify its behavior.  Allow --one-top-level only with
-x, -d, -t.
* src/misc.c (chdir_do): Do not pass -1 to openat.  Simplify now
that open_searchdir_how no longer has RESOLVE_BENEATH when
one_top_level_dir is absolute.  Fix errno confusion in messages.
* src/tar.c (decode_options): Allow --one-top-level only with -x,
-d, and -t.  Do not use RESOLVE_BENEATH if --one-top-level=/foo is
used; this simplifies chdir_do.
2026-07-29 23:12:46 -07:00
Paul Eggert 05f21fe936 Save work if one_top_level_dir is absolute
* src/misc.c (chdir_arg): Optimize --one-top-level=X where X is an
absolute file name.
2026-07-29 23:12:46 -07:00
Paul Eggert 25d8b4b1ac Save a syscall in trivial extract_dir
* src/extract.c (trivial_base_name): New function.
(extract_dir): Use it.
2026-07-29 23:12:46 -07:00
Paul Eggert ffe4551136 Remove struct wd.one_top_level
This merely refactors.
* src/misc.c: Don’t include assert.h.
(struct wd.one_top_level): Remove.  All uses changed to say that
it’s a one_top_level directory iff its index is odd and
one_top_level_dir is nonnull.  This simplifies the code and
removes the need for a couple of ‘assert’s.  This code
uses ~+X instead of ~X to pacify gcc -Wbool-operation.
2026-07-29 23:12:46 -07:00
Paul Eggert bad45bee3e Improve dir checking in make_directories
Prefer faccessat to fstatat for dir checking.
Also, don’t bother doing either check if caller
is about to check the rough equivalent anyway.
* src/extract.c (make_directories): Now static.
2nd arg is now a three-way flag.  All uses changed.
Use faccessat instead of fstatat, to avoid EOVERFLOW issues.
(create_dir): New function, for use outside this module.
External caller changed.
(maybe_recoverable): Set *INTERDIR_MADE if make_directories
said we made the parent.
2026-07-29 23:12:46 -07:00
Paul Eggert b7704c8d98 Avoid need to append "/." for make_directories
* src/extract.c (make_directories): New arg JUST_PARENT.
All callers changed.
* src/misc.c (struct wd.name, add_wd, chdir_arg):
Use char *, not char const *, to let make_directories
temporarily alter slashes.  All uses changed.
(chdir_do): Do not create a new name with trailing "/."
because make_directories no longer needs this.
2026-07-29 23:12:46 -07:00
Paul Eggert 4dc85c626f Simplify make_directories API
* src/extract.c (make_directories): Return a 3-way int rather than
an int (actually a bool) and another optional bool via a pointer.
All callers changed.  In comment, make it clearer what the
return value means.  Also, improve behavior in a small way: when
issuing a diagnostic on MS-Windows-like systems, use the original
directory name rather than translating '\\' to '/'.
2026-07-29 23:12:46 -07:00
Paul Eggert d405469bf4 Improve --keep-directory-symlink performance
* src/extract.c (is_directory_link): Remove; no longer needed.
(extract_dir): If --keep-directory-symlink, avoid the need
to call issymlinkat if either --dereference is not specified,
or if the plain stat fails.  This saves a syscall, simplifies
the code a bit, and should simplify future changes.
2026-07-29 23:12:46 -07:00
Paul Eggert 0ec9f0ebf6 Go back to simpler chdir_arg API
* src/misc.c (add_wd, ensure_wd): New functions, replacing ...
(grow_wd): .. this function, for clarity.  All uses changed.
(chdir_arg): Omit 2nd arg, to keep callers simpler.
All uses changed.  Instead of being recursive, be iterative;
this is part of the simplification.
2026-07-29 23:12:46 -07:00
Paul Eggert e335e2c8b1 Add comment about deducing --one-top-level name 2026-07-29 23:12:46 -07:00
Pavel CahynaandPaul Eggert 1980e032af Get rid of create_dir
It turns out that make_directories can do what we need (create all
directories in a path) if we append a dummy "." component, as it creates
directories up to and excluding the last component of the path.

Also, do not avoid using delay_set_stat on the newly created
directories. This matches the rest of the code and avoids potentially
leaving the newly-created directories with too open permissions.
This requires some workarounds to cope with
apply_nonancestor_delayed_set_stat and mark_metadata_set problems: do it
as in the rest of the code - apply the stats before proceeding with
extraction of anything else.
2026-07-29 23:12:46 -07:00
Pavel CahynaandPaul Eggert 325b899214 Eliminate redundant chdir_do
If one-top-level is not provided, chdir_do is a no-op.
2026-07-29 23:12:46 -07:00
Pavel CahynaandPaul Eggert b17665b2c0 Add tests for cyclic renames
Using options to extract to a subdirectory: one test with -C,
another with --one-top-level.
2026-07-29 23:12:46 -07:00
Pavel CahynaandPaul Eggert 3903b37673 Revert "tar: incremental 'X' follows --one-top-level"
This reverts commit 79d61af0e1.
2026-07-29 23:12:46 -07:00
Pavel CahynaandPaul Eggert 1b91f5f66f Draft patch for openat2 changes vs --one-top-level
The patch leverages the existing -C code. In order to do that, every
entry in the wd[] table gets another companion entry in the table that
represents the --one-top-level directory. There is one additional field
in each entry that allows skipping the companion entries if they are not
desired.

The actual directory is created lazily by chdir_do() if needed, as you
requested, to avoid empty "a/foo" after --one-top-level=foo -C a -C b.

The patch "by the way" fixes also extraction of hardlinks with
--one-top-level which currently is broken in the typical case (the
transform is not applied to the target, so the hardlink is wrong).

The patch does not yet handle the --show-transformed case with
--one-top-level that you discussed in another subthread. As a result, two
tests now fail (onetop02.at and onetop04.at). I suppose that this would
be quite easy to fix.

Another issue that I am aware of is that I am not sure whether to call
repair_delayed_set_stat and/or delay_set_stat on the newly created
directories like extract_dir() does (the whole delay_set code is abit
mysterious to me).

Use of --create together with --one-top-level should probably be
forbidden, as unlink.c uses wd[] in a way that will likely break in the
presence of companion entries (the chdir_do call in
flush_deferred_unlinks).

Show the one-top-level arg as a transformation
2026-07-29 23:12:46 -07:00
Sergey Poznyakoff e407e6e7dd Fix --set-mtime-command.
This fixes a bug introduced by 281e03ec6.

* src/system.c (sys_exec_setmtime_script): Increase buflen by
value of nread.
2026-07-25 17:10:11 +03:00
Sergey Poznyakoff 19a3a73e8c Assume directory members have size=0.
Since commit b8d8a61b, tar started honoring size field in headers
of the directory archive members when listing and extracting. That
doesn't seem right: although GNU tar always stores 0 for such members,
there are other tar implementation that don't. As a result, GNU tar
skips the actual directory contents when listing or extracting archives
created by such implementations.

This commit fixes that by assuming that size is 0 for directory archive
members.

* src/list.c (member_is_dir): Restore function.
(skim_member): Don't apply skim_file to directory members.
* tests/skipdir.at: Fix expectations.
2026-07-23 10:52:03 +03:00
Sergey Poznyakoff 5a225f25c5 Update paxutils 2026-07-23 09:00:22 +03:00
Sergey Poznyakoff 87819f9f0a Check if the dumpdir read from the archive is well-formed before using it.
* src/common.h (dumpdir_ok): New proto.
* src/incremen.c (dumpdir_ok): Take size as the second argument.
Verify if the last byte is 0 and the dumpdir contains 0 or more
nul-terminated strings.
(get_gnu_dumpdir): Check if the obtained dumpdir is ok. Clear the
is_dumpdir flag if it is not.
* src/xheader.c (dumpdir_decoder) Verify if the obtained dumpdir is
ok.
2026-07-21 22:49:04 +03:00
Pavel CahynaandSergey Poznyakoff 08c3fc2e93 Avoid acl_ prefix for functions
The acl.h header from libacl uses acl_ prefix for its functions. Avoid
defining functions with the same name in order to protect its namespace.
2026-07-03 12:58:18 +03:00
Paul Eggert 7dae65f44c * list.c: Correct some historical commentary. 2026-06-20 00:54:28 -07:00
Paul Eggert 67981bbb15 tar: ignore nonzero sizes in hard links etc
Problem reported by Antonio Teixeira.
* src/list.c (read_header): When POSIX says a size field must
be zero or does not represent a data count, treat it as zero.
* tests/extrac32.at: Update to match new behavior.
We now treat hard link sizes as zero even when the size fields are
nonzero, and this means the “injected” file is treated as valid
regardless of whether we list or extract.
* tests/extrac34.at: New test.
* tests/Makefile.am (TESTSUITE_AT), tests/testsuite.at: Add it.
2026-06-20 00:29:25 -07:00
Sergey Poznyakoff 145a671e8a Fix extracting over symlinks with --dereference
Extraction over symlink to a directory was broken in 75b03fdff4.
See https://savannah.gnu.org/bugs/index.php?68368

* src/tar.c (decode_options): Don't enable RESOLVE_BENEATH mode
if --dereference is given.
* tests/extrac33.at: New test.
* tests/Makefile.am: Add new test.
* tests/testsuite.at: Likewise.
* tests/extrac13.at: Add a keyword.
* tests/extrac31.at: Remove --absolute-names keyword: that option
is never used in the testcase. Add CVE-2025-45582 keyword instead.
2026-06-11 16:35:20 +03:00
Sergey Poznyakoff cb1973cc0e Minor fix in the testsuite
* tests/extrac32.at: Remove debugging code.
2026-06-11 16:32:17 +03:00
Sergey Poznyakoff ba4f476d68 Fix doc generation
* doc/Makefile.am: Use tidy mode for texi2dvi; don't use
the deprecated texi2html.
* doc/tar.texi: Fix rendering of o-umlaut.
* doc/texify.sed: Likewise.
2026-06-11 14:40:02 +03:00
Sergey Poznyakoff cc999825fe Fix descriptions of -C and -T options.
This fixes discrepancies reported in https://savannah.gnu.org/bugs/?68253
and https://savannah.gnu.org/bugs/?68408.

* doc/tar.texi: Emphasize that the -C option does not affect filename
arguments to another options, such as -f, -T or the like.  Improve
the description of -T.
* doc/tar.1: Fix descriptions of -C and -T.
2026-06-11 13:59:29 +03:00
Paul Eggert 0efc3bd058 Pacify GCC 16.1 -Wanalyzer-use-of-uninitialized-value
This fixes a false positive with gcc 16.1.1 20260501 (Red Hat
16.1.1-1) on x86-64.
* src/extract.c (set_stat): Use differently-worded but equivalent test
to help the compiler see that ts[0].tv_sec is used only if sedt.
2026-05-11 15:38:15 -07:00
Paul Eggert d96b58545d build: update gnulib submodule to latest 2026-05-11 15:38:15 -07:00
Paul Eggert 6ff0c2ad11 tar: remove no-longer-accurate comment 2026-05-11 14:16:28 -07:00
Paul Eggert 5479c4b905 Quote --set-mtime-command file names
Problem reported by Raphael Karger.
* src/system.c: Include quotearg.h.
(sys_exec_setmtime_script): Quote the file name for the shell.
2026-05-11 14:13:59 -07:00
Paul Eggert d479b2cc91 Use mkdtempat instead of mkdtemp
This fixes an interaction of -C with incremental 'X'.
Problem reported by Pavel Cahyna.
* gnulib.modules: Remove mkdtemp.
Add tempname, since our mkdtempat uses it.
* lib/mkdtempat.c, lib/mkdtempat.h: New files.
* lib/Makefile.am (noinst_HEADERS): Add mkdtempat.h.
(libtar_a_SOURCES): Add mkdtempat.c.
* src/incremen.c: Include mkdtempat.h.
(purge_directory): Use mkdtempat, not mkdtemp.
2026-04-13 00:02:17 -07:00
Paul Eggert 0470c109c0 tar: comment struct fdbase
* src/common.h (struct fdbase): Add comment.
2026-04-13 00:02:17 -07:00
Paul Eggert 55e8233438 tar: ENFILE is like EMFILE
* src/create.c (open_failure_recover):
* src/misc.c (fdbase_opendir):
Treat ENFILE like EMFILE.
2026-04-13 00:02:17 -07:00
Paul Eggert 79d61af0e1 tar: incremental 'X' follows --one-top-level
* src/incremen.c (purge_directory):
Also respect --one-top-level when handling 'X'.
2026-04-08 09:07:12 -07:00
Paul Eggert 67c8dff696 Simplify one_top_level_dir logic
* src/tar.c (one_top_level_option): Remove.  All uses removed.
All external uses changed to equivalent of !!one_top_level_dir.
(decode_options): Set one_top_level_dir to be consistent with
the old one_top_level_option.
2026-04-08 09:07:12 -07:00
Paul Eggert 90dec1cc53 --one-top-level now keeps "../" and ".../"
* src/list.c (enforce_one_top_level): Do not strip prefixes like
"../" (which should not be allowed unless -P) and ".../" (which
are ordinary file names).  The "../" not being allowed should be
addressed in a different way.
2026-04-08 09:07:12 -07:00
Paul Eggert b4fc9ca136 Disallow --one-top-level=''.
* src/tar.c (decode_options): Do not accept an empty string
as a relative file name.
2026-04-08 09:07:12 -07:00
Paul Eggert 3e4279db96 Prefer signed int in sparse.c
* src/sparse.c (pax_dump_header_0, floorlog10)
(pax_dump_header_1, struct ok_n_block_ptr, decode_num)
(pax_decode_header): Prefer signed to unsigned integers
where either will do, as this allows for better runtime
checking for overflow.  The integers in question cannot
be negative or greater than INTMAX_MAX anyway.
2026-04-06 14:04:48 -07:00
Paul Eggert 0714d2f082 tar: strip '/' from incremental 'X' entries
Problem identified by Michał Majchrowicz and Marcin Wyczechowski,
members of the AFINE Team.
* gnulib.modules: Add mempcpy, which we were already using anyway.
* src/incremen.c (purge_directory):
Use a safer suffix for 'X' entries, too.
Also, do not turn "/" to "//" or "//" to "///" (possible only if -P).
2026-04-04 10:51:40 -07:00
Paul Eggert 9280aa3807 Prefer UNNAMED to MAYBE_UNUSED
* src/buffer.c, src/compare.c, src/exclist.c, src/extract.c:
* src/sparse.c, src/tar.c, src/xheader.c:
UNNAMED is for when an identifier is never used and so does not
need a name.  Prefer it to MAYBE_UNUSED when that is the case.
Also, drop MAYBE_UNUSED in some places where the identifier
is always used.
2026-03-22 12:23:55 -07:00
Paul Eggert 9e22dde2df Update tar.h comments
* src/tar.h: Update comments.
2026-03-22 12:23:55 -07:00
Paul Eggert b8d8a61b25 Fix more -t/-x discrepancies
Problem reported by Guillermo de Angel in:
https://lists.gnu.org/r/bug-tar/2026-03/msg00007.html
* THANKS: Add him, and sort.
* src/extract.c (extract_dir, extract_file):
* src/incremen.c (purge_directory):
Do not call skip_member, as the caller now does that, and does it
more reliably.
* src/extract.c (extract_file):
Mark file as skipped when we’ve read it.
(extract_archive): Always call skip_member after extracting,
as it suppresses the skip as needed.
* src/incremen.c (try_purge_directory): Remove; no longer
needed.  Move internals to purge_directory.
* src/list.c (read_header): Do not treat LNKTYPE header as having
size zero, as it can be nonzero (e.g., ‘pax -o linkdata’).
Set info->skipped field according to how the header was read.
(member_is_dir): Remove; no longer needed.
(skim_member): Skip directory data too, unless it’s already been
skipped (i.e., read).
* tests/extrac32.at: New file.
* tests/Makefile.am (TESTSUITE_AT):
* tests/testsuite.at:
Add it.
* tests/skipdir.at (skip directory members):
Fix test to match the correct behavior.
This fixes a bug introduced in commit
b009124ffd
dated 2025-05-12 17:17:21 +0300.
2026-03-22 12:23:55 -07:00
Paul Eggert e06a880a91 build: update gnulib submodule to latest 2026-03-22 12:23:55 -07:00
Paul Eggert a7526eb3f0 Update NEWS for previous patch 2026-03-12 12:31:55 -07:00
Marco NenciariniandPaul Eggert dcb8c5f932 Respect --ignore-failed-read in file_removed_diag (bug#68075)
* src/misc.c (file_removed_diag): Guard set_exit_status call
with !ignore_failed_read_option, consistent with stat_diag and
other diagnostic functions.
* tests/filerem03.at: New test.
* tests/testsuite.at: Include it.
* tests/Makefile.am: Add it.
Copyright-paperwork-exempt: yes

Signed-off-by: Marco Nenciarini <marco.nenciarini@enterprisedb.com>
2026-03-12 12:31:55 -07:00
Paul Eggert dda26d5c53 Update NEWS for previous patch 2026-03-10 09:46:42 -07:00
Weixie CuiandPaul Eggert af552a0769 Fix wrong fd in restore_parent_fd fallback path
Use fstat(origfd) instead of fstat(parentfd) when verifying the
alternatively-opened directory; parentfd is invalid in this branch.

Copyright-paperwork-exempt: yes
2026-03-10 09:46:42 -07:00