160418Swollman/*
260418Swollman * Copyright 2000 Massachusetts Institute of Technology
360418Swollman *
460418Swollman * Permission to use, copy, modify, and distribute this software and
560418Swollman * its documentation for any purpose and without fee is hereby
660418Swollman * granted, provided that both the above copyright notice and this
760418Swollman * permission notice appear in all copies, that both the above
860418Swollman * copyright notice and this permission notice appear in all
960418Swollman * supporting documentation, and that the name of M.I.T. not be used
1060418Swollman * in advertising or publicity pertaining to distribution of the
1160418Swollman * software without specific, written prior permission.  M.I.T. makes
1260418Swollman * no representations about the suitability of this software for any
1360418Swollman * purpose.  It is provided "as is" without express or implied
1460418Swollman * warranty.
15121300Sphk *
1660418Swollman * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
1760418Swollman * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
1860418Swollman * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1960418Swollman * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
2060418Swollman * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2160418Swollman * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2260418Swollman * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
2360418Swollman * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
2460418Swollman * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2560418Swollman * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
2660418Swollman * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2760418Swollman * SUCH DAMAGE.
2860418Swollman */
2960418Swollman
30114601Sobrien#include <sys/cdefs.h>
31114601Sobrien__FBSDID("$FreeBSD: releng/11.0/usr.sbin/fmtree/excludes.c 298028 2016-04-15 03:38:58Z araujo $");
3260418Swollman
3360418Swollman#include <sys/types.h>
3460647Swollman#include <sys/time.h>		/* XXX for mtree.h */
3560418Swollman#include <sys/queue.h>
3660418Swollman
3760418Swollman#include <err.h>
3860418Swollman#include <fnmatch.h>
3960418Swollman#include <fts.h>
4060418Swollman#include <stdio.h>
4160418Swollman#include <stdlib.h>
4260418Swollman
4360647Swollman#include "mtree.h"		/* XXX for extern.h */
4460647Swollman#include "extern.h"
4560647Swollman
4660418Swollman/*
47121300Sphk * We're assuming that there won't be a whole lot of excludes,
4860418Swollman * so it's OK to use a stupid algorithm.
4960418Swollman */
5060418Swollmanstruct exclude {
5160938Sjake	LIST_ENTRY(exclude) link;
5260418Swollman	const char *glob;
5360418Swollman	int pathname;
5460418Swollman};
5560938Sjakestatic LIST_HEAD(, exclude) excludes;
5660418Swollman
5760418Swollmanvoid
5860418Swollmaninit_excludes(void)
5960418Swollman{
6060418Swollman	LIST_INIT(&excludes);
6160418Swollman}
6260418Swollman
6360418Swollmanvoid
6460418Swollmanread_excludes_file(const char *name)
6560418Swollman{
6660418Swollman	FILE *fp;
6760418Swollman	char *line, *str;
6860418Swollman	struct exclude *e;
6960418Swollman	size_t len;
7060418Swollman
7160418Swollman	fp = fopen(name, "r");
72298028Saraujo	if (fp == NULL)
7360418Swollman		err(1, "%s", name);
7460418Swollman
75298028Saraujo	while ((line = fgetln(fp, &len)) != NULL) {
7660418Swollman		if (line[len - 1] == '\n')
7760418Swollman			len--;
7860418Swollman		if (len == 0)
7960418Swollman			continue;
8060418Swollman
8160418Swollman		str = malloc(len + 1);
8260418Swollman		e = malloc(sizeof *e);
83298028Saraujo		if (str == NULL || e == NULL)
8460418Swollman			errx(1, "memory allocation error");
8560418Swollman		e->glob = str;
8660418Swollman		memcpy(str, line, len);
8760418Swollman		str[len] = '\0';
8860418Swollman		if (strchr(str, '/'))
8960418Swollman			e->pathname = 1;
9060418Swollman		else
9160418Swollman			e->pathname = 0;
9260418Swollman		LIST_INSERT_HEAD(&excludes, e, link);
9360418Swollman	}
9460418Swollman	fclose(fp);
9560418Swollman}
9660418Swollman
9760418Swollmanint
9860418Swollmancheck_excludes(const char *fname, const char *path)
9960418Swollman{
10060418Swollman	struct exclude *e;
10160418Swollman
10260418Swollman	/* fnmatch(3) has a funny return value convention... */
10360418Swollman#define MATCH(g, n) (fnmatch((g), (n), FNM_PATHNAME) == 0)
10460418Swollman
10570486Sben	LIST_FOREACH(e, &excludes, link) {
106121300Sphk		if ((e->pathname && MATCH(e->glob, path))
10760418Swollman		    || MATCH(e->glob, fname))
10860418Swollman			return 1;
10960418Swollman	}
11060418Swollman	return 0;
11160418Swollman}
112