]> git.ipfire.org Git - thirdparty/tar.git/commitdiff
Assume directory members have size=0. master
authorSergey Poznyakoff <gray@gnu.org>
Thu, 23 Jul 2026 07:42:56 +0000 (10:42 +0300)
committerSergey Poznyakoff <gray@gnu.org>
Thu, 23 Jul 2026 07:52:03 +0000 (10:52 +0300)
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.

src/list.c
tests/skipdir.at

index cf7b41c4e1a092775ef5e221cb3f2f02134162ac..1f44136451b0ea3296b08e8945bcd9e8d56905ff 100644 (file)
@@ -1437,6 +1437,24 @@ skip_member (void)
   skim_member (false);
 }
 
+static bool
+member_is_dir (struct tar_stat_info *info, char typeflag)
+{
+  switch (typeflag)
+    {
+    case AREGTYPE:
+    case REGTYPE:
+    case CONTTYPE:
+      return info->had_trailing_slash;
+
+    case DIRTYPE:
+      return true;
+
+    default:
+      return false;
+    }
+}
+
 /* Skip the current member in the archive.
    If MUST_COPY, always copy instead of skipping.  */
 void
@@ -1450,7 +1468,8 @@ skim_member (bool must_copy)
 
       if (current_stat_info.is_sparse)
        sparse_skim_file (&current_stat_info, must_copy);
-      else
+      else if (!member_is_dir (&current_stat_info,
+                              current_header->header.typeflag))
        skim_file (current_stat_info.stat.st_size, must_copy);
 
       mv_end ();
index 79119ddf5a2d017e0dee8a1833b7b4f13c9b578d..0bc38e4f90a830e248cb371a73085965993c0fd8 100644 (file)
@@ -42,11 +42,15 @@ base64 -d < archive.in | xz -c -d > archive.tar
 AT_CHECK([tar tf archive.tar],
 [0],
 [owo1/
+owo2/
 ])
 AT_CHECK([tar vxf archive.tar],
 [0],
 [owo1/
+owo2/
 ])
 AT_CHECK([tar -xvf archive.tar --exclude owo1],
-[0])
+[0],
+[owo2/
+])
 AT_CLEANUP