]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/mtree/mtree.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / mtree / mtree.c
1 /*      $NetBSD: mtree.c,v 1.46 2012/12/20 19:09:25 christos 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.46 2012/12/20 19:09:25 christos 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
66 static struct {
67         enum flavor flavor;
68         const char name[9];
69 } flavors[] = {
70         {F_MTREE, "mtree"},
71         {F_FREEBSD9, "freebsd9"},
72         {F_NETBSD6, "netbsd6"},
73 };
74
75 __dead static   void    usage(void);
76
77 int
78 main(int argc, char **argv)
79 {
80         int     ch, status;
81         unsigned int    i;
82         char    *dir, *p;
83         FILE    *spec1, *spec2;
84
85         setprogname(argv[0]);
86
87         dir = NULL;
88         init_excludes();
89         spec1 = stdin;
90         spec2 = NULL;
91
92         while ((ch = getopt(argc, argv,
93             "bcCdDeE:f:F:I:ijk:K:lLmMnN:p:PqrR:s:StuUwWxX:"))
94             != -1) {
95                 switch((char)ch) {
96                 case 'b':
97                         bflag = 1;
98                         break;
99                 case 'c':
100                         cflag = 1;
101                         break;
102                 case 'C':
103                         Cflag = 1;
104                         break;
105                 case 'd':
106                         dflag = 1;
107                         break;
108                 case 'D':
109                         Dflag = 1;
110                         break;
111                 case 'E':
112                         parsetags(&excludetags, optarg);
113                         break;
114                 case 'e':
115                         eflag = 1;
116                         break;
117                 case 'f':
118                         if (spec1 == stdin) {
119                                 spec1 = fopen(optarg, "r");
120                                 if (spec1 == NULL)
121                                         mtree_err("%s: %s", optarg,
122                                             strerror(errno));
123                         } else if (spec2 == NULL) {
124                                 spec2 = fopen(optarg, "r");
125                                 if (spec2 == NULL)
126                                         mtree_err("%s: %s", optarg,
127                                             strerror(errno));
128                         } else
129                                 usage();
130                         break;
131                 case 'F':
132                         for (i = 0; i < __arraycount(flavors); i++)
133                                 if (strcmp(optarg, flavors[i].name) == 0) {
134                                         flavor = flavors[i].flavor;
135                                         break;
136                                 }
137                         if (i == __arraycount(flavors))
138                                 usage();
139                         break;
140                 case 'i':
141                         iflag = 1;
142                         break;
143                 case 'I':
144                         parsetags(&includetags, optarg);
145                         break;
146                 case 'j':
147                         jflag = 1;
148                         break;
149                 case 'k':
150                         keys = F_TYPE;
151                         while ((p = strsep(&optarg, " \t,")) != NULL)
152                                 if (*p != '\0')
153                                         keys |= parsekey(p, NULL);
154                         break;
155                 case 'K':
156                         while ((p = strsep(&optarg, " \t,")) != NULL)
157                                 if (*p != '\0')
158                                         keys |= parsekey(p, NULL);
159                         break;
160                 case 'l':
161                         lflag = 1;
162                         break;
163                 case 'L':
164                         ftsoptions &= ~FTS_PHYSICAL;
165                         ftsoptions |= FTS_LOGICAL;
166                         break;
167                 case 'm':
168                         mflag = 1;
169                         break;
170                 case 'M':
171                         mtree_Mflag = 1;
172                         break;
173                 case 'n':
174                         nflag = 1;
175                         break;
176                 case 'N':
177                         if (! setup_getid(optarg))
178                                 mtree_err(
179                             "Unable to use user and group databases in `%s'",
180                                     optarg);
181                         break;
182                 case 'p':
183                         dir = optarg;
184                         break;
185                 case 'P':
186                         ftsoptions &= ~FTS_LOGICAL;
187                         ftsoptions |= FTS_PHYSICAL;
188                         break;
189                 case 'q':
190                         qflag = 1;
191                         break;
192                 case 'r':
193                         rflag = 1;
194                         break;
195                 case 'R':
196                         while ((p = strsep(&optarg, " \t,")) != NULL)
197                                 if (*p != '\0')
198                                         keys &= ~parsekey(p, NULL);
199                         break;
200                 case 's':
201                         sflag = 1;
202                         crc_total = ~strtol(optarg, &p, 0);
203                         if (*p)
204                                 mtree_err("illegal seed value -- %s", optarg);
205                         break;
206                 case 'S':
207                         mtree_Sflag = 1;
208                         break;
209                 case 't':
210                         tflag = 1;
211                         break;
212                 case 'u':
213                         uflag = 1;
214                         break;
215                 case 'U':
216                         Uflag = uflag = 1;
217                         break;
218                 case 'w':
219                         wflag = 1;
220                         break;
221                 case 'W':
222                         mtree_Wflag = 1;
223                         break;
224                 case 'x':
225                         ftsoptions |= FTS_XDEV;
226                         break;
227                 case 'X':
228                         read_excludes_file(optarg);
229                         break;
230                 case '?':
231                 default:
232                         usage();
233                 }
234         }
235         argc -= optind;
236         argv += optind;
237
238         if (argc)
239                 usage();
240
241         switch (flavor) {
242         case F_FREEBSD9:
243                 if (cflag && iflag) {
244                         warnx("-c and -i passed, replacing -i with -j for "
245                             "FreeBSD compatibility");
246                         iflag = 0;
247                         jflag = 1;
248                 }
249                 if (dflag && !bflag) {
250                         warnx("Adding -b to -d for FreeBSD compatibility");
251                         bflag = 1;
252                 }
253                 if (uflag && !iflag) {
254                         warnx("Adding -i to -%c for FreeBSD compatibility",
255                             Uflag ? 'U' : 'u');
256                         iflag = 1;
257                 }
258                 if (uflag && !tflag) {
259                         warnx("Adding -t to -%c for FreeBSD compatibility",
260                             Uflag ? 'U' : 'u');
261                         tflag = 1;
262                 }
263                 if (wflag)
264                         warnx("The -w flag is a no-op");
265                 break;
266         default:
267                 if (wflag)
268                         usage();
269         }
270
271         if (spec2 && (cflag || Cflag || Dflag))
272                 mtree_err("Double -f, -c, -C and -D flags are mutually "
273                     "exclusive");
274
275         if (dir && spec2)
276                 mtree_err("Double -f and -p flags are mutually exclusive");
277
278         if (dir && chdir(dir))
279                 mtree_err("%s: %s", dir, strerror(errno));
280
281         if ((cflag || sflag) && !getcwd(fullpath, sizeof(fullpath)))
282                 mtree_err("%s", strerror(errno));
283
284         if ((cflag && Cflag) || (cflag && Dflag) || (Cflag && Dflag))
285                 mtree_err("-c, -C and -D flags are mutually exclusive");
286
287         if (iflag && mflag)
288                 mtree_err("-i and -m flags are mutually exclusive");
289
290         if (lflag && uflag)
291                 mtree_err("-l and -u flags are mutually exclusive");
292
293         if (cflag) {
294                 cwalk();
295                 exit(0);
296         }
297         if (Cflag || Dflag) {
298                 dump_nodes("", spec(spec1), Dflag);
299                 exit(0);
300         }
301         if (spec2 != NULL)
302                 status = mtree_specspec(spec1, spec2);
303         else
304                 status = verify(spec1);
305         if (Uflag && (status == MISMATCHEXIT))
306                 status = 0;
307         exit(status);
308 }
309
310 static void
311 usage(void)
312 {
313         unsigned int i;
314
315         fprintf(stderr,
316             "usage: %s [-bCcDdejLlMnPqrStUuWx] [-i|-m] [-E tags]\n"
317             "\t\t[-f spec] [-f spec]\n"
318             "\t\t[-I tags] [-K keywords] [-k keywords] [-N dbdir] [-p path]\n"
319             "\t\t[-R keywords] [-s seed] [-X exclude-file]\n"
320             "\t\t[-F flavor]\n",
321             getprogname());
322         fprintf(stderr, "\nflavors:");
323         for (i = 0; i < __arraycount(flavors); i++)
324                 fprintf(stderr, " %s", flavors[i].name);
325         fprintf(stderr, "\n");
326         exit(1);
327 }