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.
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.
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.
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.
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.
* 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>
* tests/sparse05.at (listing sparse files bigger than 2^33 B):
If there were problems generating BIGFILE remove it,
as it has likely exhausted the file system.
Problem found on Darwin 21.6 APFS.
This addresses CVE-2025-45582.
* gnulib.modules: Add openat2.
* src/misc.c (open_subdir): New static function.
(fdbase_opendir): Use it.
* src/tar.c (open_searchdir_how): New var, replacing and
augmenting open_searchdir_flags. All uses changed.
* tests/extrac31.at: New file.
* tests/Makefile (TESTSUITE_AT), tests/testuite.at: Add it.
Problem and fix reported by Pavel Cahyna in
https://lists.gnu.org/r/bug-tar/2025-01/msg00000.html
* src/extract.c (extract_dir): With --no-overwrite-dir,
skip the chmod if the directory already exists.
* tests/extrac23.at (--no-overwrite-dir on empty directory):
Move the part of the test that looks at a nonempty directory ...
* tests/extrac30.at: ... to this new file, because the test now
must be run as non-root. Adjust the test to match the new behavior.
* tests/Makefile.am (TESTSUITE_AT), tests/testsuite.at: Add it.
* src/names.c (namelist_match_from): New function.
(namelist_match): Rewrite as a wrapper over it.
(register_match): New function.
(name_match)" Update all possible matches in the name list.
* tests/extrac29.at: New test.
* tests/Makefile.am: Add new test.
* tests/testsuite.at: Likewise.
* src/list.c (skim_member): Recognize directory members using
the same rules as during extraction.
* tests/skipdir.at: New testcase.
* tests/testsuite.at: Add new test.
* tests/Makefile.am: Likewise.
Detailed bug report: https://savannah.gnu.org/bugs/index.php?66774
* src/extract.c (update_interdir_set_stat): New function.
(extract_dir): If the directory already exists, check if it
has been created as intermediate directory earlier. If so,
update its delayed_set_stat data from archive.
* tests/Makefile.am: Add new testcase.
* tests/testsuite.at: Add new testcase.
* tests/extrac28.at: New file.
* tests/ckmtime.c (main): Don’t assume time_t is signed.
Avoid integer overflows (quite possible if time_t is 32 bit).
Do calculations precisely, without any rounding errors.
Bug reported in https://savannah.gnu.org/bugs/?65838.
Bug introduced by 79d1ac38c1.
* src/extract.c (make_directories): Restore second argument. This
reverts the change made in 79d1ac38c1.
(maybe_recoverable, rename_directory): Update calls to make_directories.
* tests/extrac27.at: New file.
* tests/Makefile.am: Add new test.
* tests/testsuite.at: Likewise.
This fixes https://savannah.gnu.org/bugs/?64387.
* src/exclist.c (info_attach_exclist): Always use file->flags.
(exclude_vcs_ignores): Pass flags from struct vcs_ignore_file
to excfile_add.
* tests/exclude19.at: New test.
* tests/exclude20.at: New test.
* tests/Makefile.am: Add new tests.
* tests/testsuite.at: Add new tests.
* tests/xform04.at: Skip test on macOS 12.6, which is behind the times
and doesn’t think that ⱥ (U+2C65 LATIN SMALL LETTER A WITH STROKE) is
printable.
Support upcasing and downcasing in multi-byte locales.
* gnulib.modules: Add c32rtomb, c32tolower, c32toupper,
mbrtoc32-regular.
* src/transform.c: Do not include ctype.h. Include mcel.h.
(stk, stk_init): Move up.
(run_case_conv): Return void, not char *. Append result to
stk directly; this avoids the need for a separate allocation.
All callers changed. Do not assume a single-byte locale.
* tests/xform04.at: New test.
* tests/Makefile.am (TESTSUITE_AT):
* tests/testsuite.at: Add it.
delayed_set_stat avoids inserting duplicate entries into
delayed_set_stat_head. It was doing this by scanning the entire
list.
Normally this list is small, but if --delay-directory-restore is
used (including automatically for incremental archives), this list
grows with the total number of directories in the archive.
The entire scan takes O(n) time. Extracting an archive with n
directories could therefore take O(n^2) time.
The included test uses AT_SKIP_LARGE_FILES, allowing it to optionally be
skipped. It may execute slowly on certain filesystems or disks, as it
creates thousands of directories.
There are still potentially problematic O(n) scans in
find_direct_ancestor and remove_delayed_set_stat, which this patch does
not attempt to fix.
* NEWS: Update.
* src/extract.c (delayed_set_stat_table): Create a table for O(1)
lookups of entries in the delayed_set_stat_head list. The list
remains, as tracking insertion order is important.
(dl_hash, dl_compare): New hash table helper functions.
(delay_set_stat): Create the hash table, replace the O(n) list scan
with a hash_lookup, insert new entries into the hash table.
(remove_delayed_set_stat): Also remove entry from hash table.
(apply_nonancestor_delayed_set_stat): Also remove entry from hash
table.
(extract_finish): Free the (empty) hash table.
* tests/extrac26.at: New file.
* tests/Makefile.am (TESTSUITE_AT): Include extrac26.at.
* tests/testsuite.at: Include extrac26.at.
Commit e89c7a45eb broke deletion from archives. The reported number
of bytes read is rounded to the nearest record anyway, revert the
commit and document the fact.
Reported by Ed Santiago. See
https://bugzilla.redhat.com/show_bug.cgi?id=2230127
* doc/tar.texi: Document the fact that --totals rounds up the
number of bytes reads to the nearest record.
* src/buffer.c: Revert changes.
* tests/delete06.at: Fix expected status code and stderr.
&> is a bashism and causes various tests to fail with /bin/sh as non-bash
(e.g. dash). Use the same pattern the rest of the file uses instead of &>.
Copyright-paperwork-exempt: true
* src/common.h (name): New field: is_wildcard.
(name_scan): Change protoype.
* src/delete.c: Update calls to name_scan.
* src/names.c (addname, add_starting_file): Initialize is_wildcard.
(namelist_match): Take two arguments. If second one is true, return
only exact matches.
(name_scan): Likewise. All callers updated.
(name_from_list): Skip patterns.
* src/update.c (remove_exact_name): New function.
(update_archive): Do not remove matching name, if it is a pattern.
Instead, add a new entry with the matching file name.
* tests/update04.at: New test.
* tests/Makefile.am: Add new test.
* tests/testsuite.at: Include new test.
* NEWS: Update.
* doc/tar.1: Add missing dots, use plural when necessary,
tweak a wording. Remove an incorrect observation, three times.
Add some missing articles, correct some formatting,
and expand the opaque descriptions of two options.
* doc/tar.texi: Drop a stray `cd` command from an example.
Correct two cross references, correct the paragraph
about the manpage, and unbreak a URL.
* src/names.c: Correct and shorten an error message: "non-optional"
means "mandatory", but "non-option" is what was meant. And the
phrase "in archive create or update mode" was both unneeded and
incomplete.
* tests/positional01.at: Change expected error text.
* tests/positional02.at: Likewise.
* tests/positional03.at: Likewise.
See https://savannah.gnu.org/bugs/?63823
* src/delete.c (flush_file): Break the loop on EOF.
* tests/delete06.at: New test.
* tests/Makefile.am: Add new test.
* tests/testsuite.at: Likewise.