1273796Sbrooks/*	$NetBSD: mtree.c,v 1.49 2014/04/24 17:22:41 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
46273796Sbrooks__RCSID("$NetBSD: mtree.c,v 1.49 2014/04/24 17:22:41 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;
62249293Sedint	bflag, dflag, eflag, iflag, jflag, lflag, mflag, nflag, qflag, rflag,
63249293Sed	sflag, tflag, uflag;
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;
82249293Sed	int	cflag, Cflag, Dflag, Uflag, wflag;
83244541Sbrooks	char	*dir, *p;
84244541Sbrooks	FILE	*spec1, *spec2;
85244541Sbrooks
86244541Sbrooks	setprogname(argv[0]);
87244541Sbrooks
88249293Sed	cflag = Cflag = Dflag = Uflag = wflag = 0;
89244541Sbrooks	dir = NULL;
90244541Sbrooks	init_excludes();
91244541Sbrooks	spec1 = stdin;
92244541Sbrooks	spec2 = NULL;
93244541Sbrooks
94244541Sbrooks	while ((ch = getopt(argc, argv,
95249293Sed	    "bcCdDeE:f:F:I:ijk:K:lLmMnN:O:p:PqrR:s:StuUwWxX:"))
96244541Sbrooks	    != -1) {
97244541Sbrooks		switch((char)ch) {
98244541Sbrooks		case 'b':
99244541Sbrooks			bflag = 1;
100244541Sbrooks			break;
101244541Sbrooks		case 'c':
102244541Sbrooks			cflag = 1;
103244541Sbrooks			break;
104244541Sbrooks		case 'C':
105244541Sbrooks			Cflag = 1;
106244541Sbrooks			break;
107244541Sbrooks		case 'd':
108244541Sbrooks			dflag = 1;
109244541Sbrooks			break;
110244541Sbrooks		case 'D':
111244541Sbrooks			Dflag = 1;
112244541Sbrooks			break;
113244541Sbrooks		case 'E':
114244541Sbrooks			parsetags(&excludetags, optarg);
115244541Sbrooks			break;
116244541Sbrooks		case 'e':
117244541Sbrooks			eflag = 1;
118244541Sbrooks			break;
119244541Sbrooks		case 'f':
120244541Sbrooks			if (spec1 == stdin) {
121244541Sbrooks				spec1 = fopen(optarg, "r");
122244541Sbrooks				if (spec1 == NULL)
123244541Sbrooks					mtree_err("%s: %s", optarg,
124244541Sbrooks					    strerror(errno));
125244541Sbrooks			} else if (spec2 == NULL) {
126244541Sbrooks				spec2 = fopen(optarg, "r");
127244541Sbrooks				if (spec2 == NULL)
128244541Sbrooks					mtree_err("%s: %s", optarg,
129244541Sbrooks					    strerror(errno));
130244541Sbrooks			} else
131244541Sbrooks				usage();
132244541Sbrooks			break;
133244541Sbrooks		case 'F':
134244541Sbrooks			for (i = 0; i < __arraycount(flavors); i++)
135244541Sbrooks				if (strcmp(optarg, flavors[i].name) == 0) {
136244541Sbrooks					flavor = flavors[i].flavor;
137244541Sbrooks					break;
138244541Sbrooks				}
139244541Sbrooks			if (i == __arraycount(flavors))
140244541Sbrooks				usage();
141244541Sbrooks			break;
142244541Sbrooks		case 'i':
143244541Sbrooks			iflag = 1;
144244541Sbrooks			break;
145244541Sbrooks		case 'I':
146244541Sbrooks			parsetags(&includetags, optarg);
147244541Sbrooks			break;
148244541Sbrooks		case 'j':
149244541Sbrooks			jflag = 1;
150244541Sbrooks			break;
151244541Sbrooks		case 'k':
152244541Sbrooks			keys = F_TYPE;
153244541Sbrooks			while ((p = strsep(&optarg, " \t,")) != NULL)
154244541Sbrooks				if (*p != '\0')
155244541Sbrooks					keys |= parsekey(p, NULL);
156244541Sbrooks			break;
157244541Sbrooks		case 'K':
158244541Sbrooks			while ((p = strsep(&optarg, " \t,")) != NULL)
159244541Sbrooks				if (*p != '\0')
160244541Sbrooks					keys |= parsekey(p, NULL);
161244541Sbrooks			break;
162244541Sbrooks		case 'l':
163244541Sbrooks			lflag = 1;
164244541Sbrooks			break;
165244541Sbrooks		case 'L':
166244541Sbrooks			ftsoptions &= ~FTS_PHYSICAL;
167244541Sbrooks			ftsoptions |= FTS_LOGICAL;
168244541Sbrooks			break;
169244541Sbrooks		case 'm':
170244541Sbrooks			mflag = 1;
171244541Sbrooks			break;
172244541Sbrooks		case 'M':
173244541Sbrooks			mtree_Mflag = 1;
174244541Sbrooks			break;
175244541Sbrooks		case 'n':
176244541Sbrooks			nflag = 1;
177244541Sbrooks			break;
178244541Sbrooks		case 'N':
179244541Sbrooks			if (! setup_getid(optarg))
180244541Sbrooks				mtree_err(
181244541Sbrooks			    "Unable to use user and group databases in `%s'",
182244541Sbrooks				    optarg);
183244541Sbrooks			break;
184249293Sed		case 'O':
185249293Sed			load_only(optarg);
186249293Sed			break;
187244541Sbrooks		case 'p':
188244541Sbrooks			dir = optarg;
189244541Sbrooks			break;
190244541Sbrooks		case 'P':
191244541Sbrooks			ftsoptions &= ~FTS_LOGICAL;
192244541Sbrooks			ftsoptions |= FTS_PHYSICAL;
193244541Sbrooks			break;
194244541Sbrooks		case 'q':
195244541Sbrooks			qflag = 1;
196244541Sbrooks			break;
197244541Sbrooks		case 'r':
198244541Sbrooks			rflag = 1;
199244541Sbrooks			break;
200244541Sbrooks		case 'R':
201244541Sbrooks			while ((p = strsep(&optarg, " \t,")) != NULL)
202244541Sbrooks				if (*p != '\0')
203244541Sbrooks					keys &= ~parsekey(p, NULL);
204244541Sbrooks			break;
205244541Sbrooks		case 's':
206244541Sbrooks			sflag = 1;
207244541Sbrooks			crc_total = ~strtol(optarg, &p, 0);
208244541Sbrooks			if (*p)
209244541Sbrooks				mtree_err("illegal seed value -- %s", optarg);
210244541Sbrooks			break;
211244541Sbrooks		case 'S':
212244541Sbrooks			mtree_Sflag = 1;
213244541Sbrooks			break;
214244541Sbrooks		case 't':
215244541Sbrooks			tflag = 1;
216244541Sbrooks			break;
217244541Sbrooks		case 'u':
218244541Sbrooks			uflag = 1;
219244541Sbrooks			break;
220244541Sbrooks		case 'U':
221244541Sbrooks			Uflag = uflag = 1;
222244541Sbrooks			break;
223244541Sbrooks		case 'w':
224244541Sbrooks			wflag = 1;
225244541Sbrooks			break;
226244541Sbrooks		case 'W':
227244541Sbrooks			mtree_Wflag = 1;
228244541Sbrooks			break;
229244541Sbrooks		case 'x':
230244541Sbrooks			ftsoptions |= FTS_XDEV;
231244541Sbrooks			break;
232244541Sbrooks		case 'X':
233244541Sbrooks			read_excludes_file(optarg);
234244541Sbrooks			break;
235244541Sbrooks		case '?':
236244541Sbrooks		default:
237244541Sbrooks			usage();
238244541Sbrooks		}
239244541Sbrooks	}
240244541Sbrooks	argc -= optind;
241244541Sbrooks	argv += optind;
242244541Sbrooks
243244541Sbrooks	if (argc)
244244541Sbrooks		usage();
245244541Sbrooks
246244541Sbrooks	switch (flavor) {
247244541Sbrooks	case F_FREEBSD9:
248244541Sbrooks		if (cflag && iflag) {
249244541Sbrooks			warnx("-c and -i passed, replacing -i with -j for "
250244541Sbrooks			    "FreeBSD compatibility");
251244541Sbrooks			iflag = 0;
252244541Sbrooks			jflag = 1;
253244541Sbrooks		}
254244541Sbrooks		if (dflag && !bflag) {
255244541Sbrooks			warnx("Adding -b to -d for FreeBSD compatibility");
256244541Sbrooks			bflag = 1;
257244541Sbrooks		}
258244541Sbrooks		if (uflag && !iflag) {
259244541Sbrooks			warnx("Adding -i to -%c for FreeBSD compatibility",
260244541Sbrooks			    Uflag ? 'U' : 'u');
261244541Sbrooks			iflag = 1;
262244541Sbrooks		}
263244541Sbrooks		if (uflag && !tflag) {
264244541Sbrooks			warnx("Adding -t to -%c for FreeBSD compatibility",
265244541Sbrooks			    Uflag ? 'U' : 'u');
266244541Sbrooks			tflag = 1;
267244541Sbrooks		}
268244541Sbrooks		if (wflag)
269244541Sbrooks			warnx("The -w flag is a no-op");
270244541Sbrooks		break;
271244541Sbrooks	default:
272244541Sbrooks		if (wflag)
273244541Sbrooks			usage();
274244541Sbrooks	}
275244541Sbrooks
276244541Sbrooks	if (spec2 && (cflag || Cflag || Dflag))
277244541Sbrooks		mtree_err("Double -f, -c, -C and -D flags are mutually "
278244541Sbrooks		    "exclusive");
279244541Sbrooks
280244541Sbrooks	if (dir && spec2)
281244541Sbrooks		mtree_err("Double -f and -p flags are mutually exclusive");
282244541Sbrooks
283244541Sbrooks	if (dir && chdir(dir))
284244541Sbrooks		mtree_err("%s: %s", dir, strerror(errno));
285244541Sbrooks
286244541Sbrooks	if ((cflag || sflag) && !getcwd(fullpath, sizeof(fullpath)))
287244541Sbrooks		mtree_err("%s", strerror(errno));
288244541Sbrooks
289244541Sbrooks	if ((cflag && Cflag) || (cflag && Dflag) || (Cflag && Dflag))
290244541Sbrooks		mtree_err("-c, -C and -D flags are mutually exclusive");
291244541Sbrooks
292244541Sbrooks	if (iflag && mflag)
293244541Sbrooks		mtree_err("-i and -m flags are mutually exclusive");
294244541Sbrooks
295244541Sbrooks	if (lflag && uflag)
296244541Sbrooks		mtree_err("-l and -u flags are mutually exclusive");
297244541Sbrooks
298244541Sbrooks	if (cflag) {
299273796Sbrooks		cwalk(stdout);
300244541Sbrooks		exit(0);
301244541Sbrooks	}
302244541Sbrooks	if (Cflag || Dflag) {
303273796Sbrooks		dump_nodes(stdout, "", spec(spec1), Dflag);
304244541Sbrooks		exit(0);
305244541Sbrooks	}
306244541Sbrooks	if (spec2 != NULL)
307244541Sbrooks		status = mtree_specspec(spec1, spec2);
308244541Sbrooks	else
309244541Sbrooks		status = verify(spec1);
310244541Sbrooks	if (Uflag && (status == MISMATCHEXIT))
311244541Sbrooks		status = 0;
312244541Sbrooks	exit(status);
313244541Sbrooks}
314244541Sbrooks
315244541Sbrooksstatic void
316244541Sbrooksusage(void)
317244541Sbrooks{
318244541Sbrooks	unsigned int i;
319244541Sbrooks
320244541Sbrooks	fprintf(stderr,
321244541Sbrooks	    "usage: %s [-bCcDdejLlMnPqrStUuWx] [-i|-m] [-E tags]\n"
322244541Sbrooks	    "\t\t[-f spec] [-f spec]\n"
323244541Sbrooks	    "\t\t[-I tags] [-K keywords] [-k keywords] [-N dbdir] [-p path]\n"
324244541Sbrooks	    "\t\t[-R keywords] [-s seed] [-X exclude-file]\n"
325244541Sbrooks	    "\t\t[-F flavor]\n",
326244541Sbrooks	    getprogname());
327244541Sbrooks	fprintf(stderr, "\nflavors:");
328244541Sbrooks	for (i = 0; i < __arraycount(flavors); i++)
329244541Sbrooks		fprintf(stderr, " %s", flavors[i].name);
330244541Sbrooks	fprintf(stderr, "\n");
331244541Sbrooks	exit(1);
332244541Sbrooks}
333