mtree.c revision 1.45 1 /* $NetBSD: mtree.c,v 1.45 2012/12/20 18:58:37 mlelstv Exp $ */
2
3 /*-
4 * Copyright (c) 1989, 1990, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 #if HAVE_NBTOOL_CONFIG_H
33 #include "nbtool_config.h"
34 #endif
35
36 #include <sys/cdefs.h>
37 #if defined(__COPYRIGHT) && !defined(lint)
38 __COPYRIGHT("@(#) Copyright (c) 1989, 1990, 1993\
39 The Regents of the University of California. All rights reserved.");
40 #endif /* not lint */
41
42 #if defined(__RCSID) && !defined(lint)
43 #if 0
44 static char sccsid[] = "@(#)mtree.c 8.1 (Berkeley) 6/6/93";
45 #else
46 __RCSID("$NetBSD: mtree.c,v 1.45 2012/12/20 18:58:37 mlelstv Exp $");
47 #endif
48 #endif /* not lint */
49
50 #include <sys/param.h>
51 #include <sys/stat.h>
52
53 #include <errno.h>
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <unistd.h>
58
59 #include "extern.h"
60
61 int ftsoptions = FTS_PHYSICAL;
62 int bflag, cflag, Cflag, dflag, Dflag, eflag, iflag, jflag, lflag, mflag,
63 nflag, qflag, rflag, sflag, tflag, uflag, Uflag, wflag;
64 char fullpath[MAXPATHLEN];
65 enum flavor flavor = F_MTREE;
66
67 static struct {
68 enum flavor flavor;
69 const char name[9];
70 } flavors[] = {
71 {F_MTREE, "mtree"},
72 {F_FREEBSD9, "freebsd9"},
73 {F_NETBSD6, "netbsd6"},
74 };
75
76 __dead static void usage(void);
77
78 int
79 main(int argc, char **argv)
80 {
81 int ch, status;
82 unsigned int i;
83 char *dir, *p;
84 FILE *spec1, *spec2;
85
86 setprogname(argv[0]);
87
88 dir = NULL;
89 init_excludes();
90 spec1 = stdin;
91 spec2 = NULL;
92
93 while ((ch = getopt(argc, argv,
94 "bcCdDeE:f:F:I:ijk:K:lLmMnN:p:PqrR:s:StuUwWxX:"))
95 != -1) {
96 switch((char)ch) {
97 case 'b':
98 bflag = 1;
99 break;
100 case 'c':
101 cflag = 1;
102 break;
103 case 'C':
104 Cflag = 1;
105 break;
106 case 'd':
107 dflag = 1;
108 break;
109 case 'D':
110 Dflag = 1;
111 break;
112 case 'E':
113 parsetags(&excludetags, optarg);
114 break;
115 case 'e':
116 eflag = 1;
117 break;
118 case 'f':
119 if (spec1 == stdin) {
120 spec1 = fopen(optarg, "r");
121 if (spec1 == NULL)
122 mtree_err("%s: %s", optarg,
123 strerror(errno));
124 } else if (spec2 == NULL) {
125 spec2 = fopen(optarg, "r");
126 if (spec2 == NULL)
127 mtree_err("%s: %s", optarg,
128 strerror(errno));
129 } else
130 usage();
131 break;
132 case 'F':
133 for (i = 0; i < __arraycount(flavors); i++)
134 if (strcmp(optarg, flavors[i].name) == 0) {
135 flavor = flavors[i].flavor;
136 break;
137 }
138 if (i == __arraycount(flavors))
139 usage();
140 break;
141 case 'i':
142 iflag = 1;
143 break;
144 case 'I':
145 parsetags(&includetags, optarg);
146 break;
147 case 'j':
148 jflag = 1;
149 break;
150 case 'k':
151 keys = F_TYPE;
152 while ((p = strsep(&optarg, " \t,")) != NULL)
153 if (*p != '\0')
154 keys |= parsekey(p, NULL);
155 break;
156 case 'K':
157 while ((p = strsep(&optarg, " \t,")) != NULL)
158 if (*p != '\0')
159 keys |= parsekey(p, NULL);
160 break;
161 case 'l':
162 lflag = 1;
163 break;
164 case 'L':
165 ftsoptions &= ~FTS_PHYSICAL;
166 ftsoptions |= FTS_LOGICAL;
167 break;
168 case 'm':
169 mflag = 1;
170 break;
171 case 'M':
172 mtree_Mflag = 1;
173 break;
174 case 'n':
175 nflag = 1;
176 break;
177 case 'N':
178 if (! setup_getid(optarg))
179 mtree_err(
180 "Unable to use user and group databases in `%s'",
181 optarg);
182 break;
183 case 'p':
184 dir = optarg;
185 break;
186 case 'P':
187 ftsoptions &= ~FTS_LOGICAL;
188 ftsoptions |= FTS_PHYSICAL;
189 break;
190 case 'q':
191 qflag = 1;
192 break;
193 case 'r':
194 rflag = 1;
195 break;
196 case 'R':
197 while ((p = strsep(&optarg, " \t,")) != NULL)
198 if (*p != '\0')
199 keys &= ~parsekey(p, NULL);
200 break;
201 case 's':
202 sflag = 1;
203 crc_total = ~strtol(optarg, &p, 0);
204 if (*p)
205 mtree_err("illegal seed value -- %s", optarg);
206 break;
207 case 'S':
208 mtree_Sflag = 1;
209 break;
210 case 't':
211 tflag = 1;
212 break;
213 case 'u':
214 uflag = 1;
215 break;
216 case 'U':
217 Uflag = uflag = 1;
218 break;
219 case 'w':
220 wflag = 1;
221 break;
222 case 'W':
223 mtree_Wflag = 1;
224 break;
225 case 'x':
226 ftsoptions |= FTS_XDEV;
227 break;
228 case 'X':
229 read_excludes_file(optarg);
230 break;
231 case '?':
232 default:
233 usage();
234 }
235 }
236 argc -= optind;
237 argv += optind;
238
239 if (argc)
240 usage();
241
242 switch (flavor) {
243 case F_FREEBSD9:
244 if (cflag && iflag) {
245 warnx("-c and -i passed, replacing -i with -j for "
246 "FreeBSD compatibility");
247 iflag = 0;
248 jflag = 1;
249 }
250 if (dflag && !bflag) {
251 warnx("Adding -b to -d for FreeBSD compatibility");
252 bflag = 1;
253 }
254 if (uflag && !iflag) {
255 warnx("Adding -i to -%c for FreeBSD compatibility",
256 Uflag ? 'U' : 'u');
257 iflag = 1;
258 }
259 if (uflag && !tflag) {
260 warnx("Adding -t to -%c for FreeBSD compatibility",
261 Uflag ? 'U' : 'u');
262 tflag = 1;
263 }
264 if (wflag)
265 warnx("The -w flag is a no-op");
266 break;
267 default:
268 if (wflag)
269 usage();
270 }
271
272 if (spec2 && (cflag || Cflag || Dflag))
273 mtree_err("Double -f, -c, -C and -D flags are mutually "
274 "exclusive");
275
276 if (dir && spec2)
277 mtree_err("Double -f and -p flags are mutually exclusive");
278
279 if (dir && chdir(dir))
280 mtree_err("%s: %s", dir, strerror(errno));
281
282 if ((cflag || sflag) && !getcwd(fullpath, sizeof(fullpath)))
283 mtree_err("%s", strerror(errno));
284
285 if ((cflag && Cflag) || (cflag && Dflag) || (Cflag && Dflag))
286 mtree_err("-c, -C and -D flags are mutually exclusive");
287
288 if (iflag && mflag)
289 mtree_err("-i and -m flags are mutually exclusive");
290
291 if (lflag && uflag)
292 mtree_err("-l and -u flags are mutually exclusive");
293
294 if (cflag) {
295 cwalk();
296 exit(0);
297 }
298 if (Cflag || Dflag) {
299 dump_nodes("", spec(spec1), Dflag);
300 exit(0);
301 }
302 if (spec2 != NULL)
303 status = mtree_specspec(spec1, spec2);
304 else
305 status = verify(spec1);
306 if (Uflag && (status == MISMATCHEXIT))
307 status = 0;
308 exit(status);
309 }
310
311 static void
312 usage(void)
313 {
314 unsigned int i;
315
316 fprintf(stderr,
317 "usage: %s [-bCcDdejLlMnPqrStUuWx] [-i|-m] [-E tags]\n"
318 "\t\t[-f spec] [-f spec]\n"
319 "\t\t[-I tags] [-K keywords] [-k keywords] [-N dbdir] [-p path]\n"
320 "\t\t[-R keywords] [-s seed] [-X exclude-file]\n"
321 "\t\t[-F flavor]\n",
322 getprogname());
323 fprintf(stderr, "\nflavors:");
324 for (i = 0; i < __arraycount(flavors); i++)
325 fprintf(stderr, " %s", flavors[i].name);
326 fprintf(stderr, "\n");
327 exit(1);
328 }
329