]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Use archive_matching API at both bsdcpio and bsdtar instead of lafe_exclude functions.
authorMichihiro NAKAJIMA <ggcueroad@gmail.com>
Wed, 18 Jan 2012 05:30:38 +0000 (00:30 -0500)
committerMichihiro NAKAJIMA <ggcueroad@gmail.com>
Wed, 18 Jan 2012 05:30:38 +0000 (00:30 -0500)
  - Remove libarchive_fe/matching.[ch], which are no longer needed.
  - Move cpio/test/test_pathmatch.c into libarchive/test/test_archive_pathmatch.c.

SVN-Revision: 4168

18 files changed:
Makefile.am
cpio/CMakeLists.txt
cpio/cpio.c
cpio/cpio.h
cpio/test/CMakeLists.txt
cpio/test/test_pathmatch.c [deleted file]
libarchive/archive_pathmatch.h
libarchive/test/CMakeLists.txt
libarchive/test/test_archive_pathmatch.c [new file with mode: 0644]
libarchive_fe/matching.c
libarchive_fe/matching.h
libarchive_fe/pathmatch.c [deleted file]
libarchive_fe/pathmatch.h [deleted file]
tar/CMakeLists.txt
tar/bsdtar.c
tar/bsdtar.h
tar/read.c
tar/write.c

index 3cac4263f29fd1c1b1da6ee15676c3e2fc44141b..56ee86346afa96f91c47dbfe82ef2fd744b03907 100644 (file)
@@ -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 \
index ce500b1cc6b4420e69d3645ff1246e20ab631d43..98e3449676bc297d448af697c7472e3775f7b0cb 100644 (file)
@@ -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)
index 025c50cfafd2af65f94ecbf68406453b6349ce43..c919d380b785edb9e87fc87fdf01c071a7816d3b 100644 (file)
@@ -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);
index dc68e66a6fed5fbd7ae61ce04e9294a0ac98b833..9e5af674e7860141af6db0ad1a7ba25a5f12b4f7 100644 (file)
@@ -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;
 };
index 2196c19aed0d0c63dd54151ce617af7a53137f55..a06ae0496ec4ce103da1b83f1307700c917d53d4 100644 (file)
@@ -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 (file)
index 177c2bc..0000000
+++ /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));
-}
index 259599ac82aa90eb42ca8df76d61c01d1426b620..e6901774dddbb66bbd310f0d818466f6853477c0 100644 (file)
  */
 
 #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
index 4c97055347b58e8d47ee913cb654bc546f355ac3..479681cd43a7f7c6676adfe6a36ee5628dd397fc 100644 (file)
@@ -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 (file)
index 0000000..fed6ad7
--- /dev/null
@@ -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));
+}
index 4ba608222f3f979a3d0f3f9802ad4b905d6d9960..be454b5b9e0adf5249c2059fc748411b1158e010 100644 (file)
@@ -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);
-}
index f4edebd4399702985be000f34beeb363fedf1907..4c174a8457d89d32c46ae3f8b17728b1ea641814 100644 (file)
 #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 (file)
index ff8a105..0000000
+++ /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 (file)
index a92f3ae..0000000
+++ /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
index b3b931e919b4fd3195236ff8790333dc05d82b41..39b336cd9392ec304d1a63fe87c512629e44a2d8 100644 (file)
@@ -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)
index 5f89959c72b569aeaa1de0d6235bf8138e355a1d..a2d4617f05e8118f80d074b4b2904c9428ea44cb 100644 (file)
@@ -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)
 {
index 9c8bf7f0f6876df54cc525e4c1b302c5d36b8570..a85e9364a2f23464034089c36ab85c3a862b2768 100644 (file)
@@ -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 */
index 2ca7a534cb140c8f5f030103249b55821fd58e8f..90d8a8f2eef163e93f96bfd9c39670bab7b6b2e8 100644 (file)
@@ -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));
+}
index 99d4d78f5d62e85ad16e1d0bb5800d944a9aaa58..c3a701618553ffef27ed9d759b0902aab6466608 100644 (file)
@@ -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)
 {