summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am8
-rw-r--r--cpio/CMakeLists.txt2
-rw-r--r--cpio/cpio.c21
-rw-r--r--cpio/cpio.h2
-rw-r--r--cpio/test/CMakeLists.txt2
-rw-r--r--cpio/test/test_pathmatch.c243
-rw-r--r--libarchive/archive_pathmatch.h2
-rw-r--r--libarchive/test/CMakeLists.txt1
-rw-r--r--libarchive/test/test_archive_pathmatch.c244
-rw-r--r--libarchive_fe/matching.c222
-rw-r--r--libarchive_fe/matching.h14
-rw-r--r--libarchive_fe/pathmatch.c255
-rw-r--r--libarchive_fe/pathmatch.h42
-rw-r--r--tar/CMakeLists.txt2
-rw-r--r--tar/bsdtar.c93
-rw-r--r--tar/bsdtar.h8
-rw-r--r--tar/read.c74
-rw-r--r--tar/write.c110
18 files changed, 349 insertions, 996 deletions
diff --git a/Makefile.am b/Makefile.am
index 3cac4263..56ee8634 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -261,6 +261,7 @@ libarchive_test_SOURCES= \
libarchive/test/test_archive_matching_owner.c \
libarchive/test/test_archive_matching_path.c \
libarchive/test/test_archive_matching_time.c \
+ libarchive/test/test_archive_pathmatch.c \
libarchive/test/test_archive_read_close_twice.c \
libarchive/test/test_archive_read_close_twice_open_fd.c \
libarchive/test/test_archive_read_close_twice_open_filename.c \
@@ -580,9 +581,7 @@ libarchive_fe_la_SOURCES= \
libarchive_fe/line_reader.c \
libarchive_fe/line_reader.h \
libarchive_fe/matching.c \
- libarchive_fe/matching.h \
- libarchive_fe/pathmatch.c \
- libarchive_fe/pathmatch.h
+ libarchive_fe/matching.h
#
#
@@ -789,8 +788,7 @@ bsdcpio_test_SOURCES= \
cpio/test/test_option_z.c \
cpio/test/test_owner_parse.c \
cpio/test/test_passthrough_dotdot.c \
- cpio/test/test_passthrough_reverse.c \
- cpio/test/test_pathmatch.c
+ cpio/test/test_passthrough_reverse.c
bsdcpio_test_CPPFLAGS= \
-I$(top_srcdir)/libarchive -I$(top_srcdir)/libarchive_fe \
diff --git a/cpio/CMakeLists.txt b/cpio/CMakeLists.txt
index ce500b1c..98e34496 100644
--- a/cpio/CMakeLists.txt
+++ b/cpio/CMakeLists.txt
@@ -17,8 +17,6 @@ IF(ENABLE_CPIO)
../libarchive_fe/line_reader.h
../libarchive_fe/matching.c
../libarchive_fe/matching.h
- ../libarchive_fe/pathmatch.c
- ../libarchive_fe/pathmatch.h
)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../libarchive_fe)
IF(WIN32 AND NOT CYGWIN)
diff --git a/cpio/cpio.c b/cpio/cpio.c
index 025c50cf..c919d380 100644
--- a/cpio/cpio.c
+++ b/cpio/cpio.c
@@ -189,6 +189,10 @@ main(int argc, char *argv[])
cpio->bytes_per_block = 512;
cpio->filename = NULL;
+ cpio->matching = archive_matching_new();
+ if (cpio->matching == NULL)
+ lafe_errc(1, 0, "Out of memory");
+
while ((opt = cpio_getopt(cpio)) != -1) {
switch (opt) {
case '0': /* GNU convention: --null, -0 */
@@ -215,14 +219,17 @@ main(int argc, char *argv[])
cpio->extract_flags &= ~ARCHIVE_EXTRACT_NO_AUTODIR;
break;
case 'E': /* NetBSD/OpenBSD */
- lafe_include_from_file(&cpio->matching,
+ lafe_include_from_file(cpio->matching,
cpio->argument, cpio->option_null);
break;
case 'F': /* NetBSD/OpenBSD/GNU cpio */
cpio->filename = cpio->argument;
break;
case 'f': /* POSIX 1997 */
- lafe_exclude(&cpio->matching, cpio->argument);
+ if (archive_matching_exclude_pattern(cpio->matching,
+ cpio->argument) != ARCHIVE_OK)
+ lafe_errc(1, 0, "Error : %s",
+ archive_error_string(cpio->matching));
break;
case 'H': /* GNU cpio (also --format) */
cpio->format = cpio->argument;
@@ -384,7 +391,10 @@ main(int argc, char *argv[])
break;
case 'i':
while (*cpio->argv != NULL) {
- lafe_include(&cpio->matching, *cpio->argv);
+ if (archive_matching_include_pattern(cpio->matching,
+ *cpio->argv) != ARCHIVE_OK)
+ lafe_errc(1, 0, "Error : %s",
+ archive_error_string(cpio->matching));
--cpio->argc;
++cpio->argv;
}
@@ -404,6 +414,7 @@ main(int argc, char *argv[])
"Must specify at least one of -i, -o, or -p");
}
+ archive_matching_free(cpio->matching);
free_cache(cpio->gname_cache);
free_cache(cpio->uname_cache);
return (cpio->return_value);
@@ -869,7 +880,7 @@ mode_in(struct cpio *cpio)
lafe_errc(1, archive_errno(a),
"%s", archive_error_string(a));
}
- if (lafe_excluded(cpio->matching, archive_entry_pathname(entry)))
+ if (archive_matching_path_excluded_ae(cpio->matching, entry))
continue;
if (cpio->option_rename) {
destpath = cpio_rename(archive_entry_pathname(entry));
@@ -971,7 +982,7 @@ mode_list(struct cpio *cpio)
lafe_errc(1, archive_errno(a),
"%s", archive_error_string(a));
}
- if (lafe_excluded(cpio->matching, archive_entry_pathname(entry)))
+ if (archive_matching_path_excluded_ae(cpio->matching, entry))
continue;
if (cpio->verbose)
list_item_verbose(cpio, entry);
diff --git a/cpio/cpio.h b/cpio/cpio.h
index dc68e66a..9e5af674 100644
--- a/cpio/cpio.h
+++ b/cpio/cpio.h
@@ -88,7 +88,7 @@ struct cpio {
struct name_cache *gname_cache;
/* Work data. */
- struct lafe_matching *matching;
+ struct archive *matching;
char *buff;
size_t buff_size;
};
diff --git a/cpio/test/CMakeLists.txt b/cpio/test/CMakeLists.txt
index 2196c19a..a06ae049 100644
--- a/cpio/test/CMakeLists.txt
+++ b/cpio/test/CMakeLists.txt
@@ -7,7 +7,6 @@ IF(ENABLE_CPIO AND ENABLE_TEST)
SET(bsdcpio_test_SOURCES
../cmdline.c
../../libarchive_fe/err.c
- ../../libarchive_fe/pathmatch.c
main.c
test.h
test_0.c
@@ -37,7 +36,6 @@ IF(ENABLE_CPIO AND ENABLE_TEST)
test_owner_parse.c
test_passthrough_dotdot.c
test_passthrough_reverse.c
- test_pathmatch.c
)
#
diff --git a/cpio/test/test_pathmatch.c b/cpio/test/test_pathmatch.c
deleted file mode 100644
index 177c2bcc..00000000
--- a/cpio/test/test_pathmatch.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include "test.h"
-__FBSDID("$FreeBSD$");
-
-#include "pathmatch.h"
-
-/*
- * Verify that the pattern matcher implements the wildcard logic specified
- * in SUSv2 for the cpio command. This is essentially the
- * shell glob syntax:
- * * - matches any sequence of chars, including '/'
- * ? - matches any single char, including '/'
- * [...] - matches any of a set of chars, '-' specifies a range,
- * initial '!' is undefined
- *
- * The specification in SUSv2 is a bit incomplete, I assume the following:
- * Trailing '-' in [...] is not special.
- *
- * TODO: Figure out if there's a good way to extend this to handle
- * Windows paths that use '\' as a path separator. <sigh>
- */
-
-DEFINE_TEST(test_pathmatch)
-{
- assertEqualInt(1, lafe_pathmatch("a/b/c", "a/b/c", 0));
- assertEqualInt(0, lafe_pathmatch("a/b/", "a/b/c", 0));
- assertEqualInt(0, lafe_pathmatch("a/b", "a/b/c", 0));
- assertEqualInt(0, lafe_pathmatch("a/b/c", "a/b/", 0));
- assertEqualInt(0, lafe_pathmatch("a/b/c", "a/b", 0));
-
- /* Empty pattern only matches empty string. */
- assertEqualInt(1, lafe_pathmatch("","", 0));
- assertEqualInt(0, lafe_pathmatch("","a", 0));
- assertEqualInt(1, lafe_pathmatch("*","", 0));
- assertEqualInt(1, lafe_pathmatch("*","a", 0));
- assertEqualInt(1, lafe_pathmatch("*","abcd", 0));
- /* SUSv2: * matches / */
- assertEqualInt(1, lafe_pathmatch("*","abcd/efgh/ijkl", 0));
- assertEqualInt(1, lafe_pathmatch("abcd*efgh/ijkl","abcd/efgh/ijkl", 0));
- assertEqualInt(1, lafe_pathmatch("abcd***efgh/ijkl","abcd/efgh/ijkl", 0));
- assertEqualInt(1, lafe_pathmatch("abcd***/efgh/ijkl","abcd/efgh/ijkl", 0));
- assertEqualInt(0, lafe_pathmatch("?", "", 0));
- assertEqualInt(0, lafe_pathmatch("?", "\0", 0));
- assertEqualInt(1, lafe_pathmatch("?", "a", 0));
- assertEqualInt(0, lafe_pathmatch("?", "ab", 0));
- assertEqualInt(1, lafe_pathmatch("?", ".", 0));
- assertEqualInt(1, lafe_pathmatch("?", "?", 0));
- assertEqualInt(1, lafe_pathmatch("a", "a", 0));
- assertEqualInt(0, lafe_pathmatch("a", "ab", 0));
- assertEqualInt(0, lafe_pathmatch("a", "ab", 0));
- assertEqualInt(1, lafe_pathmatch("a?c", "abc", 0));
- /* SUSv2: ? matches / */
- assertEqualInt(1, lafe_pathmatch("a?c", "a/c", 0));
- assertEqualInt(1, lafe_pathmatch("a?*c*", "a/c", 0));
- assertEqualInt(1, lafe_pathmatch("*a*", "a/c", 0));
- assertEqualInt(1, lafe_pathmatch("*a*", "/a/c", 0));
- assertEqualInt(1, lafe_pathmatch("*a*", "defaaaaaaa", 0));
- assertEqualInt(0, lafe_pathmatch("a*", "defghi", 0));
- assertEqualInt(0, lafe_pathmatch("*a*", "defghi", 0));
-
- /* Character classes */
- assertEqualInt(1, lafe_pathmatch("abc[def", "abc[def", 0));
- assertEqualInt(0, lafe_pathmatch("abc[def]", "abc[def", 0));
- assertEqualInt(0, lafe_pathmatch("abc[def", "abcd", 0));
- assertEqualInt(1, lafe_pathmatch("abc[def]", "abcd", 0));
- assertEqualInt(1, lafe_pathmatch("abc[def]", "abce", 0));
- assertEqualInt(1, lafe_pathmatch("abc[def]", "abcf", 0));
- assertEqualInt(0, lafe_pathmatch("abc[def]", "abcg", 0));
- assertEqualInt(1, lafe_pathmatch("abc[d*f]", "abcd", 0));
- assertEqualInt(1, lafe_pathmatch("abc[d*f]", "abc*", 0));
- assertEqualInt(0, lafe_pathmatch("abc[d*f]", "abcdefghi", 0));
- assertEqualInt(0, lafe_pathmatch("abc[d*", "abcdefghi", 0));
- assertEqualInt(1, lafe_pathmatch("abc[d*", "abc[defghi", 0));
- assertEqualInt(1, lafe_pathmatch("abc[d-f]", "abcd", 0));
- assertEqualInt(1, lafe_pathmatch("abc[d-f]", "abce", 0));
- assertEqualInt(1, lafe_pathmatch("abc[d-f]", "abcf", 0));
- assertEqualInt(0, lafe_pathmatch("abc[d-f]", "abcg", 0));
- assertEqualInt(0, lafe_pathmatch("abc[d-fh-k]", "abca", 0));
- assertEqualInt(1, lafe_pathmatch("abc[d-fh-k]", "abcd", 0));
- assertEqualInt(1, lafe_pathmatch("abc[d-fh-k]", "abce", 0));
- assertEqualInt(1, lafe_pathmatch("abc[d-fh-k]", "abcf", 0));
- assertEqualInt(0, lafe_pathmatch("abc[d-fh-k]", "abcg", 0));
- assertEqualInt(1, lafe_pathmatch("abc[d-fh-k]", "abch", 0));
- assertEqualInt(1, lafe_pathmatch("abc[d-fh-k]", "abci", 0));
- assertEqualInt(1, lafe_pathmatch("abc[d-fh-k]", "abcj", 0));
- assertEqualInt(1, lafe_pathmatch("abc[d-fh-k]", "abck", 0));
- assertEqualInt(0, lafe_pathmatch("abc[d-fh-k]", "abcl", 0));
- assertEqualInt(0, lafe_pathmatch("abc[d-fh-k]", "abc-", 0));
-
- /* [] matches nothing, [!] is the same as ? */
- assertEqualInt(0, lafe_pathmatch("abc[]efg", "abcdefg", 0));
- assertEqualInt(0, lafe_pathmatch("abc[]efg", "abcqefg", 0));
- assertEqualInt(0, lafe_pathmatch("abc[]efg", "abcefg", 0));
- assertEqualInt(1, lafe_pathmatch("abc[!]efg", "abcdefg", 0));
- assertEqualInt(1, lafe_pathmatch("abc[!]efg", "abcqefg", 0));
- assertEqualInt(0, lafe_pathmatch("abc[!]efg", "abcefg", 0));
-
- /* I assume: Trailing '-' is non-special. */
- assertEqualInt(0, lafe_pathmatch("abc[d-fh-]", "abcl", 0));
- assertEqualInt(1, lafe_pathmatch("abc[d-fh-]", "abch", 0));
- assertEqualInt(1, lafe_pathmatch("abc[d-fh-]", "abc-", 0));
- assertEqualInt(1, lafe_pathmatch("abc[d-fh-]", "abc-", 0));
-
- /* ']' can be backslash-quoted within a character class. */
- assertEqualInt(1, lafe_pathmatch("abc[\\]]", "abc]", 0));
- assertEqualInt(1, lafe_pathmatch("abc[\\]d]", "abc]", 0));
- assertEqualInt(1, lafe_pathmatch("abc[\\]d]", "abcd", 0));
- assertEqualInt(1, lafe_pathmatch("abc[d\\]]", "abc]", 0));
- assertEqualInt(1, lafe_pathmatch("abc[d\\]]", "abcd", 0));
- assertEqualInt(1, lafe_pathmatch("abc[d]e]", "abcde]", 0));
- assertEqualInt(1, lafe_pathmatch("abc[d\\]e]", "abc]", 0));
- assertEqualInt(0, lafe_pathmatch("abc[d\\]e]", "abcd]e", 0));
- assertEqualInt(0, lafe_pathmatch("abc[d]e]", "abc]", 0));
-
- /* backslash-quoted chars can appear as either end of a range. */
- assertEqualInt(1, lafe_pathmatch("abc[\\d-f]gh", "abcegh", 0));
- assertEqualInt(0, lafe_pathmatch("abc[\\d-f]gh", "abcggh", 0));
- assertEqualInt(0, lafe_pathmatch("abc[\\d-f]gh", "abc\\gh", 0));
- assertEqualInt(1, lafe_pathmatch("abc[d-\\f]gh", "abcegh", 0));
- assertEqualInt(1, lafe_pathmatch("abc[\\d-\\f]gh", "abcegh", 0));
- assertEqualInt(1, lafe_pathmatch("abc[\\d-\\f]gh", "abcegh", 0));
- /* backslash-quoted '-' isn't special. */
- assertEqualInt(0, lafe_pathmatch("abc[d\\-f]gh", "abcegh", 0));
- assertEqualInt(1, lafe_pathmatch("abc[d\\-f]gh", "abc-gh", 0));
-
- /* Leading '!' negates a character class. */
- assertEqualInt(0, lafe_pathmatch("abc[!d]", "abcd", 0));
- assertEqualInt(1, lafe_pathmatch("abc[!d]", "abce", 0));
- assertEqualInt(1, lafe_pathmatch("abc[!d]", "abcc", 0));
- assertEqualInt(0, lafe_pathmatch("abc[!d-z]", "abcq", 0));
- assertEqualInt(1, lafe_pathmatch("abc[!d-gi-z]", "abch", 0));
- assertEqualInt(1, lafe_pathmatch("abc[!fgijkl]", "abch", 0));
- assertEqualInt(0, lafe_pathmatch("abc[!fghijkl]", "abch", 0));
-
- /* Backslash quotes next character. */
- assertEqualInt(0, lafe_pathmatch("abc\\[def]", "abc\\d", 0));
- assertEqualInt(1, lafe_pathmatch("abc\\[def]", "abc[def]", 0));
- assertEqualInt(0, lafe_pathmatch("abc\\\\[def]", "abc[def]", 0));
- assertEqualInt(0, lafe_pathmatch("abc\\\\[def]", "abc\\[def]", 0));
- assertEqualInt(1, lafe_pathmatch("abc\\\\[def]", "abc\\d", 0));
- assertEqualInt(1, lafe_pathmatch("abcd\\", "abcd\\", 0));
- assertEqualInt(0, lafe_pathmatch("abcd\\", "abcd\\[", 0));
- assertEqualInt(0, lafe_pathmatch("abcd\\", "abcde", 0));
- assertEqualInt(0, lafe_pathmatch("abcd\\[", "abcd\\", 0));
-
- /*
- * Because '.' and '/' have special meanings, we can
- * identify many equivalent paths even if they're expressed
- * differently. (But quoting a character with '\\' suppresses
- * special meanings!)
- */
- assertEqualInt(0, lafe_pathmatch("a/b/", "a/bc", 0));
- assertEqualInt(1, lafe_pathmatch("a/./b", "a/b", 0));
- assertEqualInt(0, lafe_pathmatch("a\\/./b", "a/b", 0));
- assertEqualInt(0, lafe_pathmatch("a/\\./b", "a/b", 0));
- assertEqualInt(0, lafe_pathmatch("a/.\\/b", "a/b", 0));
- assertEqualInt(0, lafe_pathmatch("a\\/\\.\\/b", "a/b", 0));
- assertEqualInt(1, lafe_pathmatch("./abc/./def/", "abc/def/", 0));
- assertEqualInt(1, lafe_pathmatch("abc/def", "./././abc/./def", 0));
- assertEqualInt(1, lafe_pathmatch("abc/def/././//", "./././abc/./def/", 0));
- assertEqualInt(1, lafe_pathmatch(".////abc/.//def", "./././abc/./def", 0));
- assertEqualInt(1, lafe_pathmatch("./abc?def/", "abc/def/", 0));
- failure("\"?./\" is not the same as \"/./\"");
- assertEqualInt(0, lafe_pathmatch("./abc?./def/", "abc/def/", 0));
- failure("Trailing '/' should match no trailing '/'");
- assertEqualInt(1, lafe_pathmatch("./abc/./def/", "abc/def", 0));
- failure("Trailing '/./' is still the same directory.");
- assertEqualInt(1, lafe_pathmatch("./abc/./def/./", "abc/def", 0));
- failure("Trailing '/.' is still the same directory.");
- assertEqualInt(1, lafe_pathmatch("./abc/./def/.", "abc/def", 0));
- assertEqualInt(1, lafe_pathmatch("./abc/./def", "abc/def/", 0));
- failure("Trailing '/./' is still the same directory.");
- assertEqualInt(1, lafe_pathmatch("./abc/./def", "abc/def/./", 0));
- failure("Trailing '/.' is still the same directory.");
- assertEqualInt(1, lafe_pathmatch("./abc*/./def", "abc/def/.", 0));
-
- /* Matches not anchored at beginning. */
- assertEqualInt(0,
- lafe_pathmatch("bcd", "abcd", PATHMATCH_NO_ANCHOR_START));
- assertEqualInt(1,
- lafe_pathmatch("abcd", "abcd", PATHMATCH_NO_ANCHOR_START));
- assertEqualInt(0,
- lafe_pathmatch("^bcd", "abcd", PATHMATCH_NO_ANCHOR_START));
- assertEqualInt(1,
- lafe_pathmatch("b/c/d", "a/b/c/d", PATHMATCH_NO_ANCHOR_START));
- assertEqualInt(0,
- lafe_pathmatch("b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_START));
- assertEqualInt(0,
- lafe_pathmatch("^b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_START));
-
- /* Matches not anchored at end. */
- assertEqualInt(0,
- lafe_pathmatch("bcd", "abcd", PATHMATCH_NO_ANCHOR_END));
- assertEqualInt(1,
- lafe_pathmatch("abcd", "abcd", PATHMATCH_NO_ANCHOR_END));
- assertEqualInt(1,
- lafe_pathmatch("abcd", "abcd/", PATHMATCH_NO_ANCHOR_END));
- assertEqualInt(1,
- lafe_pathmatch("abcd", "abcd/.", PATHMATCH_NO_ANCHOR_END));
- assertEqualInt(0,
- lafe_pathmatch("abc", "abcd", PATHMATCH_NO_ANCHOR_END));
- assertEqualInt(1,
- lafe_pathmatch("a/b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_END));
- assertEqualInt(0,
- lafe_pathmatch("a/b/c$", "a/b/c/d", PATHMATCH_NO_ANCHOR_END));
- assertEqualInt(1,
- lafe_pathmatch("a/b/c$", "a/b/c", PATHMATCH_NO_ANCHOR_END));
- assertEqualInt(1,
- lafe_pathmatch("a/b/c$", "a/b/c/", PATHMATCH_NO_ANCHOR_END));
- assertEqualInt(1,
- lafe_pathmatch("a/b/c/", "a/b/c/d", PATHMATCH_NO_ANCHOR_END));
- assertEqualInt(0,
- lafe_pathmatch("a/b/c/$", "a/b/c/d", PATHMATCH_NO_ANCHOR_END));
- assertEqualInt(1,
- lafe_pathmatch("a/b/c/$", "a/b/c/", PATHMATCH_NO_ANCHOR_END));
- assertEqualInt(1,
- lafe_pathmatch("a/b/c/$", "a/b/c", PATHMATCH_NO_ANCHOR_END));
- assertEqualInt(0,
- lafe_pathmatch("b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_END));
-}
diff --git a/libarchive/archive_pathmatch.h b/libarchive/archive_pathmatch.h
index 259599ac..e6901774 100644
--- a/libarchive/archive_pathmatch.h
+++ b/libarchive/archive_pathmatch.h
@@ -27,8 +27,10 @@
*/
#ifndef __LIBARCHIVE_BUILD
+#ifndef __LIBARCHIVE_TEST
#error This header is only to be used internally to libarchive.
#endif
+#endif
#ifndef ARCHIVE_PATHMATCH_H
#define ARCHIVE_PATHMATCH_H
diff --git a/libarchive/test/CMakeLists.txt b/libarchive/test/CMakeLists.txt
index 4c970553..479681cd 100644
--- a/libarchive/test/CMakeLists.txt
+++ b/libarchive/test/CMakeLists.txt
@@ -18,6 +18,7 @@ IF(ENABLE_TEST)
test_archive_matching_owner.c
test_archive_matching_path.c
test_archive_matching_time.c
+ test_archive_pathmatch.c
test_archive_read_close_twice.c
test_archive_read_close_twice_open_fd.c
test_archive_read_close_twice_open_filename.c
diff --git a/libarchive/test/test_archive_pathmatch.c b/libarchive/test/test_archive_pathmatch.c
new file mode 100644
index 00000000..fed6ad78
--- /dev/null
+++ b/libarchive/test/test_archive_pathmatch.c
@@ -0,0 +1,244 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+#define __LIBARCHIVE_TEST
+#include "archive_pathmatch.h"
+
+/*
+ * Verify that the pattern matcher implements the wildcard logic specified
+ * in SUSv2 for the cpio command. This is essentially the
+ * shell glob syntax:
+ * * - matches any sequence of chars, including '/'
+ * ? - matches any single char, including '/'
+ * [...] - matches any of a set of chars, '-' specifies a range,
+ * initial '!' is undefined
+ *
+ * The specification in SUSv2 is a bit incomplete, I assume the following:
+ * Trailing '-' in [...] is not special.
+ *
+ * TODO: Figure out if there's a good way to extend this to handle
+ * Windows paths that use '\' as a path separator. <sigh>
+ */
+
+DEFINE_TEST(test_archive_pathmatch)
+{
+ assertEqualInt(1, archive_pathmatch("a/b/c", "a/b/c", 0));
+ assertEqualInt(0, archive_pathmatch("a/b/", "a/b/c", 0));
+ assertEqualInt(0, archive_pathmatch("a/b", "a/b/c", 0));
+ assertEqualInt(0, archive_pathmatch("a/b/c", "a/b/", 0));
+ assertEqualInt(0, archive_pathmatch("a/b/c", "a/b", 0));
+
+ /* Empty pattern only matches empty string. */
+ assertEqualInt(1, archive_pathmatch("","", 0));
+ assertEqualInt(0, archive_pathmatch("","a", 0));
+ assertEqualInt(1, archive_pathmatch("*","", 0));
+ assertEqualInt(1, archive_pathmatch("*","a", 0));
+ assertEqualInt(1, archive_pathmatch("*","abcd", 0));
+ /* SUSv2: * matches / */
+ assertEqualInt(1, archive_pathmatch("*","abcd/efgh/ijkl", 0));
+ assertEqualInt(1, archive_pathmatch("abcd*efgh/ijkl","abcd/efgh/ijkl", 0));
+ assertEqualInt(1, archive_pathmatch("abcd***efgh/ijkl","abcd/efgh/ijkl", 0));
+ assertEqualInt(1, archive_pathmatch("abcd***/efgh/ijkl","abcd/efgh/ijkl", 0));
+ assertEqualInt(0, archive_pathmatch("?", "", 0));
+ assertEqualInt(0, archive_pathmatch("?", "\0", 0));
+ assertEqualInt(1, archive_pathmatch("?", "a", 0));
+ assertEqualInt(0, archive_pathmatch("?", "ab", 0));
+ assertEqualInt(1, archive_pathmatch("?", ".", 0));
+ assertEqualInt(1, archive_pathmatch("?", "?", 0));
+ assertEqualInt(1, archive_pathmatch("a", "a", 0));
+ assertEqualInt(0, archive_pathmatch("a", "ab", 0));
+ assertEqualInt(0, archive_pathmatch("a", "ab", 0));
+ assertEqualInt(1, archive_pathmatch("a?c", "abc", 0));
+ /* SUSv2: ? matches / */
+ assertEqualInt(1, archive_pathmatch("a?c", "a/c", 0));
+ assertEqualInt(1, archive_pathmatch("a?*c*", "a/c", 0));
+ assertEqualInt(1, archive_pathmatch("*a*", "a/c", 0));
+ assertEqualInt(1, archive_pathmatch("*a*", "/a/c", 0));
+ assertEqualInt(1, archive_pathmatch("*a*", "defaaaaaaa", 0));
+ assertEqualInt(0, archive_pathmatch("a*", "defghi", 0));
+ assertEqualInt(0, archive_pathmatch("*a*", "defghi", 0));
+
+ /* Character classes */
+ assertEqualInt(1, archive_pathmatch("abc[def", "abc[def", 0));
+ assertEqualInt(0, archive_pathmatch("abc[def]", "abc[def", 0));
+ assertEqualInt(0, archive_pathmatch("abc[def", "abcd", 0));
+ assertEqualInt(1, archive_pathmatch("abc[def]", "abcd", 0));
+ assertEqualInt(1, archive_pathmatch("abc[def]", "abce", 0));
+ assertEqualInt(1, archive_pathmatch("abc[def]", "abcf", 0));
+ assertEqualInt(0, archive_pathmatch("abc[def]", "abcg", 0));
+ assertEqualInt(1, archive_pathmatch("abc[d*f]", "abcd", 0));
+ assertEqualInt(1, archive_pathmatch("abc[d*f]", "abc*", 0));
+ assertEqualInt(0, archive_pathmatch("abc[d*f]", "abcdefghi", 0));
+ assertEqualInt(0, archive_pathmatch("abc[d*", "abcdefghi", 0));
+ assertEqualInt(1, archive_pathmatch("abc[d*", "abc[defghi", 0));
+ assertEqualInt(1, archive_pathmatch("abc[d-f]", "abcd", 0));
+ assertEqualInt(1, archive_pathmatch("abc[d-f]", "abce", 0));
+ assertEqualInt(1, archive_pathmatch("abc[d-f]", "abcf", 0));
+ assertEqualInt(0, archive_pathmatch("abc[d-f]", "abcg", 0));
+ assertEqualInt(0, archive_pathmatch("abc[d-fh-k]", "abca", 0));
+ assertEqualInt(1, archive_pathmatch("abc[d-fh-k]", "abcd", 0));
+ assertEqualInt(1, archive_pathmatch("abc[d-fh-k]", "abce", 0));
+ assertEqualInt(1, archive_pathmatch("abc[d-fh-k]", "abcf", 0));
+ assertEqualInt(0, archive_pathmatch("abc[d-fh-k]", "abcg", 0));
+ assertEqualInt(1, archive_pathmatch("abc[d-fh-k]", "abch", 0));
+ assertEqualInt(1, archive_pathmatch("abc[d-fh-k]", "abci", 0));
+ assertEqualInt(1, archive_pathmatch("abc[d-fh-k]", "abcj", 0));
+ assertEqualInt(1, archive_pathmatch("abc[d-fh-k]", "abck", 0));
+ assertEqualInt(0, archive_pathmatch("abc[d-fh-k]", "abcl", 0));
+ assertEqualInt(0, archive_pathmatch("abc[d-fh-k]", "abc-", 0));
+
+ /* [] matches nothing, [!] is the same as ? */
+ assertEqualInt(0, archive_pathmatch("abc[]efg", "abcdefg", 0));
+ assertEqualInt(0, archive_pathmatch("abc[]efg", "abcqefg", 0));
+ assertEqualInt(0, archive_pathmatch("abc[]efg", "abcefg", 0));
+ assertEqualInt(1, archive_pathmatch("abc[!]efg", "abcdefg", 0));
+ assertEqualInt(1, archive_pathmatch("abc[!]efg", "abcqefg", 0));
+ assertEqualInt(0, archive_pathmatch("abc[!]efg", "abcefg", 0));
+
+ /* I assume: Trailing '-' is non-special. */
+ assertEqualInt(0, archive_pathmatch("abc[d-fh-]", "abcl", 0));
+ assertEqualInt(1, archive_pathmatch("abc[d-fh-]", "abch", 0));
+ assertEqualInt(1, archive_pathmatch("abc[d-fh-]", "abc-", 0));
+ assertEqualInt(1, archive_pathmatch("abc[d-fh-]", "abc-", 0));
+
+ /* ']' can be backslash-quoted within a character class. */
+ assertEqualInt(1, archive_pathmatch("abc[\\]]", "abc]", 0));
+ assertEqualInt(1, archive_pathmatch("abc[\\]d]", "abc]", 0));
+ assertEqualInt(1, archive_pathmatch("abc[\\]d]", "abcd", 0));
+ assertEqualInt(1, archive_pathmatch("abc[d\\]]", "abc]", 0));
+ assertEqualInt(1, archive_pathmatch("abc[d\\]]", "abcd", 0));
+ assertEqualInt(1, archive_pathmatch("abc[d]e]", "abcde]", 0));
+ assertEqualInt(1, archive_pathmatch("abc[d\\]e]", "abc]", 0));
+ assertEqualInt(0, archive_pathmatch("abc[d\\]e]", "abcd]e", 0));
+ assertEqualInt(0, archive_pathmatch("abc[d]e]", "abc]", 0));
+
+ /* backslash-quoted chars can appear as either end of a range. */
+ assertEqualInt(1, archive_pathmatch("abc[\\d-f]gh", "abcegh", 0));
+ assertEqualInt(0, archive_pathmatch("abc[\\d-f]gh", "abcggh", 0));
+ assertEqualInt(0, archive_pathmatch("abc[\\d-f]gh", "abc\\gh", 0));
+ assertEqualInt(1, archive_pathmatch("abc[d-\\f]gh", "abcegh", 0));
+ assertEqualInt(1, archive_pathmatch("abc[\\d-\\f]gh", "abcegh", 0));
+ assertEqualInt(1, archive_pathmatch("abc[\\d-\\f]gh", "abcegh", 0));
+ /* backslash-quoted '-' isn't special. */
+ assertEqualInt(0, archive_pathmatch("abc[d\\-f]gh", "abcegh", 0));
+ assertEqualInt(1, archive_pathmatch("abc[d\\-f]gh", "abc-gh", 0));
+
+ /* Leading '!' negates a character class. */
+ assertEqualInt(0, archive_pathmatch("abc[!d]", "abcd", 0));
+ assertEqualInt(1, archive_pathmatch("abc[!d]", "abce", 0));
+ assertEqualInt(1, archive_pathmatch("abc[!d]", "abcc", 0));
+ assertEqualInt(0, archive_pathmatch("abc[!d-z]", "abcq", 0));
+ assertEqualInt(1, archive_pathmatch("abc[!d-gi-z]", "abch", 0));
+ assertEqualInt(1, archive_pathmatch("abc[!fgijkl]", "abch", 0));
+ assertEqualInt(0, archive_pathmatch("abc[!fghijkl]", "abch", 0));
+
+ /* Backslash quotes next character. */
+ assertEqualInt(0, archive_pathmatch("abc\\[def]", "abc\\d", 0));
+ assertEqualInt(1, archive_pathmatch("abc\\[def]", "abc[def]", 0));
+ assertEqualInt(0, archive_pathmatch("abc\\\\[def]", "abc[def]", 0));
+ assertEqualInt(0, archive_pathmatch("abc\\\\[def]", "abc\\[def]", 0));
+ assertEqualInt(1, archive_pathmatch("abc\\\\[def]", "abc\\d", 0));
+ assertEqualInt(1, archive_pathmatch("abcd\\", "abcd\\", 0));
+ assertEqualInt(0, archive_pathmatch("abcd\\", "abcd\\[", 0));
+ assertEqualInt(0, archive_pathmatch("abcd\\", "abcde", 0));
+ assertEqualInt(0, archive_pathmatch("abcd\\[", "abcd\\", 0));
+
+ /*
+ * Because '.' and '/' have special meanings, we can
+ * identify many equivalent paths even if they're expressed
+ * differently. (But quoting a character with '\\' suppresses
+ * special meanings!)
+ */
+ assertEqualInt(0, archive_pathmatch("a/b/", "a/bc", 0));
+ assertEqualInt(1, archive_pathmatch("a/./b", "a/b", 0));
+ assertEqualInt(0, archive_pathmatch("a\\/./b", "a/b", 0));
+ assertEqualInt(0, archive_pathmatch("a/\\./b", "a/b", 0));
+ assertEqualInt(0, archive_pathmatch("a/.\\/b", "a/b", 0));
+ assertEqualInt(0, archive_pathmatch("a\\/\\.\\/b", "a/b", 0));
+ assertEqualInt(1, archive_pathmatch("./abc/./def/", "abc/def/", 0));
+ assertEqualInt(1, archive_pathmatch("abc/def", "./././abc/./def", 0));
+ assertEqualInt(1, archive_pathmatch("abc/def/././//", "./././abc/./def/", 0));
+ assertEqualInt(1, archive_pathmatch(".////abc/.//def", "./././abc/./def", 0));
+ assertEqualInt(1, archive_pathmatch("./abc?def/", "abc/def/", 0));
+ failure("\"?./\" is not the same as \"/./\"");
+ assertEqualInt(0, archive_pathmatch("./abc?./def/", "abc/def/", 0));
+ failure("Trailing '/' should match no trailing '/'");
+ assertEqualInt(1, archive_pathmatch("./abc/./def/", "abc/def", 0));
+ failure("Trailing '/./' is still the same directory.");
+ assertEqualInt(1, archive_pathmatch("./abc/./def/./", "abc/def", 0));
+ failure("Trailing '/.' is still the same directory.");
+ assertEqualInt(1, archive_pathmatch("./abc/./def/.", "abc/def", 0));
+ assertEqualInt(1, archive_pathmatch("./abc/./def", "abc/def/", 0));
+ failure("Trailing '/./' is still the same directory.");
+ assertEqualInt(1, archive_pathmatch("./abc/./def", "abc/def/./", 0));
+ failure("Trailing '/.' is still the same directory.");
+ assertEqualInt(1, archive_pathmatch("./abc*/./def", "abc/def/.", 0));
+
+ /* Matches not anchored at beginning. */
+ assertEqualInt(0,
+ archive_pathmatch("bcd", "abcd", PATHMATCH_NO_ANCHOR_START));
+ assertEqualInt(1,
+ archive_pathmatch("abcd", "abcd", PATHMATCH_NO_ANCHOR_START));
+ assertEqualInt(0,
+ archive_pathmatch("^bcd", "abcd", PATHMATCH_NO_ANCHOR_START));
+ assertEqualInt(1,
+ archive_pathmatch("b/c/d", "a/b/c/d", PATHMATCH_NO_ANCHOR_START));
+ assertEqualInt(0,
+ archive_pathmatch("b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_START));
+ assertEqualInt(0,
+ archive_pathmatch("^b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_START));
+
+ /* Matches not anchored at end. */
+ assertEqualInt(0,
+ archive_pathmatch("bcd", "abcd", PATHMATCH_NO_ANCHOR_END));
+ assertEqualInt(1,
+ archive_pathmatch("abcd", "abcd", PATHMATCH_NO_ANCHOR_END));
+ assertEqualInt(1,
+ archive_pathmatch("abcd", "abcd/", PATHMATCH_NO_ANCHOR_END));
+ assertEqualInt(1,
+ archive_pathmatch("abcd", "abcd/.", PATHMATCH_NO_ANCHOR_END));
+ assertEqualInt(0,
+ archive_pathmatch("abc", "abcd", PATHMATCH_NO_ANCHOR_END));
+ assertEqualInt(1,
+ archive_pathmatch("a/b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_END));
+ assertEqualInt(0,
+ archive_pathmatch("a/b/c$", "a/b/c/d", PATHMATCH_NO_ANCHOR_END));
+ assertEqualInt(1,
+ archive_pathmatch("a/b/c$", "a/b/c", PATHMATCH_NO_ANCHOR_END));
+ assertEqualInt(1,
+ archive_pathmatch("a/b/c$", "a/b/c/", PATHMATCH_NO_ANCHOR_END));
+ assertEqualInt(1,
+ archive_pathmatch("a/b/c/", "a/b/c/d", PATHMATCH_NO_ANCHOR_END));
+ assertEqualInt(0,
+ archive_pathmatch("a/b/c/$", "a/b/c/d", PATHMATCH_NO_ANCHOR_END));
+ assertEqualInt(1,
+ archive_pathmatch("a/b/c/$", "a/b/c/", PATHMATCH_NO_ANCHOR_END));
+ assertEqualInt(1,
+ archive_pathmatch("a/b/c/$", "a/b/c", PATHMATCH_NO_ANCHOR_END));
+ assertEqualInt(0,
+ archive_pathmatch("b/c", "a/b/c/d", PATHMATCH_NO_ANCHOR_END));
+}
diff --git a/libarchive_fe/matching.c b/libarchive_fe/matching.c
index 4ba60822..be454b5b 100644
--- a/libarchive_fe/matching.c
+++ b/libarchive_fe/matching.c
@@ -29,61 +29,17 @@ __FBSDID("$FreeBSD: src/usr.bin/cpio/matching.c,v 1.2 2008/06/21 02:20:20 kientz
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
#include "err.h"
#include "line_reader.h"
#include "matching.h"
-#include "pathmatch.h"
-
-struct match {
- struct match *next;
- int matches;
- char pattern[1];
-};
-
-struct lafe_matching {
- struct match *exclusions;
- int exclusions_count;
- struct match *inclusions;
- int inclusions_count;
- int inclusions_unmatched_count;
-};
-
-static void add_pattern(struct match **list, const char *pattern);
-static void initialize_matching(struct lafe_matching **);
-static int match_exclusion(struct match *, const char *pathname);
-static int match_inclusion(struct match *, const char *pathname);
-
-/*
- * The matching logic here needs to be re-thought. I started out to
- * try to mimic gtar's matching logic, but it's not entirely
- * consistent. In particular 'tar -t' and 'tar -x' interpret patterns
- * on the command line as anchored, but --exclude doesn't.
- */
/*
* Utility functions to manage exclusion/inclusion patterns
*/
int
-lafe_exclude(struct lafe_matching **matching, const char *pattern)
-{
-
- if (*matching == NULL)
- initialize_matching(matching);
- add_pattern(&((*matching)->exclusions), pattern);
- (*matching)->exclusions_count++;
- return (0);
-}
-
-int
-lafe_exclude_from_file(struct lafe_matching **matching, const char *pathname)
+lafe_exclude_from_file(struct archive *matching, const char *pathname)
{
struct lafe_line_reader *lr;
const char *p;
@@ -91,27 +47,16 @@ lafe_exclude_from_file(struct lafe_matching **matching, const char *pathname)
lr = lafe_line_reader(pathname, 0);
while ((p = lafe_line_reader_next(lr)) != NULL) {
- if (lafe_exclude(matching, p) != 0)
- ret = -1;
+ ret = archive_matching_exclude_pattern(matching, p);
+ if (ret == ARCHIVE_FATAL)
+ lafe_errc(1, errno, "Out of memory");
}
lafe_line_reader_free(lr);
return (ret);
}
int
-lafe_include(struct lafe_matching **matching, const char *pattern)
-{
-
- if (*matching == NULL)
- initialize_matching(matching);
- add_pattern(&((*matching)->inclusions), pattern);
- (*matching)->inclusions_count++;
- (*matching)->inclusions_unmatched_count++;
- return (0);
-}
-
-int
-lafe_include_from_file(struct lafe_matching **matching, const char *pathname,
+lafe_include_from_file(struct archive *matching, const char *pathname,
int nullSeparator)
{
struct lafe_line_reader *lr;
@@ -120,162 +65,11 @@ lafe_include_from_file(struct lafe_matching **matching, const char *pathname,
lr = lafe_line_reader(pathname, nullSeparator);
while ((p = lafe_line_reader_next(lr)) != NULL) {
- if (lafe_include(matching, p) != 0)
- ret = -1;
+ ret = archive_matching_include_pattern(matching, p);
+ if (ret == ARCHIVE_FATAL)
+ lafe_errc(1, errno, "Out of memory");
}
lafe_line_reader_free(lr);
return (ret);
}
-static void
-add_pattern(struct match **list, const char *pattern)
-{
- struct match *match;
- size_t len;
-
- len = strlen(pattern);
- match = malloc(sizeof(*match) + len + 1);
- if (match == NULL)
- lafe_errc(1, errno, "Out of memory");
- strcpy(match->pattern, pattern);
- /* Both "foo/" and "foo" should match "foo/bar". */
- if (len && match->pattern[len - 1] == '/')
- match->pattern[len - 1] = '\0';
- match->next = *list;
- *list = match;
- match->matches = 0;
-}
-
-
-int
-lafe_excluded(struct lafe_matching *matching, const char *pathname)
-{
- struct match *match;
- struct match *matched;
-
- 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);
- }
-
- /* 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){
- /* We looked at previously-unmatched inclusions already. */
- if (match->matches > 0
- && match_inclusion(match, pathname)) {
- match->matches++;
- return (0);
- }
- }
-
- /* If there were inclusions, default is to exclude. */
- if (matching->inclusions != NULL)
- return (1);
-
- /* No explicit inclusions, default is to match. */
- return (0);
-}
-
-/*
- * This is a little odd, but it matches the default behavior of
- * gtar. In particular, 'a*b' will match 'foo/a1111/222b/bar'
- *
- */
-static int
-match_exclusion(struct match *match, const char *pathname)
-{
- return (lafe_pathmatch(match->pattern,
- pathname,
- PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END));
-}
-
-/*
- * Again, mimic gtar: inclusions are always anchored (have to match
- * the beginning of the path) even though exclusions are not anchored.
- */
-static int
-match_inclusion(struct match *match, const char *pathname)
-{
- return (lafe_pathmatch(match->pattern, pathname, PATHMATCH_NO_ANCHOR_END));
-}
-
-void
-lafe_cleanup_exclusions(struct lafe_matching **matching)
-{
- struct match *p, *q;
-
- if (*matching == NULL)
- return;
-
- for (p = (*matching)->inclusions; p != NULL; ) {
- q = p;
- p = p->next;
- free(q);
- }
-
- for (p = (*matching)->exclusions; p != NULL; ) {
- q = p;
- p = p->next;
- free(q);
- }
-
- free(*matching);
- *matching = NULL;
-}
-
-static void
-initialize_matching(struct lafe_matching **matching)
-{
- *matching = calloc(sizeof(**matching), 1);
- if (*matching == NULL)
- lafe_errc(1, errno, "No memory");
-}
-
-int
-lafe_unmatched_inclusions(struct lafe_matching *matching)
-{
-
- if (matching == NULL)
- return (0);
- return (matching->inclusions_unmatched_count);
-}
-
-int
-lafe_unmatched_inclusions_warn(struct lafe_matching *matching, const char *msg)
-{
- struct match *p;
-
- if (matching == NULL)
- return (0);
-
- for (p = matching->inclusions; p != NULL; p = p->next) {
- if (p->matches == 0)
- lafe_warnc(0, "%s: %s", p->pattern, msg);
- }
-
- return (matching->inclusions_unmatched_count);
-}
diff --git a/libarchive_fe/matching.h b/libarchive_fe/matching.h
index f4edebd4..4c174a84 100644
--- a/libarchive_fe/matching.h
+++ b/libarchive_fe/matching.h
@@ -29,18 +29,10 @@
#ifndef MATCHING_H
#define MATCHING_H
-struct lafe_matching;
+#include "archive.h"
-int lafe_exclude(struct lafe_matching **matching, const char *pattern);
-int lafe_exclude_from_file(struct lafe_matching **matching,
- const char *pathname);
-int lafe_include(struct lafe_matching **matching, const char *pattern);
-int lafe_include_from_file(struct lafe_matching **matching,
+int lafe_exclude_from_file(struct archive *, const char *pathname);
+int lafe_include_from_file(struct archive *,
const char *pathname, int nullSeparator);
-int lafe_excluded(struct lafe_matching *, const char *pathname);
-void lafe_cleanup_exclusions(struct lafe_matching **);
-int lafe_unmatched_inclusions(struct lafe_matching *);
-int lafe_unmatched_inclusions_warn(struct lafe_matching *, const char *msg);
-
#endif
diff --git a/libarchive_fe/pathmatch.c b/libarchive_fe/pathmatch.c
deleted file mode 100644
index ff8a1050..00000000
--- a/libarchive_fe/pathmatch.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer
- * in this position and unchanged.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "lafe_platform.h"
-__FBSDID("$FreeBSD$");
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include "pathmatch.h"
-
-/*
- * Check whether a character 'c' is matched by a list specification [...]:
- * * Leading '!' or '^' negates the class.
- * * <char>-<char> is a range of characters
- * * \<char> removes any special meaning for <char>
- *
- * Some interesting boundary cases:
- * a-d-e is one range (a-d) followed by two single characters - and e.
- * \a-\d is same as a-d
- * a\-d is three single characters: a, d, -
- * Trailing - is not special (so [a-] is two characters a and -).
- * Initial - is not special ([a-] is same as [-a] is same as [\\-a])
- * This function never sees a trailing \.
- * [] always fails
- * [!] always succeeds
- */
-static int
-pm_list(const char *start, const char *end, const char c, int flags)
-{
- const char *p = start;
- char rangeStart = '\0', nextRangeStart;
- int match = 1, nomatch = 0;
-
- /* This will be used soon... */
- (void)flags; /* UNUSED */
-
- /* If this is a negated class, return success for nomatch. */
- if ((*p == '!' || *p == '^') && p < end) {
- match = 0;
- nomatch = 1;
- ++p;
- }
-
- while (p < end) {
- nextRangeStart = '\0';
- switch (*p) {
- case '-':
- /* Trailing or initial '-' is not special. */
- if ((rangeStart == '\0') || (p == end - 1)) {
- if (*p == c)
- return (match);
- } else {
- char rangeEnd = *++p;
- if (rangeEnd == '\\')
- rangeEnd = *++p;
- if ((rangeStart <= c) && (c <= rangeEnd))
- return (match);
- }
- break;
- case '\\':
- ++p;
- /* Fall through */
- default:
- if (*p == c)
- return (match);
- nextRangeStart = *p; /* Possible start of range. */
- }
- rangeStart = nextRangeStart;
- ++p;
- }
- return (nomatch);
-}
-
-/*
- * If s is pointing to "./", ".//", "./././" or the like, skip it.
- */
-static const char *
-pm_slashskip(const char *s) {
- while ((*s == '/')
- || (s[0] == '.' && s[1] == '/')
- || (s[0] == '.' && s[1] == '\0'))
- ++s;
- return (s);
-}
-
-static int
-pm(const char *p, const char *s, int flags)
-{
- const char *end;
-
- /*
- * Ignore leading './', './/', '././', etc.
- */
- if (s[0] == '.' && s[1] == '/')
- s = pm_slashskip(s + 1);
- if (p[0] == '.' && p[1] == '/')
- p = pm_slashskip(p + 1);
-
- for (;;) {
- switch (*p) {
- case '\0':
- if (s[0] == '/') {
- if (flags & PATHMATCH_NO_ANCHOR_END)
- return (1);
- /* "dir" == "dir/" == "dir/." */
- s = pm_slashskip(s);
- }
- return (*s == '\0');
- case '?':
- /* ? always succeeds, unless we hit end of 's' */
- if (*s == '\0')
- return (0);
- break;
- case '*':
- /* "*" == "**" == "***" ... */
- while (*p == '*')
- ++p;
- /* Trailing '*' always succeeds. */
- if (*p == '\0')
- return (1);
- while (*s) {
- if (lafe_pathmatch(p, s, flags))
- return (1);
- ++s;
- }
- return (0);
- case '[':
- /*
- * Find the end of the [...] character class,
- * ignoring \] that might occur within the class.
- */
- end = p + 1;
- while (*end != '\0' && *end != ']') {
- if (*end == '\\' && end[1] != '\0')
- ++end;
- ++end;
- }
- if (*end == ']') {
- /* We found [...], try to match it. */
- if (!pm_list(p + 1, end, *s, flags))
- return (0);
- p = end; /* Jump to trailing ']' char. */
- break;
- } else
- /* No final ']', so just match '['. */
- if (*p != *s)
- return (0);
- break;
- case '\\':
- /* Trailing '\\' matches itself. */
- if (p[1] == '\0') {
- if (*s != '\\')
- return (0);
- } else {
- ++p;
- if (*p != *s)
- return (0);
- }
- break;
- case '/':
- if (*s != '/' && *s != '\0')
- return (0);
- /* Note: pattern "/\./" won't match "/";
- * pm_slashskip() correctly stops at backslash. */
- p = pm_slashskip(p);
- s = pm_slashskip(s);
- if (*p == '\0' && (flags & PATHMATCH_NO_ANCHOR_END))
- return (1);
- --p; /* Counteract the increment below. */
- --s;
- break;
- case '$':
- /* '$' is special only at end of pattern and only
- * if PATHMATCH_NO_ANCHOR_END is specified. */
- if (p[1] == '\0' && (flags & PATHMATCH_NO_ANCHOR_END)){
- /* "dir" == "dir/" == "dir/." */
- return (*pm_slashskip(s) == '\0');
- }
- /* Otherwise, '$' is not special. */
- /* FALL THROUGH */
- default:
- if (*p != *s)
- return (0);
- break;
- }
- ++p;
- ++s;
- }
-}
-
-/* Main entry point. */
-int
-lafe_pathmatch(const char *p, const char *s, int flags)
-{
- /* Empty pattern only matches the empty string. */
- if (p == NULL || *p == '\0')
- return (s == NULL || *s == '\0');
-
- /* Leading '^' anchors the start of the pattern. */
- if (*p == '^') {
- ++p;
- flags &= ~PATHMATCH_NO_ANCHOR_START;
- }
-
- if (*p == '/' && *s != '/')
- return (0);
-
- /* Certain patterns and file names anchor implicitly. */
- if (*p == '*' || *p == '/' || *p == '/') {
- while (*p == '/')
- ++p;
- while (*s == '/')
- ++s;
- return (pm(p, s, flags));
- }
-
- /* If start is unanchored, try to match start of each path element. */
- if (flags & PATHMATCH_NO_ANCHOR_START) {
- for ( ; s != NULL; s = strchr(s, '/')) {
- if (*s == '/')
- s++;
- if (pm(p, s, flags))
- return (1);
- }
- return (0);
- }
-
- /* Default: Match from beginning. */
- return (pm(p, s, flags));
-}
diff --git a/libarchive_fe/pathmatch.h b/libarchive_fe/pathmatch.h
deleted file mode 100644
index a92f3aef..00000000
--- a/libarchive_fe/pathmatch.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*-
- * Copyright (c) 2003-2007 Tim Kientzle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer
- * in this position and unchanged.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef LAFE_PATHMATCH_H
-#define LAFE_PATHMATCH_H
-
-/* Don't anchor at beginning unless the pattern starts with "^" */
-#define PATHMATCH_NO_ANCHOR_START 1
-/* Don't anchor at end unless the pattern ends with "$" */
-#define PATHMATCH_NO_ANCHOR_END 2
-
-/* Note that "^" and "$" are not special unless you set the corresponding
- * flag above. */
-
-int lafe_pathmatch(const char *p, const char *s, int flags);
-
-#endif
diff --git a/tar/CMakeLists.txt b/tar/CMakeLists.txt
index b3b931e9..39b336cd 100644
--- a/tar/CMakeLists.txt
+++ b/tar/CMakeLists.txt
@@ -22,8 +22,6 @@ IF(ENABLE_TAR)
../libarchive_fe/line_reader.h
../libarchive_fe/matching.c
../libarchive_fe/matching.h
- ../libarchive_fe/pathmatch.c
- ../libarchive_fe/pathmatch.h
)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../libarchive_fe)
IF(WIN32 AND NOT CYGWIN)
diff --git a/tar/bsdtar.c b/tar/bsdtar.c
index 5f89959c..a2d4617f 100644
--- a/tar/bsdtar.c
+++ b/tar/bsdtar.c
@@ -121,7 +121,6 @@ need_report(void)
/* External function to parse a date/time string */
time_t get_date(time_t, const char *);
-static int get_filetime(const char *, int, time_t *, long *);
static void long_help(void);
static void only_mode(struct bsdtar *, const char *opt,
const char *valid);
@@ -247,6 +246,9 @@ main(int argc, char **argv)
if (getenv(COPYFILE_DISABLE_VAR))
bsdtar->enable_copyfile = 0;
#endif
+ bsdtar->matching = archive_matching_new();
+ if (bsdtar->matching == NULL)
+ lafe_errc(1, errno, "Out of memory");
bsdtar->argv = argv;
bsdtar->argc = argc;
@@ -291,7 +293,8 @@ main(int argc, char **argv)
bsdtar->enable_copyfile = 0;
break;
case OPTION_EXCLUDE: /* GNU tar */
- if (lafe_exclude(&bsdtar->matching, bsdtar->argument))
+ if (archive_matching_exclude_pattern(
+ bsdtar->matching, bsdtar->argument) != ARCHIVE_OK)
lafe_errc(1, 0,
"Couldn't exclude %s\n", bsdtar->argument);
break;
@@ -342,7 +345,8 @@ main(int argc, char **argv)
* no one else needs this to filter entries
* when transforming archives.
*/
- if (lafe_include(&bsdtar->matching, bsdtar->argument))
+ if (archive_matching_include_pattern(bsdtar->matching,
+ bsdtar->argument) != ARCHIVE_OK)
lafe_errc(1, 0,
"Failed to add %s to inclusion list",
bsdtar->argument);
@@ -396,30 +400,28 @@ main(int argc, char **argv)
* TODO: Add corresponding "older" options to reverse these.
*/
case OPTION_NEWER_CTIME: /* GNU tar */
- bsdtar->newer_ctime_filter = 1;
- bsdtar->newer_ctime_sec = get_date(now, bsdtar->argument);
+ if (archive_matching_newer_ctime(bsdtar->matching,
+ get_date(now, bsdtar->argument), 0) != ARCHIVE_OK)
+ lafe_errc(1, 0, "Error : %s",
+ archive_error_string(bsdtar->matching));
break;
case OPTION_NEWER_CTIME_THAN:
- if (get_filetime(bsdtar->argument, 1/*ctime*/,
- &bsdtar->newer_ctime_sec,
- &bsdtar->newer_ctime_nsec) == 0)
- bsdtar->newer_ctime_filter = 1;
- else
- lafe_errc(1, 0,
- "Can't open file %s", bsdtar->argument);
+ if (archive_matching_newer_ctime_than(bsdtar->matching,
+ bsdtar->argument) != ARCHIVE_OK)
+ lafe_errc(1, 0, "Error : %s",
+ archive_error_string(bsdtar->matching));
break;
case OPTION_NEWER_MTIME: /* GNU tar */
- bsdtar->newer_mtime_filter = 1;
- bsdtar->newer_mtime_sec = get_date(now, bsdtar->argument);
+ if (archive_matching_newer_mtime(bsdtar->matching,
+ get_date(now, bsdtar->argument), 0) != ARCHIVE_OK)
+ lafe_errc(1, 0, "Error : %s",
+ archive_error_string(bsdtar->matching));
break;
case OPTION_NEWER_MTIME_THAN:
- if (get_filetime(bsdtar->argument, 0/*mtime*/,
- &bsdtar->newer_mtime_sec,
- &bsdtar->newer_mtime_nsec) == 0)
- bsdtar->newer_mtime_filter = 1;
- else
- lafe_errc(1, 0,
- "Can't open file %s", bsdtar->argument);
+ if (archive_matching_newer_mtime_than(bsdtar->matching,
+ bsdtar->argument) != ARCHIVE_OK)
+ lafe_errc(1, 0, "Error : %s",
+ archive_error_string(bsdtar->matching));
break;
case OPTION_NODUMP: /* star */
bsdtar->option_honor_nodump = 1;
@@ -554,7 +556,8 @@ main(int argc, char **argv)
bsdtar->option_interactive = 1;
break;
case 'X': /* GNU tar */
- if (lafe_exclude_from_file(&bsdtar->matching, bsdtar->argument))
+ if (lafe_exclude_from_file(bsdtar->matching,
+ bsdtar->argument))
lafe_errc(1, 0,
"failed to process exclusions from file %s",
bsdtar->argument);
@@ -679,7 +682,7 @@ main(int argc, char **argv)
break;
}
- lafe_cleanup_exclusions(&bsdtar->matching);
+ archive_matching_free(bsdtar->matching);
#if HAVE_REGEX_H
cleanup_substitution(bsdtar);
#endif
@@ -690,50 +693,6 @@ main(int argc, char **argv)
return (bsdtar->return_value);
}
-static int
-get_filetime(const char *path, int is_ctime, time_t *time, long *ns)
-{
-#if defined(_WIN32) && !defined(__CYGWIN__)
- /* NOTE: stat() on Windows cannot handle nano seconds. */
-#define EPOC_TIME (116444736000000000ui64)
- HANDLE h;
- WIN32_FIND_DATA d;
- ULARGE_INTEGER utc;
-
- h = FindFirstFile(path, &d);
- if (h == INVALID_HANDLE_VALUE)
- return (-1);
- FindClose(h);
- if (is_ctime) {
- utc.HighPart = d.ftCreationTime.dwHighDateTime;
- utc.LowPart = d.ftCreationTime.dwLowDateTime;
- } else {
- utc.HighPart = d.ftLastWriteTime.dwHighDateTime;
- utc.LowPart = d.ftLastWriteTime.dwLowDateTime;
- }
- if (utc.QuadPart >= EPOC_TIME) {
- utc.QuadPart -= EPOC_TIME;
- *time = (time_t)(utc.QuadPart / 10000000);
- *ns = (long)(utc.QuadPart % 10000000) * 100;
- } else {
- *time = 0;
- *ns = 0;
- }
-#else
- struct stat st;
- if (stat(path, &st) != 0)
- return (-1);
- if (is_ctime) {
- *time = st.st_ctime;
- *ns = ARCHIVE_STAT_CTIME_NANOS(&st);
- } else {
- *time = st.st_mtime;
- *ns = ARCHIVE_STAT_MTIME_NANOS(&st);
- }
-#endif
- return (0);
-}
-
static void
set_mode(struct bsdtar *bsdtar, char opt)
{
diff --git a/tar/bsdtar.h b/tar/bsdtar.h
index 9c8bf7f0..a85e9364 100644
--- a/tar/bsdtar.h
+++ b/tar/bsdtar.h
@@ -46,12 +46,6 @@ struct bsdtar {
const char *create_format; /* -F format */
char *pending_chdir; /* -C dir */
const char *names_from_file; /* -T file */
- int newer_ctime_filter; /* --newer/--newer-than */
- time_t newer_ctime_sec; /* --newer/--newer-than */
- long newer_ctime_nsec; /* --newer/--newer-than */
- int newer_mtime_filter; /* --newer-mtime/--newer-mtime-than */
- time_t newer_mtime_sec; /* --newer-mtime */
- long newer_mtime_nsec; /* --newer-mtime-than */
int bytes_per_block; /* -b block_size */
int bytes_in_last_block; /* See -b handling. */
int verbose; /* -v */
@@ -112,7 +106,7 @@ struct bsdtar {
char *buff; /* for write.c */
size_t buff_size; /* for write.c */
int first_fs; /* for write.c */
- struct lafe_matching *matching; /* for matching.c */
+ struct archive *matching; /* for matching.c */
struct security *security; /* for read.c */
struct name_cache *uname_cache; /* for write.c */
struct siginfo_data *siginfo; /* for siginfo.c */
diff --git a/tar/read.c b/tar/read.c
index 2ca7a534..90d8a8f2 100644
--- a/tar/read.c
+++ b/tar/read.c
@@ -77,12 +77,15 @@ struct progress_data {
static void list_item_verbose(struct bsdtar *, FILE *,
struct archive_entry *);
static void read_archive(struct bsdtar *bsdtar, char mode, struct archive *);
+static int unmatched_inclusions_warn(struct archive *matching, const char *);
+
void
tar_mode_t(struct bsdtar *bsdtar)
{
read_archive(bsdtar, 't', NULL);
- if (lafe_unmatched_inclusions_warn(bsdtar->matching, "Not found in archive") != 0)
+ if (unmatched_inclusions_warn(bsdtar->matching,
+ "Not found in archive") != 0)
bsdtar->return_value = 1;
}
@@ -100,7 +103,8 @@ tar_mode_x(struct bsdtar *bsdtar)
read_archive(bsdtar, 'x', writer);
- if (lafe_unmatched_inclusions_warn(bsdtar->matching, "Not found in archive") != 0)
+ if (unmatched_inclusions_warn(bsdtar->matching,
+ "Not found in archive") != 0)
bsdtar->return_value = 1;
archive_write_free(writer);
}
@@ -152,16 +156,17 @@ read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer)
struct archive *a;
struct archive_entry *entry;
int r;
- time_t sec;
- long nsec;
while (*bsdtar->argv) {
- lafe_include(&bsdtar->matching, *bsdtar->argv);
+ if (archive_matching_include_pattern(bsdtar->matching,
+ *bsdtar->argv) != ARCHIVE_OK)
+ lafe_errc(1, 0, "Error inclusion pattern: %s",
+ archive_error_string(bsdtar->matching));
bsdtar->argv++;
}
if (bsdtar->names_from_file != NULL)
- lafe_include_from_file(&bsdtar->matching,
+ lafe_include_from_file(bsdtar->matching,
bsdtar->names_from_file, bsdtar->option_null);
a = archive_read_new();
@@ -199,7 +204,7 @@ read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer)
for (;;) {
/* Support --fast-read option */
if (bsdtar->option_fast_read &&
- lafe_unmatched_inclusions(bsdtar->matching) == 0)
+ archive_matching_path_unmatched_inclusions(bsdtar->matching) == 0)
break;
r = archive_read_next_header(a, &entry);
@@ -234,38 +239,8 @@ read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer)
/*
* Exclude entries that are too old.
*/
- if (bsdtar->newer_ctime_filter) {
- /* Use ctime if format provides, else mtime. */
- if (archive_entry_ctime_is_set(entry)) {
- sec = archive_entry_ctime(entry);
- nsec = archive_entry_ctime_nsec(entry);
- } else if (archive_entry_mtime_is_set(entry)) {
- sec = archive_entry_mtime(entry);
- nsec = archive_entry_mtime_nsec(entry);
- } else {
- sec = 0;
- nsec = 0;
- }
- if (sec < bsdtar->newer_ctime_sec)
- continue; /* Too old, skip it. */
- if (sec == bsdtar->newer_ctime_sec
- && nsec <= bsdtar->newer_ctime_nsec)
- continue; /* Too old, skip it. */
- }
- if (bsdtar->newer_mtime_filter) {
- if (archive_entry_mtime_is_set(entry)) {
- sec = archive_entry_mtime(entry);
- nsec = archive_entry_mtime_nsec(entry);
- } else {
- sec = 0;
- nsec = 0;
- }
- if (sec < bsdtar->newer_mtime_sec)
- continue; /* Too old, skip it. */
- if (sec == bsdtar->newer_mtime_sec
- && nsec <= bsdtar->newer_mtime_nsec)
- continue; /* Too old, skip it. */
- }
+ if (archive_matching_time_excluded_ae(bsdtar->matching, entry))
+ continue; /* skip it. */
/*
* Note that pattern exclusions are checked before
@@ -276,7 +251,8 @@ read_archive(struct bsdtar *bsdtar, char mode, struct archive *writer)
* rewrite, there would be no way to exclude foo1/bar
* while allowing foo2/bar.)
*/
- if (lafe_excluded(bsdtar->matching, archive_entry_pathname(entry)))
+ if (archive_matching_path_excluded_ae(bsdtar->matching,
+ entry))
continue; /* Excluded by a pattern test. */
if (mode == 't') {
@@ -471,3 +447,21 @@ list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry)
else if (archive_entry_symlink(entry)) /* Symbolic link */
safe_fprintf(out, " -> %s", archive_entry_symlink(entry));
}
+
+static int
+unmatched_inclusions_warn(struct archive *matching, const char *msg)
+{
+ const char *p;
+ int r;
+
+ if (matching == NULL)
+ return (0);
+
+ while ((r = archive_matching_path_unmatched_inclusions_next(
+ matching, &p)) == ARCHIVE_OK)
+ lafe_warnc(0, "%s: %s", p, msg);
+ if (r == ARCHIVE_FATAL)
+ lafe_errc(1, errno, "Out of memory");
+
+ return (archive_matching_path_unmatched_inclusions(matching));
+}
diff --git a/tar/write.c b/tar/write.c
index 99d4d78f..c3a70161 100644
--- a/tar/write.c
+++ b/tar/write.c
@@ -93,8 +93,6 @@ struct archive_dir {
struct archive_dir_entry *head, *tail;
};
-static void add_dir_list(struct bsdtar *bsdtar, const char *path,
- time_t mtime_sec, int mtime_nsec);
static int append_archive(struct bsdtar *, struct archive *,
struct archive *ina);
static int append_archive_filename(struct bsdtar *,
@@ -106,7 +104,6 @@ static int copy_file_data_block(struct bsdtar *,
struct archive_entry *);
static int name_filter(struct archive *, void *,
struct archive_entry *);
-static int new_enough(struct bsdtar *, struct archive_entry *);
static void report_write(struct bsdtar *, struct archive *,
struct archive_entry *, int64_t progress);
static void test_for_append(struct bsdtar *);
@@ -345,9 +342,10 @@ tar_mode_u(struct bsdtar *bsdtar)
lafe_errc(1, 0,
"Cannot append to compressed archive.");
}
- add_dir_list(bsdtar, archive_entry_pathname(entry),
- archive_entry_mtime(entry),
- archive_entry_mtime_nsec(entry));
+ if (archive_matching_pathname_newer_mtime_ae(bsdtar->matching,
+ entry) != ARCHIVE_OK)
+ lafe_errc(1, 0, "Error : %s",
+ archive_error_string(bsdtar->matching));
/* Record the last format determination we see */
format = archive_format(a);
/* Keep going until we hit end-of-archive */
@@ -593,10 +591,11 @@ append_archive(struct bsdtar *bsdtar, struct archive *a, struct archive *ina)
int e;
while (ARCHIVE_OK == (e = archive_read_next_header(ina, &in_entry))) {
- if (!new_enough(bsdtar, in_entry))
+ if (archive_matching_time_excluded_ae(bsdtar->matching,
+ in_entry))
continue;
- if (lafe_excluded(bsdtar->matching,
- archive_entry_pathname(in_entry)))
+ if (archive_matching_path_excluded_ae(bsdtar->matching,
+ in_entry))
continue;
if (bsdtar->option_interactive &&
!yes("copy '%s'", archive_entry_pathname(in_entry)))
@@ -718,7 +717,7 @@ name_filter(struct archive *a, void *_data, struct archive_entry *entry)
* If this file/dir is excluded by a filename
* pattern, skip it.
*/
- if (lafe_excluded(bsdtar->matching, archive_entry_pathname(entry)))
+ if (archive_matching_path_excluded_ae(bsdtar->matching, entry))
return (0);
return (1);
}
@@ -732,7 +731,7 @@ metadata_filter(struct archive *a, void *_data, struct archive_entry *entry)
* In -u mode, check that the file is newer than what's
* already in the archive; in all modes, obey --newerXXX flags.
*/
- if (!new_enough(bsdtar, entry)) {
+ if (archive_matching_time_excluded_ae(bsdtar->matching, entry)) {
if (bsdtar->option_no_subdirs)
return (0);
if (!archive_read_disk_can_descend(a))
@@ -943,95 +942,6 @@ report_write(struct bsdtar *bsdtar, struct archive *a,
tar_i64toa(archive_entry_size(entry)));
}
-/*
- * Test if the specified file is new enough to include in the archive.
- */
-static int
-new_enough(struct bsdtar *bsdtar, struct archive_entry *e)
-{
- struct archive_dir_entry *p;
-
- /*
- * If this file/dir is excluded by a time comparison, skip it.
- */
- if (bsdtar->newer_ctime_filter) {
- if (archive_entry_ctime(e) < bsdtar->newer_ctime_sec)
- return (0); /* Too old, skip it. */
- if (archive_entry_ctime(e) == bsdtar->newer_ctime_sec
- && archive_entry_ctime_nsec(e) <= bsdtar->newer_ctime_nsec)
- return (0); /* Too old, skip it. */
- }
- if (bsdtar->newer_mtime_filter) {
- if (archive_entry_mtime(e) < bsdtar->newer_mtime_sec)
- return (0); /* Too old, skip it. */
- if (archive_entry_mtime(e) == bsdtar->newer_mtime_sec
- && archive_entry_mtime_nsec(e) <= bsdtar->newer_mtime_nsec)
- return (0); /* Too old, skip it. */
- }
-
- /*
- * In -u mode, we only write an entry if it's newer than
- * what was already in the archive.
- */
- if (bsdtar->archive_dir != NULL &&
- bsdtar->archive_dir->head != NULL) {
- const char *path = archive_entry_pathname(e);
- for (p = bsdtar->archive_dir->head; p != NULL; p = p->next) {
- if (pathcmp(path, p->name)==0)
- return (p->mtime_sec < archive_entry_mtime(e) ||
- (p->mtime_sec == archive_entry_mtime(e) &&
- p->mtime_nsec
- < archive_entry_mtime_nsec(e)));
- }
- }
-
- /* If the file wasn't rejected, include it. */
- return (1);
-}
-
-/*
- * Add an entry to the dir list for 'u' mode.
- *
- * XXX TODO: Make this fast.
- */
-static void
-add_dir_list(struct bsdtar *bsdtar, const char *path,
- time_t mtime_sec, int mtime_nsec)
-{
- struct archive_dir_entry *p;
-
- /*
- * Search entire list to see if this file has appeared before.
- * If it has, override the timestamp data.
- */
- p = bsdtar->archive_dir->head;
- while (p != NULL) {
- if (strcmp(path, p->name)==0) {
- p->mtime_sec = mtime_sec;
- p->mtime_nsec = mtime_nsec;
- return;
- }
- p = p->next;
- }
-
- p = malloc(sizeof(*p));
- if (p == NULL)
- lafe_errc(1, ENOMEM, "Can't read archive directory");
-
- p->name = strdup(path);
- if (p->name == NULL)
- lafe_errc(1, ENOMEM, "Can't read archive directory");
- p->mtime_sec = mtime_sec;
- p->mtime_nsec = mtime_nsec;
- p->next = NULL;
- if (bsdtar->archive_dir->tail == NULL) {
- bsdtar->archive_dir->head = bsdtar->archive_dir->tail = p;
- } else {
- bsdtar->archive_dir->tail->next = p;
- bsdtar->archive_dir->tail = p;
- }
-}
-
static void
test_for_append(struct bsdtar *bsdtar)
{