Hello,
here is a patch that adds the -X option to /usr/sbin/mtree. This
option is described in the man page as follows:
"The specified file contains fnmatch(3) patterns matching
files to be excluded from the specification, one to a line."
The code is taken from NetBSD's mtree. Also at least FreeBSD
and Mac OS X have the same option available.
I have been using the patch in 4.7 and it seems to work
fine for me. I hope one of you can check that it is OK
and commit into OpenBSD CVS. I did not touch licenses etc.
If you have further questions or want to say how it should
have been done, cc me, as I don't subscribe to tech.
Thanks,
Teemu
Here it is, 260 lines between the tags:
<patch>
--- /dev/null Sun Sep 12 01:52:21 2010
+++ excludes.c Wed Jun 30 01:12:51 2010
@@ -0,0 +1,114 @@
+/* $NetBSD: excludes.c,v 1.13 2004/06/20 22:20:18 jmc Exp $ */
+
+/*
+ * Copyright 2000 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. 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 <sys/cdefs.h>
+
+#if defined(__RCSID) && !defined(lint)
+__RCSID("$NetBSD: excludes.c,v 1.13 2004/06/20 22:20:18 jmc Exp $");
+#endif
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <fnmatch.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <util.h>
+
+#include "extern.h"
+
+/*
+ * We're assuming that there won't be a whole lot of excludes,
+ * so it's OK to use a stupid algorithm.
+ */
+struct exclude {
+ LIST_ENTRY(exclude) link;
+ const char *glob;
+ int pathname;
+};
+static LIST_HEAD(, exclude) excludes;
+
+void
+init_excludes(void)
+{
+ LIST_INIT(&excludes);
+}
+
+void
+read_excludes_file(const char *name)
+{
+ FILE *fp;
+ char *line;
+ struct exclude *e;
+
+ fp = fopen(name, "r");
+ if (fp == 0)
+ err(1, "%s", name);
+
+ while ((line = fparseln(fp, NULL, NULL, NULL,
+ FPARSELN_UNESCCOMM | FPARSELN_UNESCCONT | FPARSELN_UNESCESC))
+ != NULL) {
+ if (line[0] == '\0')
+ continue;
+
+ if ((e = malloc(sizeof *e)) == NULL)
+ error("memory allocation error");
+
+ e->glob = line;
+ if (strchr(e->glob, '/') != NULL)
+ e->pathname = 1;
+ else
+ e->pathname = 0;
+ LIST_INSERT_HEAD(&excludes, e, link);
+ }
+ fclose(fp);
+}
+
+int
+check_excludes(const char *fname, const char *path)
+{
+ struct exclude *e;
+
+ /* fnmatch(3) has a funny return value convention... */
+#define MATCH(g, n) (fnmatch((g), (n), FNM_PATHNAME) == 0)
+
+ e = LIST_FIRST(&excludes);
+ while (e) {
+ if ((e->pathname && MATCH(e->glob, path))
+ || MATCH(e->glob, fname)) {
+ return (1);
+ }
+ e = LIST_NEXT(e, link);
+ }
+ return (0);
+}
Index: Makefile
===================================================================
RCS file: /cvs/src/usr.sbin/mtree/Makefile,v
retrieving revision 1.7
diff -u -r1.7 Makefile
--- Makefile 2 May 2004 17:55:53 -0000 1.7
+++ Makefile 11 Sep 2010 22:52:42 -0000
@@ -2,7 +2,8 @@
PROG= mtree
#CFLAGS+=-DDEBUG
+LDFLAGS+=-O2 -pipe -lutil
MAN= mtree.8
-SRCS= compare.c crc.c create.c misc.c mtree.c spec.c verify.c
+SRCS= compare.c crc.c create.c excludes.c misc.c mtree.c spec.c verify.c
.include <bsd.prog.mk>
Index: create.c
===================================================================
RCS file: /cvs/src/usr.sbin/mtree/create.c,v
retrieving revision 1.26
diff -u -r1.26 create.c
--- create.c 27 Oct 2009 23:59:53 -0000 1.26
+++ create.c 11 Sep 2010 22:52:42 -0000
@@ -87,6 +87,10 @@
if ((t = fts_open(argv, ftsoptions, dsort)) == NULL)
error("fts_open: %s", strerror(errno));
while ((p = fts_read(t))) {
+ if (check_excludes(p->fts_name, p->fts_path)) {
+ fts_set(t, p, FTS_SKIP);
+ continue;
+ }
if (iflag)
indent = p->fts_level * 4;
switch(p->fts_info) {
Index: extern.h
===================================================================
RCS file: /cvs/src/usr.sbin/mtree/extern.h,v
retrieving revision 1.8
diff -u -r1.8 extern.h
--- extern.h 10 Aug 2005 00:42:09 -0000 1.8
+++ extern.h 11 Sep 2010 22:52:42 -0000
@@ -46,3 +46,6 @@
char *rlink(char *);
struct _node *spec(void);
int verify(void);
+void init_excludes(void);
+void read_excludes_file(const char *);
+int check_excludes(const char *, const char *);
Index: mtree.8
===================================================================
RCS file: /cvs/src/usr.sbin/mtree/mtree.8,v
retrieving revision 1.32
diff -u -r1.32 mtree.8
--- mtree.8 31 May 2007 19:20:26 -0000 1.32
+++ mtree.8 11 Sep 2010 22:52:42 -0000
@@ -45,6 +45,7 @@
.Op Fl k Ar keywords
.Op Fl p Ar path
.Op Fl s Ar seed
+.Op Fl X Ar exclude-file
.Ek
.Sh DESCRIPTION
The utility
@@ -147,6 +148,20 @@
did not match the specification.
.It Fl x
Don't descend below mount points in the file hierarchy.
+.It Fl X Ar exclude-file
+The specified file contains
+.Xr fnmatch 3
+patterns matching files to be excluded from
+the specification, one to a line.
+If the pattern contains a
+.Ql \&/
+character, it will be matched against entire pathnames (relative to
+the starting directory); otherwise,
+it will be matched against basenames only.
+Comments are permitted in
+the
+.Ar exclude-list
+file.
.El
.Pp
Specifications are mostly composed of
Index: mtree.c
===================================================================
RCS file: /cvs/src/usr.sbin/mtree/mtree.c,v
retrieving revision 1.20
diff -u -r1.20 mtree.c
--- mtree.c 27 Oct 2009 23:59:53 -0000 1.20
+++ mtree.c 11 Sep 2010 22:52:42 -0000
@@ -58,9 +58,11 @@
char *dir, *p;
int status;
+ init_excludes();
+
dir = NULL;
keys = KEYDEFAULT;
- while ((ch = getopt(argc, argv, "cdef:iK:k:lnp:qrs:tUux")) != -1)
+ while ((ch = getopt(argc, argv, "cdef:iK:k:lnp:qrs:tUuX:x")) != -1)
switch((char)ch) {
case 'c':
cflag = 1;
@@ -123,6 +125,9 @@
case 'x':
ftsoptions |= FTS_XDEV;
break;
+ case 'X':
+ read_excludes_file(optarg);
+ break;
case '?':
default:
usage();
@@ -157,7 +162,7 @@
{
(void)fprintf(stderr,
"usage: mtree [-cdeilnqrtUux] [-f spec] [-K keywords] "
- "[-k keywords] [-p path]\n"
- " [-s seed]\n");
+ "[-k keywords]\n"
+ " [-X exclude-file] [-p path] [-s seed]\n");
exit(1);
}
Index: verify.c
===================================================================
RCS file: /cvs/src/usr.sbin/mtree/verify.c,v
retrieving revision 1.19
diff -u -r1.19 verify.c
--- verify.c 27 Oct 2009 23:59:53 -0000 1.19
+++ verify.c 11 Sep 2010 22:52:42 -0000
@@ -79,6 +79,10 @@
level = root;
specdepth = rval = 0;
while ((p = fts_read(t))) {
+ if (check_excludes(p->fts_name, p->fts_path)) {
+ fts_set(t, p, FTS_SKIP);
+ continue;
+ }
switch(p->fts_info) {
case FTS_D:
break;
</patch>