git: b1fd95c9e247 - main - tarfs: Support paths that spill into exthdrs.

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

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

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

    tarfs: Support paths that spill into exthdrs.
    
    MFC after:      3 days
    Sponsored by:   Juniper Networks, Inc.
    Sponsored by:   Klara, Inc.
    Reviewed by:    kevans
    Differential Revision:  https://reviews.freebsd.org/D44599
---
 sys/fs/tarfs/tarfs_vfsops.c      |  7 +++++-
 tests/sys/fs/tarfs/tarfs_test.sh | 50 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+), 1 deletion(-)

diff --git a/sys/fs/tarfs/tarfs_vfsops.c b/sys/fs/tarfs/tarfs_vfsops.c
index d1af7070e706..df657fb13414 100644
--- a/sys/fs/tarfs/tarfs_vfsops.c
+++ b/sys/fs/tarfs/tarfs_vfsops.c
@@ -614,7 +614,10 @@ again:
 			value = sep + 1;
 			TARFS_DPF(ALLOC, "%s: exthdr %s=%s\n", __func__,
 			    key, value);
-			if (strcmp(key, "linkpath") == 0) {
+			if (strcmp(key, "path") == 0) {
+				name = value;
+				namelen = eol - value;
+			} else if (strcmp(key, "linkpath") == 0) {
 				link = value;
 				linklen = eol - value;
 			} else if (strcmp(key, "GNU.sparse.major") == 0) {
@@ -905,6 +908,8 @@ tarfs_alloc_mount(struct mount *mp, struct vnode *vp,
 	blknum = 0;
 	do {
 		if ((error = tarfs_alloc_one(tmp, &blknum)) != 0) {
+			printf("unsupported or corrupt tar file at %zu\n",
+			    TARFS_BLOCKSIZE * blknum);
 			goto bad;
 		}
 	} while (blknum != TAR_EOF);
diff --git a/tests/sys/fs/tarfs/tarfs_test.sh b/tests/sys/fs/tarfs/tarfs_test.sh
index 2a5dfc434201..5d3fbca2f4ee 100644
--- a/tests/sys/fs/tarfs/tarfs_test.sh
+++ b/tests/sys/fs/tarfs/tarfs_test.sh
@@ -309,6 +309,54 @@ tarfs_checksum_cleanup() {
 	tarfs_cleanup
 }
 
+atf_test_case tarfs_long_names cleanup
+tarfs_long_names_head() {
+	atf_set "descr" "Verify that tarfs supports long file names"
+	atf_set "require.user" "root"
+}
+tarfs_long_names_body() {
+	tarfs_setup
+	local a b c d e
+	a="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+	b="bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
+	c="cccccccccccccccccccccccccccccccccccccccc"
+	d="dddddddddddddddddddddddddddddddddddddddd"
+	e="eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
+	mkdir -p "${a}"
+	touch "${a}/${b}_${c}_${d}_${e}_foo"
+	ln "${a}/${b}_${c}_${d}_${e}_foo" "${a}/${b}_${c}_${d}_${e}_bar"
+	ln -s "${b}_${c}_${d}_${e}_bar" "${a}/${b}_${c}_${d}_${e}_baz"
+	tar -cf tarfs_long_names.tar "${a}"
+	atf_check mount -rt tarfs tarfs_long_names.tar "${mnt}"
+}
+tarfs_long_names_cleanup() {
+	tarfs_cleanup
+}
+
+atf_test_case tarfs_long_paths cleanup
+tarfs_long_paths_head() {
+	atf_set "descr" "Verify that tarfs supports long paths"
+	atf_set "require.user" "root"
+}
+tarfs_long_paths_body() {
+	tarfs_setup
+	local a b c d e
+	a="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+	b="bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
+	c="cccccccccccccccccccccccccccccccccccccccc"
+	d="dddddddddddddddddddddddddddddddddddddddd"
+	e="eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
+	mkdir -p "${a}/${b}/${c}/${d}/${e}"
+	touch "${a}/${b}/${c}/${d}/${e}/foo"
+	ln "${a}/${b}/${c}/${d}/${e}/foo" "${a}/${b}/${c}/${d}/${e}/bar"
+	ln -s "${b}/${c}/${d}/${e}/bar" "${a}/baz"
+	tar -cf tarfs_long_paths.tar "${a}"
+	atf_check mount -rt tarfs tarfs_long_paths.tar "${mnt}"
+}
+tarfs_long_paths_cleanup() {
+	tarfs_cleanup
+}
+
 atf_init_test_cases() {
 	atf_add_test_case tarfs_basic
 	atf_add_test_case tarfs_basic_gnu
@@ -324,4 +372,6 @@ atf_init_test_cases() {
 	atf_add_test_case tarfs_linktodir
 	atf_add_test_case tarfs_linktononexistent
 	atf_add_test_case tarfs_checksum
+	atf_add_test_case tarfs_long_names
+	atf_add_test_case tarfs_long_paths
 }