mtree.c revision 244541
1244541Sbrooks/*	$NetBSD: mtree.c,v 1.46 2012/12/20 19:09:25 christos Exp $	*/
2244541Sbrooks
3244541Sbrooks/*-
4244541Sbrooks * Copyright (c) 1989, 1990, 1993
5244541Sbrooks *	The Regents of the University of California.  All rights reserved.
6244541Sbrooks *
7244541Sbrooks * Redistribution and use in source and binary forms, with or without
8244541Sbrooks * modification, are permitted provided that the following conditions
9244541Sbrooks * are met:
10244541Sbrooks * 1. Redistributions of source code must retain the above copyright
11244541Sbrooks *    notice, this list of conditions and the following disclaimer.
12244541Sbrooks * 2. Redistributions in binary form must reproduce the above copyright
13244541Sbrooks *    notice, this list of conditions and the following disclaimer in the
14244541Sbrooks *    documentation and/or other materials provided with the distribution.
15244541Sbrooks * 3. Neither the name of the University nor the names of its contributors
16244541Sbrooks *    may be used to endorse or promote products derived from this software
17244541Sbrooks *    without specific prior written permission.
18244541Sbrooks *
19244541Sbrooks * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20244541Sbrooks * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21244541Sbrooks * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22244541Sbrooks * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23244541Sbrooks * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24244541Sbrooks * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25244541Sbrooks * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26244541Sbrooks * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27244541Sbrooks * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28244541Sbrooks * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29244541Sbrooks * SUCH DAMAGE.
30244541Sbrooks */
31244541Sbrooks
32244541Sbrooks#if HAVE_NBTOOL_CONFIG_H
33244541Sbrooks#include "nbtool_config.h"
34244541Sbrooks#endif
35244541Sbrooks
36244541Sbrooks#include <sys/cdefs.h>
37244541Sbrooks#if defined(__COPYRIGHT) && !defined(lint)
38244541Sbrooks__COPYRIGHT("@(#) Copyright (c) 1989, 1990, 1993\
39244541Sbrooks The Regents of the University of California.  All rights reserved.");
40244541Sbrooks#endif /* not lint */
41244541Sbrooks
42244541Sbrooks#if defined(__RCSID) && !defined(lint)
43244541Sbrooks#if 0
44244541Sbrooksstatic char sccsid[] = "@(#)mtree.c	8.1 (Berkeley) 6/6/93";
45244541Sbrooks#else
46244541Sbrooks__RCSID("$NetBSD: mtree.c,v 1.46 2012/12/20 19:09:25 christos Exp $");
47244541Sbrooks#endif
48244541Sbrooks#endif /* not lint */
49244541Sbrooks
50244541Sbrooks#include <sys/param.h>
51244541Sbrooks#include <sys/stat.h>
52244541Sbrooks
53244541Sbrooks#include <errno.h>
54244541Sbrooks#include <stdio.h>
55244541Sbrooks#include <stdlib.h>
56244541Sbrooks#include <string.h>
57244541Sbrooks#include <unistd.h>
58244541Sbrooks
59244541Sbrooks#include "extern.h"
60244541Sbrooks
61244541Sbrooksint	ftsoptions = FTS_PHYSICAL;
62244541Sbrooksint	bflag, cflag, Cflag, dflag, Dflag, eflag, iflag, jflag, lflag, mflag,
63244541Sbrooks    	nflag, qflag, rflag, sflag, tflag, uflag, Uflag, wflag;
64244541Sbrookschar	fullpath[MAXPATHLEN];
65244541Sbrooks
66244541Sbrooksstatic struct {
67244541Sbrooks	enum flavor flavor;
68244541Sbrooks	const char name[9];
69244541Sbrooks} flavors[] = {
70244541Sbrooks	{F_MTREE, "mtree"},
71244541Sbrooks	{F_FREEBSD9, "freebsd9"},
72244541Sbrooks	{F_NETBSD6, "netbsd6"},
73244541Sbrooks};
74244541Sbrooks
75244541Sbrooks__dead static	void	usage(void);
76244541Sbrooks
77244541Sbrooksint
78244541Sbrooksmain(int argc, char **argv)
79244541Sbrooks{
80244541Sbrooks	int	ch, status;
81244541Sbrooks	unsigned int	i;
82244541Sbrooks	char	*dir, *p;
83244541Sbrooks	FILE	*spec1, *spec2;
84244541Sbrooks
85244541Sbrooks	setprogname(argv[0]);
86244541Sbrooks
87244541Sbrooks	dir = NULL;
88244541Sbrooks	init_excludes();
89244541Sbrooks	spec1 = stdin;
90244541Sbrooks	spec2 = NULL;
91244541Sbrooks
92244541Sbrooks	while ((ch = getopt(argc, argv,
93244541Sbrooks	    "bcCdDeE:f:F:I:ijk:K:lLmMnN:p:PqrR:s:StuUwWxX:"))
94244541Sbrooks	    != -1) {
95244541Sbrooks		switch((char)ch) {
96244541Sbrooks		case 'b':
97244541Sbrooks			bflag = 1;
98244541Sbrooks			break;
99244541Sbrooks		case 'c':
100244541Sbrooks			cflag = 1;
101244541Sbrooks			break;
102244541Sbrooks		case 'C':
103244541Sbrooks			Cflag = 1;
104244541Sbrooks			break;
105244541Sbrooks		case 'd':
106244541Sbrooks			dflag = 1;
107244541Sbrooks			break;
108244541Sbrooks		case 'D':
109244541Sbrooks			Dflag = 1;
110244541Sbrooks			break;
111244541Sbrooks		case 'E':
112244541Sbrooks			parsetags(&excludetags, optarg);
113244541Sbrooks			break;
114244541Sbrooks		case 'e':
115244541Sbrooks			eflag = 1;
116244541Sbrooks			break;
117244541Sbrooks		case 'f':
118244541Sbrooks			if (spec1 == stdin) {
119244541Sbrooks				spec1 = fopen(optarg, "r");
120244541Sbrooks				if (spec1 == NULL)
121244541Sbrooks					mtree_err("%s: %s", optarg,
122244541Sbrooks					    strerror(errno));
123244541Sbrooks			} else if (spec2 == NULL) {
124244541Sbrooks				spec2 = fopen(optarg, "r");
125244541Sbrooks				if (spec2 == NULL)
126244541Sbrooks					mtree_err("%s: %s", optarg,
127244541Sbrooks					    strerror(errno));
128244541Sbrooks			} else
129244541Sbrooks				usage();
130244541Sbrooks			break;
131244541Sbrooks		case 'F':
132244541Sbrooks			for (i = 0; i < __arraycount(flavors); i++)
133244541Sbrooks				if (strcmp(optarg, flavors[i].name) == 0) {
134244541Sbrooks					flavor = flavors[i].flavor;
135244541Sbrooks					break;
136244541Sbrooks				}
137244541Sbrooks			if (i == __arraycount(flavors))
138244541Sbrooks				usage();
139244541Sbrooks			break;
140244541Sbrooks		case 'i':
141244541Sbrooks			iflag = 1;
142244541Sbrooks			break;
143244541Sbrooks		case 'I':
144244541Sbrooks			parsetags(&includetags, optarg);
145244541Sbrooks			break;
146244541Sbrooks		case 'j':
147244541Sbrooks			jflag = 1;
148244541Sbrooks			break;
149244541Sbrooks		case 'k':
150244541Sbrooks			keys = F_TYPE;
151244541Sbrooks			while ((p = strsep(&optarg, " \t,")) != NULL)
152244541Sbrooks				if (*p != '\0')
153244541Sbrooks					keys |= parsekey(p, NULL);
154244541Sbrooks			break;
155244541Sbrooks		case 'K':
156244541Sbrooks			while ((p = strsep(&optarg, " \t,")) != NULL)
157244541Sbrooks				if (*p != '\0')
158244541Sbrooks					keys |= parsekey(p, NULL);
159244541Sbrooks			break;
160244541Sbrooks		case 'l':
161244541Sbrooks			lflag = 1;
162244541Sbrooks			break;
163244541Sbrooks		case 'L':
164244541Sbrooks			ftsoptions &= ~FTS_PHYSICAL;
165244541Sbrooks			ftsoptions |= FTS_LOGICAL;
166244541Sbrooks			break;
167244541Sbrooks		case 'm':
168244541Sbrooks			mflag = 1;
169244541Sbrooks			break;
170244541Sbrooks		case 'M':
171244541Sbrooks			mtree_Mflag = 1;
172244541Sbrooks			break;
173244541Sbrooks		case 'n':
174244541Sbrooks			nflag = 1;
175244541Sbrooks			break;
176244541Sbrooks		case 'N':
177244541Sbrooks			if (! setup_getid(optarg))
178244541Sbrooks				mtree_err(
179244541Sbrooks			    "Unable to use user and group databases in `%s'",
180244541Sbrooks				    optarg);
181244541Sbrooks			break;
182244541Sbrooks		case 'p':
183244541Sbrooks			dir = optarg;
184244541Sbrooks			break;
185244541Sbrooks		case 'P':
186244541Sbrooks			ftsoptions &= ~FTS_LOGICAL;
187244541Sbrooks			ftsoptions |= FTS_PHYSICAL;
188244541Sbrooks			break;
189244541Sbrooks		case 'q':
190244541Sbrooks			qflag = 1;
191244541Sbrooks			break;
192244541Sbrooks		case 'r':
193244541Sbrooks			rflag = 1;
194244541Sbrooks			break;
195244541Sbrooks		case 'R':
196244541Sbrooks			while ((p = strsep(&optarg, " \t,")) != NULL)
197244541Sbrooks				if (*p != '\0')
198244541Sbrooks					keys &= ~parsekey(p, NULL);
199244541Sbrooks			break;
200244541Sbrooks		case 's':
201244541Sbrooks			sflag = 1;
202244541Sbrooks			crc_total = ~strtol(optarg, &p, 0);
203244541Sbrooks			if (*p)
204244541Sbrooks				mtree_err("illegal seed value -- %s", optarg);
205244541Sbrooks			break;
206244541Sbrooks		case 'S':
207244541Sbrooks			mtree_Sflag = 1;
208244541Sbrooks			break;
209244541Sbrooks		case 't':
210244541Sbrooks			tflag = 1;
211244541Sbrooks			break;
212244541Sbrooks		case 'u':
213244541Sbrooks			uflag = 1;
214244541Sbrooks			break;
215244541Sbrooks		case 'U':
216244541Sbrooks			Uflag = uflag = 1;
217244541Sbrooks			break;
218244541Sbrooks		case 'w':
219244541Sbrooks			wflag = 1;
220244541Sbrooks			break;
221244541Sbrooks		case 'W':
222244541Sbrooks			mtree_Wflag = 1;
223244541Sbrooks			break;
224244541Sbrooks		case 'x':
225244541Sbrooks			ftsoptions |= FTS_XDEV;
226244541Sbrooks			break;
227244541Sbrooks		case 'X':
228244541Sbrooks			read_excludes_file(optarg);
229244541Sbrooks			break;
230244541Sbrooks		case '?':
231244541Sbrooks		default:
232244541Sbrooks			usage();
233244541Sbrooks		}
234244541Sbrooks	}
235244541Sbrooks	argc -= optind;
236244541Sbrooks	argv += optind;
237244541Sbrooks
238244541Sbrooks	if (argc)
239244541Sbrooks		usage();
240244541Sbrooks
241244541Sbrooks	switch (flavor) {
242244541Sbrooks	case F_FREEBSD9:
243244541Sbrooks		if (cflag && iflag) {
244244541Sbrooks			warnx("-c and -i passed, replacing -i with -j for "
245244541Sbrooks			    "FreeBSD compatibility");
246244541Sbrooks			iflag = 0;
247244541Sbrooks			jflag = 1;
248244541Sbrooks		}
249244541Sbrooks		if (dflag && !bflag) {
250244541Sbrooks			warnx("Adding -b to -d for FreeBSD compatibility");
251244541Sbrooks			bflag = 1;
252244541Sbrooks		}
253244541Sbrooks		if (uflag && !iflag) {
254244541Sbrooks			warnx("Adding -i to -%c for FreeBSD compatibility",
255244541Sbrooks			    Uflag ? 'U' : 'u');
256244541Sbrooks			iflag = 1;
257244541Sbrooks		}
258244541Sbrooks		if (uflag && !tflag) {
259244541Sbrooks			warnx("Adding -t to -%c for FreeBSD compatibility",
260244541Sbrooks			    Uflag ? 'U' : 'u');
261244541Sbrooks			tflag = 1;
262244541Sbrooks		}
263244541Sbrooks		if (wflag)
264244541Sbrooks			warnx("The -w flag is a no-op");
265244541Sbrooks		break;
266244541Sbrooks	default:
267244541Sbrooks		if (wflag)
268244541Sbrooks			usage();
269244541Sbrooks	}
270244541Sbrooks
271244541Sbrooks	if (spec2 && (cflag || Cflag || Dflag))
272244541Sbrooks		mtree_err("Double -f, -c, -C and -D flags are mutually "
273244541Sbrooks		    "exclusive");
274244541Sbrooks
275244541Sbrooks	if (dir && spec2)
276244541Sbrooks		mtree_err("Double -f and -p flags are mutually exclusive");
277244541Sbrooks
278244541Sbrooks	if (dir && chdir(dir))
279244541Sbrooks		mtree_err("%s: %s", dir, strerror(errno));
280244541Sbrooks
281244541Sbrooks	if ((cflag || sflag) && !getcwd(fullpath, sizeof(fullpath)))
282244541Sbrooks		mtree_err("%s", strerror(errno));
283244541Sbrooks
284244541Sbrooks	if ((cflag && Cflag) || (cflag && Dflag) || (Cflag && Dflag))
285244541Sbrooks		mtree_err("-c, -C and -D flags are mutually exclusive");
286244541Sbrooks
287244541Sbrooks	if (iflag && mflag)
288244541Sbrooks		mtree_err("-i and -m flags are mutually exclusive");
289244541Sbrooks
290244541Sbrooks	if (lflag && uflag)
291244541Sbrooks		mtree_err("-l and -u flags are mutually exclusive");
292244541Sbrooks
293244541Sbrooks	if (cflag) {
294244541Sbrooks		cwalk();
295244541Sbrooks		exit(0);
296244541Sbrooks	}
297244541Sbrooks	if (Cflag || Dflag) {
298244541Sbrooks		dump_nodes("", spec(spec1), Dflag);
299244541Sbrooks		exit(0);
300244541Sbrooks	}
301244541Sbrooks	if (spec2 != NULL)
302244541Sbrooks		status = mtree_specspec(spec1, spec2);
303244541Sbrooks	else
304244541Sbrooks		status = verify(spec1);
305244541Sbrooks	if (Uflag && (status == MISMATCHEXIT))
306244541Sbrooks		status = 0;
307244541Sbrooks	exit(status);
308244541Sbrooks}
309244541Sbrooks
310244541Sbrooksstatic void
311244541Sbrooksusage(void)
312244541Sbrooks{
313244541Sbrooks	unsigned int i;
314244541Sbrooks
315244541Sbrooks	fprintf(stderr,
316244541Sbrooks	    "usage: %s [-bCcDdejLlMnPqrStUuWx] [-i|-m] [-E tags]\n"
317244541Sbrooks	    "\t\t[-f spec] [-f spec]\n"
318244541Sbrooks	    "\t\t[-I tags] [-K keywords] [-k keywords] [-N dbdir] [-p path]\n"
319244541Sbrooks	    "\t\t[-R keywords] [-s seed] [-X exclude-file]\n"
320244541Sbrooks	    "\t\t[-F flavor]\n",
321244541Sbrooks	    getprogname());
322244541Sbrooks	fprintf(stderr, "\nflavors:");
323244541Sbrooks	for (i = 0; i < __arraycount(flavors); i++)
324244541Sbrooks		fprintf(stderr, " %s", flavors[i].name);
325244541Sbrooks	fprintf(stderr, "\n");
326244541Sbrooks	exit(1);
327244541Sbrooks}
328