From: Tim Kientzle Date: Sun, 22 Sep 2024 23:06:34 +0000 (-0700) Subject: Clean up linkpath between entries (#2343) X-Git-Tag: v3.8.0~164 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=75cdc5947073f346d6926939d94347c8592a913b;p=thirdparty%2Flibarchive.git Clean up linkpath between entries (#2343) PR #2127 failed to clean up the linkpath storage between entries. As a result, after the first hard/symlink entry in a pax format archive, all subsequent entries would get the same link information. I'm really unsure how this bug failed to trip CI. I'll do some digging in the test suite before I merge this. Resolves #2331 , #2337 P.S. Thanks to Brad King for noting that the linkpath wasn't being managed correctly, which was a big hint for me. --- diff --git a/libarchive/archive_read_support_format_tar.c b/libarchive/archive_read_support_format_tar.c index cb103c368..ab0b20a7e 100644 --- a/libarchive/archive_read_support_format_tar.c +++ b/libarchive/archive_read_support_format_tar.c @@ -727,6 +727,7 @@ tar_read_header(struct archive_read *a, struct tar *tar, archive_string_empty(&(tar->entry_pathname)); archive_string_empty(&(tar->entry_pathname_override)); archive_string_empty(&(tar->entry_uname)); + archive_string_empty(&tar->entry_linkpath); /* Ensure format is set. */ if (a->archive.archive_format_name == NULL) { diff --git a/tar/test/test_copy.c b/tar/test/test_copy.c index fd47a6d87..27faaecba 100644 --- a/tar/test/test_copy.c +++ b/tar/test/test_copy.c @@ -190,7 +190,7 @@ create_tree(void) #define LIMIT_USTAR 100 static void -verify_tree(size_t limit) +verify_tree(size_t limit, const char *format) { char name1[260]; char name2[260]; @@ -203,6 +203,7 @@ verify_tree(size_t limit) /* Verify a file named "f/abcdef..." */ snprintf(name1, sizeof(name1), "f/%s", filenames[i]); if (i <= limit) { + failure("Verifying %s", format); assertFileExists(name1); assertFileContents(name1, (int)strlen(name1), name1); } @@ -210,6 +211,7 @@ verify_tree(size_t limit) snprintf(name2, sizeof(name2), "l/%s", filenames[i]); if (i + 2 <= limit) { /* Verify hardlink "l/abcdef..." */ + failure("Verifying %s", format); assertIsHardlink(name1, name2); /* Verify hardlink "m/abcdef..." */ name2[0] = 'm'; @@ -220,13 +222,16 @@ verify_tree(size_t limit) /* Verify symlink "s/abcdef..." */ snprintf(name1, sizeof(name1), "s/%s", filenames[i]); snprintf(name2, sizeof(name2), "../f/%s", filenames[i]); - if (strlen(name2) <= limit) + if (strlen(name2) <= limit) { + failure("Verifying %s", format); assertIsSymlink(name1, name2, 0); + } } /* Verify dir "d/abcdef...". */ snprintf(name1, sizeof(name1), "d/%s", filenames[i]); if (i + 1 <= limit) { /* +1 for trailing slash */ + failure("Verifying %s", format); if (assertIsDir(name1, -1)) { /* TODO: opendir/readdir this * directory and make sure @@ -246,7 +251,7 @@ verify_tree(size_t limit) char dir[2]; dir[0] = *dp; dir[1] = '\0'; d = opendir(dir); - failure("Unable to open dir '%s'", dir); + failure("Unable to open dir '%s' for testing %s", dir, format); if (!assert(d != NULL)) continue; while ((de = readdir(d)) != NULL) { @@ -278,25 +283,25 @@ verify_tree(size_t limit) } static void -copy_basic(void) +copy_basic(const char *extra_args, const char *name) { int r; /* NOTE: for proper operation on cygwin-1.5 and windows, the - * length of the name of the directory below, "plain", must be + * length of the name of the directory below must be * less than or equal to the length of the name of the original * directory, "original" This restriction derives from the * extremely limited pathname lengths on those platforms. */ - assertMakeDir("plain", 0775); - assertEqualInt(0, chdir("plain")); + assertMakeDir(name, 0775); + assertEqualInt(0, chdir(name)); /* * Use the tar program to create an archive. */ - r = systemf("%s cf archive -C ../original f d l m s >pack.out 2>pack.err", - testprog); - failure("Error invoking \"%s cf\"", testprog); + r = systemf("%s cf archive %s -C ../original f d l m s >pack.out 2>pack.err", + testprog, extra_args); + failure("Error invoking \"%s cf archive %s\"", testprog, extra_args); assertEqualInt(r, 0); /* Verify that nothing went to stdout or stderr. */ @@ -314,7 +319,7 @@ copy_basic(void) assertEmptyFile("unpack.err"); assertEmptyFile("unpack.out"); - verify_tree(LIMIT_NONE); + verify_tree(LIMIT_NONE, name); assertEqualInt(0, chdir("..")); } @@ -357,8 +362,8 @@ copy_ustar(void) assertEmptyFile("unpack.err"); assertEmptyFile("unpack.out"); - verify_tree(LIMIT_USTAR); - assertEqualInt(0, chdir("../..")); + verify_tree(LIMIT_USTAR, "ustar"); + assertEqualInt(0, chdir("..")); } DEFINE_TEST(test_copy) @@ -367,8 +372,11 @@ DEFINE_TEST(test_copy) create_tree(); /* Create sample files in "original" dir. */ /* Test simple "tar -c | tar -x" pipeline copy. */ - copy_basic(); + copy_basic("", "default"); /* Same, but constrain to ustar format. */ copy_ustar(); + + /* Same, but with pax format. */ + copy_basic(" --format pax", "pax"); }