git: 584e1c355ae3 - main - tarfs: Ignore global extended headers.

From: Dag-Erling Smørgrav <des_at_FreeBSD.org>
Date: Wed, 03 Apr 2024 09:59:34 UTC
The branch main has been updated by des:

URL: https://cgit.FreeBSD.org/src/commit/?id=584e1c355ae3c994331005b7196cc87a714e5317

commit 584e1c355ae3c994331005b7196cc87a714e5317
Author:     Dag-Erling Smørgrav <des@FreeBSD.org>
AuthorDate: 2024-04-03 09:55:06 +0000
Commit:     Dag-Erling Smørgrav <des@FreeBSD.org>
CommitDate: 2024-04-03 09:55:06 +0000

    tarfs: Ignore global extended headers.
    
    Previously, we would error out if we encountered a global extended
    header, because we don't know what it means.  This doesn't really
    matter though, and traditionally, tar implementations have either
    ignored them or treated them as plain files, so just ignore them.
    This allows tarfs to mount tar files created by `git archive`.
    
    MFC after:      3 days
    Sponsored by:   Juniper Networks, Inc.
    Sponsored by:   Klara, Inc.
    Reviewed by:    kevans
    Differential Revision:  https://reviews.freebsd.org/D44600
---
 sys/fs/tarfs/tarfs_vfsops.c      | 13 +++++++------
 tests/sys/fs/tarfs/tarfs_test.sh | 24 ++++++++++++++++++++++++
 2 files changed, 31 insertions(+), 6 deletions(-)

diff --git a/sys/fs/tarfs/tarfs_vfsops.c b/sys/fs/tarfs/tarfs_vfsops.c
index df657fb13414..cbc3d88eaad8 100644
--- a/sys/fs/tarfs/tarfs_vfsops.c
+++ b/sys/fs/tarfs/tarfs_vfsops.c
@@ -553,13 +553,14 @@ again:
 	TARFS_DPF(ALLOC, "%s: [%c] %zu @%jd %o %d:%d\n", __func__,
 	    hdrp->typeflag[0], sz, (intmax_t)mtime, mode, uid, gid);
 
-	/* extended header? */
+	/* global extended header? */
 	if (hdrp->typeflag[0] == TAR_TYPE_GLOBAL_EXTHDR) {
-		printf("%s: unsupported global extended header at %zu\n",
-		    __func__, (size_t)(TARFS_BLOCKSIZE * (blknum - 1)));
-		error = EFTYPE;
-		goto bad;
+		TARFS_DPF(ALLOC, "%s: %zu-byte global extended header at %zu\n",
+		    __func__, sz, TARFS_BLOCKSIZE * (blknum - 1));
+		goto skip;
 	}
+
+	/* extended header? */
 	if (hdrp->typeflag[0] == TAR_TYPE_EXTHDR) {
 		if (exthdr != NULL) {
 			TARFS_DPF(IO, "%s: multiple extended headers at %zu\n",
@@ -568,7 +569,7 @@ again:
 			goto bad;
 		}
 		/* read the contents of the exthdr */
-		TARFS_DPF(ALLOC, "%s: %zu-byte extended header at %zd\n",
+		TARFS_DPF(ALLOC, "%s: %zu-byte extended header at %zu\n",
 		    __func__, sz, TARFS_BLOCKSIZE * (blknum - 1));
 		exthdr = malloc(sz, M_TEMP, M_WAITOK);
 		res = tarfs_io_read_buf(tmp, false, exthdr,
diff --git a/tests/sys/fs/tarfs/tarfs_test.sh b/tests/sys/fs/tarfs/tarfs_test.sh
index 5d3fbca2f4ee..f1322033fbad 100644
--- a/tests/sys/fs/tarfs/tarfs_test.sh
+++ b/tests/sys/fs/tarfs/tarfs_test.sh
@@ -357,6 +357,29 @@ tarfs_long_paths_cleanup() {
 	tarfs_cleanup
 }
 
+atf_test_case tarfs_git_archive cleanup
+tarfs_git_archive_head() {
+	atf_set "descr" "Verify that tarfs supports archives created by git"
+	atf_set "require.user" "root"
+	atf_set "require.progs" "git"
+}
+tarfs_git_archive_body() {
+	tarfs_setup
+	mkdir foo
+	echo "Hello, world!" >foo/bar
+	git -C foo init --initial-branch=tarfs
+	git -C foo config user.name "File System"
+	git -C foo config user.email fs@freebsd.org
+	git -C foo add bar
+	git -C foo commit -m bar
+	git -C foo archive --output=../tarfs_git_archive.tar HEAD
+	atf_check mount -rt tarfs tarfs_git_archive.tar "${mnt}"
+	atf_check -o file:foo/bar cat "${mnt}"/bar
+}
+tarfs_git_archive_cleanup() {
+	tarfs_cleanup
+}
+
 atf_init_test_cases() {
 	atf_add_test_case tarfs_basic
 	atf_add_test_case tarfs_basic_gnu
@@ -374,4 +397,5 @@ atf_init_test_cases() {
 	atf_add_test_case tarfs_checksum
 	atf_add_test_case tarfs_long_names
 	atf_add_test_case tarfs_long_paths
+	atf_add_test_case tarfs_git_archive
 }