summaryrefslogtreecommitdiff
path: root/libarchive_fe
diff options
context:
space:
mode:
authorJoerg Sonnenberger <joerg.sonnenberger@gmail.com>2009-05-26 08:47:02 -0400
committerJoerg Sonnenberger <joerg.sonnenberger@gmail.com>2009-05-26 08:47:02 -0400
commit71d1bfe0f4f12d101def081c2ce170bb337b7841 (patch)
tree9096ab5d8261e5249fa31a2ec1332447d971d00e /libarchive_fe
parent83b3130331a1d5145bdd9f726d21876f15f2665d (diff)
downloadlibarchive-71d1bfe0f4f12d101def081c2ce170bb337b7841.tar.gz
Refactor common frontend code into a separate library.
SVN-Revision: 1118
Diffstat (limited to 'libarchive_fe')
-rw-r--r--libarchive_fe/err.c74
-rw-r--r--libarchive_fe/err.h34
-rw-r--r--libarchive_fe/lafe_platform.h53
-rw-r--r--libarchive_fe/line_reader.c159
-rw-r--r--libarchive_fe/line_reader.h35
-rw-r--r--libarchive_fe/matching.c283
-rw-r--r--libarchive_fe/matching.h46
-rw-r--r--libarchive_fe/pathmatch.c257
-rw-r--r--libarchive_fe/pathmatch.h42
9 files changed, 983 insertions, 0 deletions
diff --git a/libarchive_fe/err.c b/libarchive_fe/err.c
new file mode 100644
index 00000000..eb3f9f3e
--- /dev/null
+++ b/libarchive_fe/err.c
@@ -0,0 +1,74 @@
+/*-
+ * 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_STDARG_H
+#include <stdarg.h>
+#endif
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include "err.h"
+
+const char *lafe_progname;
+
+static void
+lafe_vwarnc(int code, const char *fmt, va_list ap)
+{
+ fprintf(stderr, "%s: ", lafe_progname);
+ vfprintf(stderr, fmt, ap);
+ if (code != 0)
+ fprintf(stderr, ": %s", strerror(code));
+ fprintf(stderr, "\n");
+}
+
+void
+lafe_warnc(int code, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ lafe_vwarnc(code, fmt, ap);
+ va_end(ap);
+}
+
+void
+lafe_errc(int eval, int code, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ lafe_vwarnc(code, fmt, ap);
+ va_end(ap);
+ exit(eval);
+}
diff --git a/libarchive_fe/err.h b/libarchive_fe/err.h
new file mode 100644
index 00000000..164e2d38
--- /dev/null
+++ b/libarchive_fe/err.h
@@ -0,0 +1,34 @@
+/*-
+ * Copyright (c) 2009 Joerg Sonnenberger
+ * 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.
+ */
+
+#ifndef LAFE_ERR_H
+#define LAFE_ERR_H
+
+extern const char *lafe_progname;
+
+void lafe_warnc(int code, const char *fmt, ...);
+void lafe_errc(int eval, int code, const char *fmt, ...);
+
+#endif
diff --git a/libarchive_fe/lafe_platform.h b/libarchive_fe/lafe_platform.h
new file mode 100644
index 00000000..dceb5aaf
--- /dev/null
+++ b/libarchive_fe/lafe_platform.h
@@ -0,0 +1,53 @@
+/*-
+ * 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.
+ *
+ * $FreeBSD: src/usr.bin/cpio/cpio_platform.h,v 1.2 2008/12/06 07:15:42 kientzle Exp $
+ */
+
+/*
+ * This header is the first thing included in any of the libarchive_fe
+ * source files. As far as possible, platform-specific issues should
+ * be dealt with here and not within individual source files.
+ */
+
+#ifndef LAFE_PLATFORM_H_INCLUDED
+#define LAFE_PLATFORM_H_INCLUDED
+
+#if defined(PLATFORM_CONFIG_H)
+/* Use hand-built config.h in environments that need it. */
+#include PLATFORM_CONFIG_H
+#else
+/* Read config.h or die trying. */
+#include "config.h"
+#endif
+
+/* No non-FreeBSD platform will have __FBSDID, so just define it here. */
+#ifdef __FreeBSD__
+#include <sys/cdefs.h> /* For __FBSDID */
+#elif !defined(__FBSDID)
+/* Just leaving this macro replacement empty leads to a dangling semicolon. */
+#define __FBSDID(a) struct _undefined_hack
+#endif
+
+#endif
diff --git a/libarchive_fe/line_reader.c b/libarchive_fe/line_reader.c
new file mode 100644
index 00000000..ee5252db
--- /dev/null
+++ b/libarchive_fe/line_reader.c
@@ -0,0 +1,159 @@
+/*-
+ * Copyright (c) 2008 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$");
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "err.h"
+#include "line_reader.h"
+
+/*
+ * Read lines from file and do something with each one. If option_null
+ * is set, lines are terminated with zero bytes; otherwise, they're
+ * terminated with newlines.
+ *
+ * This uses a self-sizing buffer to handle arbitrarily-long lines.
+ */
+struct lafe_line_reader {
+ FILE *f;
+ char *buff, *buff_end, *line_start, *line_end, *p;
+ char *pathname;
+ size_t buff_length;
+ int separator;
+ int ret;
+};
+
+struct lafe_line_reader *
+lafe_line_reader(const char *pathname, char separator)
+{
+ struct lafe_line_reader *lr;
+
+ lr = calloc(1, sizeof(*lr));
+ if (lr == NULL)
+ lafe_errc(1, ENOMEM, "Can't open %s", pathname);
+
+ lr->separator = separator;
+ lr->pathname = strdup(pathname);
+
+ if (strcmp(pathname, "-") == 0)
+ lr->f = stdin;
+ else
+ lr->f = fopen(pathname, "r");
+ if (lr->f == NULL)
+ lafe_errc(1, errno, "Couldn't open %s", pathname);
+ lr->buff_length = 8192;
+ lr->buff = malloc(lr->buff_length);
+ if (lr->buff == NULL)
+ lafe_errc(1, ENOMEM, "Can't read %s", pathname);
+ lr->line_start = lr->line_end = lr->buff_end = lr->buff;
+
+ return (lr);
+}
+
+const char *
+lafe_line_reader_next(struct lafe_line_reader *lr)
+{
+ size_t bytes_wanted, bytes_read, new_buff_size;
+ char *line_start, *p;
+
+ for (;;) {
+ /* If there's a line in the buffer, return it immediately. */
+ while (lr->line_end < lr->buff_end) {
+ if (*lr->line_end == lr->separator) {
+ *lr->line_end = '\0';
+ line_start = lr->line_start;
+ lr->line_start = lr->line_end + 1;
+ lr->line_end = lr->line_start;
+ return (line_start);
+ } else
+ lr->line_end++;
+ }
+
+ /* If we're at end-of-file, process the final data. */
+ if (lr->f == NULL) {
+ /* If there's more text, return one last line. */
+ if (lr->line_end > lr->line_start) {
+ *lr->line_end = '\0';
+ line_start = lr->line_start;
+ lr->line_start = lr->line_end + 1;
+ lr->line_end = lr->line_start;
+ return (line_start);
+ }
+ /* Otherwise, we're done. */
+ return (NULL);
+ }
+
+ /* Buffer only has part of a line. */
+ if (lr->line_start > lr->buff) {
+ /* Move a leftover fractional line to the beginning. */
+ memmove(lr->buff, lr->line_start,
+ lr->buff_end - lr->line_start);
+ lr->buff_end -= lr->line_start - lr->buff;
+ lr->line_end -= lr->line_start - lr->buff;
+ lr->line_start = lr->buff;
+ } else {
+ /* Line is too big; enlarge the buffer. */
+ new_buff_size = lr->buff_length * 2;
+ if (new_buff_size <= lr->buff_length)
+ lafe_errc(1, ENOMEM,
+ "Line too long in %s", lr->pathname);
+ lr->buff_length = new_buff_size;
+ p = realloc(lr->buff, new_buff_size);
+ if (p == NULL)
+ lafe_errc(1, ENOMEM,
+ "Line too long in %s", lr->pathname);
+ lr->buff_end = p + (lr->buff_end - lr->buff);
+ lr->line_end = p + (lr->line_end - lr->buff);
+ lr->line_start = lr->buff = p;
+ }
+
+ /* Get some more data into the buffer. */
+ bytes_wanted = lr->buff + lr->buff_length - lr->buff_end;
+ bytes_read = fread(lr->buff_end, 1, bytes_wanted, lr->f);
+ lr->buff_end += bytes_read;
+
+ if (ferror(lr->f))
+ lafe_errc(1, errno, "Can't read %s", lr->pathname);
+ if (feof(lr->f)) {
+ if (lr->f != stdin)
+ fclose(lr->f);
+ lr->f = NULL;
+ }
+ }
+}
+
+void
+lafe_line_reader_free(struct lafe_line_reader *lr)
+{
+ free(lr->buff);
+ free(lr->pathname);
+ free(lr);
+}
diff --git a/libarchive_fe/line_reader.h b/libarchive_fe/line_reader.h
new file mode 100644
index 00000000..7bb1742c
--- /dev/null
+++ b/libarchive_fe/line_reader.h
@@ -0,0 +1,35 @@
+/*-
+ * Copyright (c) 2009 Joerg Sonnenberger
+ * 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.
+ */
+
+#ifndef LAFE_LINE_READER_H
+#define LAFE_LINE_READER_H
+
+struct lafe_line_reader;
+
+struct lafe_line_reader *lafe_line_reader(const char *, char separator);
+const char *lafe_line_reader_next(struct lafe_line_reader *);
+void lafe_line_reader_free(struct lafe_line_reader *);
+
+#endif
diff --git a/libarchive_fe/matching.c b/libarchive_fe/matching.c
new file mode 100644
index 00000000..af5bde4e
--- /dev/null
+++ b/libarchive_fe/matching.c
@@ -0,0 +1,283 @@
+/*-
+ * 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 "lafe_platform.h"
+__FBSDID("$FreeBSD: src/usr.bin/cpio/matching.c,v 1.2 2008/06/21 02:20:20 kientzle Exp $");
+
+#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)
+{
+ struct lafe_line_reader *lr;
+ const char *p;
+ int ret = 0;
+
+ lr = lafe_line_reader(pathname, '\n');
+ while ((p = lafe_line_reader_next(lr)) != NULL) {
+ if (lafe_exclude(matching, p) != 0)
+ ret = -1;
+ }
+ 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)
+{
+ struct lafe_line_reader *lr;
+ const char *p;
+ int ret = 0;
+
+ lr = lafe_line_reader(pathname, '\n');
+ while ((p = lafe_line_reader_next(lr)) != NULL) {
+ if (lafe_include(matching, p) != 0)
+ ret = -1;
+ }
+ 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[strlen(match->pattern)-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);
+
+ /* Exclusions take priority */
+ for (match = matching->exclusions; match != NULL; match = match->next){
+ if (match_exclusion(match, pathname))
+ return (1);
+ }
+
+ /* Then check for inclusions */
+ matched = NULL;
+ for (match = matching->inclusions; match != NULL; match = match->next){
+ if (match_inclusion(match, pathname)) {
+ /*
+ * If this pattern has never been matched,
+ * then we're done.
+ */
+ if (match->matches == 0) {
+ match->matches++;
+ matching->inclusions_unmatched_count--;
+ return (0);
+ }
+ /*
+ * Otherwise, remember the match but keep checking
+ * in case we can tick off an unmatched pattern.
+ */
+ matched = match;
+ }
+ }
+ /*
+ * We didn't find a pattern that had never been matched, but
+ * we did find a match, so count it and exit.
+ */
+ if (matched != NULL) {
+ matched->matches++;
+ return (0);
+ }
+
+ /* If there were inclusions, default is to exclude. */
+ if (matching->inclusions != NULL)
+ 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)
+{
+#if 0
+ return (lafe_pathmatch(match->pattern, pathname, 0));
+#else
+ return (lafe_pathmatch(match->pattern, pathname, PATHMATCH_NO_ANCHOR_END));
+#endif
+}
+
+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
new file mode 100644
index 00000000..5cdc0166
--- /dev/null
+++ b/libarchive_fe/matching.h
@@ -0,0 +1,46 @@
+/*-
+ * 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 MATCHING_H
+#define MATCHING_H
+
+struct lafe_matching;
+
+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,
+ const char *pathname);
+
+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
new file mode 100644
index 00000000..80a0b6aa
--- /dev/null
+++ b/libarchive_fe/pathmatch.c
@@ -0,0 +1,257 @@
+/*-
+ * 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 '!' 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 < 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');
+ break;
+ case '?':
+ /* ? always succeds, 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);
+ break;
+ 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
new file mode 100644
index 00000000..a92f3aef
--- /dev/null
+++ b/libarchive_fe/pathmatch.h
@@ -0,0 +1,42 @@
+/*-
+ * 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