From 7a2b46a89ad69a7a8265ab6c36a3b7aa7a1a63a6 Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Sun, 11 Apr 2010 14:08:36 -0400 Subject: [PATCH] Improve the testing of tar -X and try to correctly handle some odd cases. Here are some of the cases currently handled (assuming test.tar contains a single entry "file1"): $ tar xf test.tar file1 Extracts file1 with no error. $ tar xf test.tar file1 file2 Extracts file1, error because file2 was requested but not found. $ tar xf test.tar file1 'file2*' Extracts file1, error because 'file2*' pattern matched no entries. $ tar xf test.tar file1 file1 Extracts file1 with no error $ tar xf test.tar file1 'file*' Extracts file1 with no error $ tar xf test.tar --exclude=file1 Does not extract file1, no error. $ tar xf test.tar --exclude=file1 file1 Does not extract file1, no error. $ tar xf test.tar --exclude=file2 file1 Extracts file1, no error. SVN-Revision: 2229 --- libarchive_fe/matching.c | 55 +++++++++++------------ tar/test/test_option_X_upper.c | 79 +++++++++++++++++++++++++++++++++- 2 files changed, 104 insertions(+), 30 deletions(-) diff --git a/libarchive_fe/matching.c b/libarchive_fe/matching.c index f774ac773..b2aba0227 100644 --- a/libarchive_fe/matching.c +++ b/libarchive_fe/matching.c @@ -156,40 +156,41 @@ lafe_excluded(struct lafe_matching *matching, const char *pathname) if (matching == NULL) return (0); + /* Mark off any unmatched inclusions. */ + /* In particular, if a filename does appear in the archive and + * is explicitly included and excluded, then we don't report + * it as missing even though we don't extract it. + */ + matched = NULL; + for (match = matching->inclusions; match != NULL; match = match->next){ + if (match->matches == 0 + && match_inclusion(match, pathname)) { + matching->inclusions_unmatched_count--; + match->matches++; + matched = match; + } + } + /* Exclusions take priority */ for (match = matching->exclusions; match != NULL; match = match->next){ if (match_exclusion(match, pathname)) return (1); } - /* Then check for inclusions */ - matched = NULL; + /* It's not excluded and we found an inclusion above, so it's included. */ + if (matched != NULL) + return (0); + + + /* We didn't find an unmatched inclusion, check the remaining ones. */ for (match = matching->inclusions; match != NULL; match = match->next){ - if (match_inclusion(match, pathname)) { - /* - * If this pattern has never been matched, - * then we're done. - */ - if (match->matches == 0) { - match->matches++; - matching->inclusions_unmatched_count--; - return (0); - } - /* - * Otherwise, remember the match but keep checking - * in case we can tick off an unmatched pattern. - */ - matched = match; + /* We looked at previously-unmatched inclusions already. */ + if (match->matches > 0 + && match_inclusion(match, pathname)) { + match->matches++; + return (0); } } - /* - * We didn't find a pattern that had never been matched, but - * we did find a match, so count it and exit. - */ - if (matched != NULL) { - matched->matches++; - return (0); - } /* If there were inclusions, default is to exclude. */ if (matching->inclusions != NULL) @@ -219,11 +220,7 @@ match_exclusion(struct match *match, const char *pathname) static int match_inclusion(struct match *match, const char *pathname) { -#if 0 - return (lafe_pathmatch(match->pattern, pathname, 0)); -#else return (lafe_pathmatch(match->pattern, pathname, PATHMATCH_NO_ANCHOR_END)); -#endif } void diff --git a/tar/test/test_option_X_upper.c b/tar/test/test_option_X_upper.c index 5aedc5eca..1aa21fc90 100644 --- a/tar/test/test_option_X_upper.c +++ b/tar/test/test_option_X_upper.c @@ -34,7 +34,10 @@ DEFINE_TEST(test_option_X_upper) */ assertMakeFile("file1", 0644, "file1"); assertMakeFile("file2", 0644, "file2"); - assertEqualInt(0, systemf("%s -cf archive.tar file1 file2", testprog)); + assertMakeFile("file3a", 0644, "file3a"); + assertMakeFile("file4a", 0644, "file4a"); + assertEqualInt(0, + systemf("%s -cf archive.tar file1 file2 file3a file4a", testprog)); /* * Now, try extracting from the test archive with various -X usage. @@ -50,6 +53,8 @@ DEFINE_TEST(test_option_X_upper) assertFileContents("file1", 5, "file1"); assertFileContents("file2", 5, "file2"); + assertFileContents("file3a", 6, "file3a"); + assertFileContents("file4a", 6, "file4a"); assertEmptyFile("test.out"); assertEmptyFile("test.err"); assertChdir(".."); @@ -62,6 +67,78 @@ DEFINE_TEST(test_option_X_upper) systemf("%s -xf ../archive.tar -X exclusions >test.out 2>test.err", testprog)); assertFileNotExists("file1"); assertFileContents("file2", 5, "file2"); + assertFileContents("file3a", 6, "file3a"); + assertFileContents("file4a", 6, "file4a"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 3: Use -X to skip multiple files */ + assertMakeDir("test3", 0755); + assertChdir("test3"); + assertMakeFile("exclusions", 0644, "file1\nfile2\n"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar -X exclusions >test.out 2>test.err", testprog)); + assertFileNotExists("file1"); + assertFileNotExists("file2"); + assertFileContents("file3a", 6, "file3a"); + assertFileContents("file4a", 6, "file4a"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 4: Omit trailing \n */ + assertMakeDir("test4", 0755); + assertChdir("test4"); + assertMakeFile("exclusions", 0644, "file1\nfile2"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar -X exclusions >test.out 2>test.err", testprog)); + assertFileNotExists("file1"); + assertFileNotExists("file2"); + assertFileContents("file3a", 6, "file3a"); + assertFileContents("file4a", 6, "file4a"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 5: include/exclude without overlap */ + assertMakeDir("test5", 0755); + assertChdir("test5"); + assertMakeFile("exclusions", 0644, "file1\nfile2"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar -X exclusions file3a >test.out 2>test.err", testprog)); + assertFileNotExists("file1"); + assertFileNotExists("file2"); + assertFileContents("file3a", 6, "file3a"); + assertFileNotExists("file4a"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 6: Overlapping include/exclude */ + assertMakeDir("test6", 0755); + assertChdir("test6"); + assertMakeFile("exclusions", 0644, "file1\nfile2"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar -X exclusions file1 file3a >test.out 2>test.err", testprog)); + assertFileNotExists("file1"); + assertFileNotExists("file2"); + assertFileContents("file3a", 6, "file3a"); + assertFileNotExists("file4a"); + assertEmptyFile("test.out"); + assertEmptyFile("test.err"); + assertChdir(".."); + + /* Test 7: with pattern */ + assertMakeDir("test7", 0755); + assertChdir("test7"); + assertMakeFile("exclusions", 0644, "file*a\nfile1"); + assertEqualInt(0, + systemf("%s -xf ../archive.tar -X exclusions >test.out 2>test.err", testprog)); + assertFileNotExists("file1"); + assertFileContents("file2", 5, "file2"); + assertFileNotExists("file3a"); + assertFileNotExists("file4a"); assertEmptyFile("test.out"); assertEmptyFile("test.err"); assertChdir(".."); -- 2.47.3