mtree.c revision 274101
156160Sru/* $NetBSD: mtree.c,v 1.49 2014/04/24 17:22:41 christos Exp $ */ 256160Sru 356160Sru/*- 456160Sru * Copyright (c) 1989, 1990, 1993 556160Sru * The Regents of the University of California. All rights reserved. 656160Sru * 756160Sru * Redistribution and use in source and binary forms, with or without 856160Sru * modification, are permitted provided that the following conditions 956160Sru * are met: 1056160Sru * 1. Redistributions of source code must retain the above copyright 1156160Sru * notice, this list of conditions and the following disclaimer. 1256160Sru * 2. Redistributions in binary form must reproduce the above copyright 1356160Sru * notice, this list of conditions and the following disclaimer in the 1456160Sru * documentation and/or other materials provided with the distribution. 1556160Sru * 3. Neither the name of the University nor the names of its contributors 1656160Sru * may be used to endorse or promote products derived from this software 1756160Sru * without specific prior written permission. 1856160Sru * 1956160Sru * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2056160Sru * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2156160Sru * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2256160Sru * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2356160Sru * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2456160Sru * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2556160Sru * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2656160Sru * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2756160Sru * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2856160Sru * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2956160Sru * SUCH DAMAGE. 3056160Sru */ 3156160Sru 3256160Sru#if HAVE_NBTOOL_CONFIG_H 3356160Sru#include "nbtool_config.h" 3456160Sru#endif 3556160Sru 3656160Sru#include <sys/cdefs.h> 3756160Sru#if defined(__COPYRIGHT) && !defined(lint) 3856160Sru__COPYRIGHT("@(#) Copyright (c) 1989, 1990, 1993\ 3956160Sru The Regents of the University of California. All rights reserved."); 4056160Sru#endif /* not lint */ 4156160Sru 4256160Sru#if defined(__RCSID) && !defined(lint) 4356160Sru#if 0 4456160Srustatic char sccsid[] = "@(#)mtree.c 8.1 (Berkeley) 6/6/93"; 4556160Sru#else 4656160Sru__RCSID("$NetBSD: mtree.c,v 1.49 2014/04/24 17:22:41 christos Exp $"); 4756160Sru#endif 4856160Sru#endif /* not lint */ 4956160Sru 5056160Sru#include <sys/param.h> 5156160Sru#include <sys/stat.h> 5256160Sru 5356160Sru#include <errno.h> 5456160Sru#include <stdio.h> 5556160Sru#include <stdlib.h> 5656160Sru#include <string.h> 5756160Sru#include <unistd.h> 5856160Sru 5956160Sru#include "extern.h" 6056160Sru 6156160Sruint ftsoptions = FTS_PHYSICAL; 6256160Sruint bflag, dflag, eflag, iflag, jflag, lflag, mflag, nflag, qflag, rflag, 6356160Sru sflag, tflag, uflag; 6456160Sruchar fullpath[MAXPATHLEN]; 6556160Sru 6656160Srustatic struct { 6756160Sru enum flavor flavor; 6856160Sru const char name[9]; 6956160Sru} flavors[] = { 7056160Sru {F_MTREE, "mtree"}, 7156160Sru {F_FREEBSD9, "freebsd9"}, 7256160Sru {F_NETBSD6, "netbsd6"}, 7356160Sru}; 7456160Sru 7556160Sru__dead static void usage(void); 7656160Sru 7756160Sruint 7856160Srumain(int argc, char **argv) 7956160Sru{ 8056160Sru int ch, status; 8156160Sru unsigned int i; 8256160Sru int cflag, Cflag, Dflag, Uflag, wflag; 8356160Sru char *dir, *p; 8456160Sru FILE *spec1, *spec2; 8556160Sru 8656160Sru setprogname(argv[0]); 8756160Sru 8856160Sru cflag = Cflag = Dflag = Uflag = wflag = 0; 8956160Sru dir = NULL; 9056160Sru init_excludes(); 9156160Sru spec1 = stdin; 9256160Sru spec2 = NULL; 9356160Sru 9456160Sru while ((ch = getopt(argc, argv, 9556160Sru "bcCdDeE:f:F:I:ijk:K:lLmMnN:O:p:PqrR:s:StuUwWxX:")) 9656160Sru != -1) { 9756160Sru switch((char)ch) { 9856160Sru case 'b': 9956160Sru bflag = 1; 10056160Sru break; 10156160Sru case 'c': 10256160Sru cflag = 1; 10356160Sru break; 10456160Sru case 'C': 10556160Sru Cflag = 1; 10656160Sru break; 10756160Sru case 'd': 10856160Sru dflag = 1; 10956160Sru break; 11056160Sru case 'D': 11156160Sru Dflag = 1; 11256160Sru break; 11356160Sru case 'E': 11456160Sru parsetags(&excludetags, optarg); 11556160Sru break; 11656160Sru case 'e': 11756160Sru eflag = 1; 11856160Sru break; 11956160Sru case 'f': 12056160Sru if (spec1 == stdin) { 12156160Sru spec1 = fopen(optarg, "r"); 12256160Sru if (spec1 == NULL) 12356160Sru mtree_err("%s: %s", optarg, 12456160Sru strerror(errno)); 12556160Sru } else if (spec2 == NULL) { 12656160Sru spec2 = fopen(optarg, "r"); 12756160Sru if (spec2 == NULL) 12856160Sru mtree_err("%s: %s", optarg, 12956160Sru strerror(errno)); 13056160Sru } else 13156160Sru usage(); 13256160Sru break; 13356160Sru case 'F': 13456160Sru for (i = 0; i < __arraycount(flavors); i++) 13556160Sru if (strcmp(optarg, flavors[i].name) == 0) { 13656160Sru flavor = flavors[i].flavor; 13756160Sru break; 13856160Sru } 13956160Sru if (i == __arraycount(flavors)) 14056160Sru usage(); 14156160Sru break; 14256160Sru case 'i': 14356160Sru iflag = 1; 14456160Sru break; 14556160Sru case 'I': 14656160Sru parsetags(&includetags, optarg); 14756160Sru break; 14856160Sru case 'j': 14956160Sru jflag = 1; 15056160Sru break; 15156160Sru case 'k': 15256160Sru keys = F_TYPE; 15356160Sru while ((p = strsep(&optarg, " \t,")) != NULL) 15456160Sru if (*p != '\0') 15556160Sru keys |= parsekey(p, NULL); 15656160Sru break; 15756160Sru case 'K': 15856160Sru while ((p = strsep(&optarg, " \t,")) != NULL) 15956160Sru if (*p != '\0') 16056160Sru keys |= parsekey(p, NULL); 16156160Sru break; 16256160Sru case 'l': 16356160Sru lflag = 1; 16456160Sru break; 16556160Sru case 'L': 16656160Sru ftsoptions &= ~FTS_PHYSICAL; 16756160Sru ftsoptions |= FTS_LOGICAL; 16856160Sru break; 16956160Sru case 'm': 17056160Sru mflag = 1; 17156160Sru break; 17256160Sru case 'M': 17356160Sru mtree_Mflag = 1; 17456160Sru break; 17556160Sru case 'n': 17656160Sru nflag = 1; 17756160Sru break; 17856160Sru case 'N': 17956160Sru if (! setup_getid(optarg)) 18056160Sru mtree_err( 18156160Sru "Unable to use user and group databases in `%s'", 18256160Sru optarg); 183 break; 184 case 'O': 185 load_only(optarg); 186 break; 187 case 'p': 188 dir = optarg; 189 break; 190 case 'P': 191 ftsoptions &= ~FTS_LOGICAL; 192 ftsoptions |= FTS_PHYSICAL; 193 break; 194 case 'q': 195 qflag = 1; 196 break; 197 case 'r': 198 rflag = 1; 199 break; 200 case 'R': 201 while ((p = strsep(&optarg, " \t,")) != NULL) 202 if (*p != '\0') 203 keys &= ~parsekey(p, NULL); 204 break; 205 case 's': 206 sflag = 1; 207 crc_total = ~strtol(optarg, &p, 0); 208 if (*p) 209 mtree_err("illegal seed value -- %s", optarg); 210 break; 211 case 'S': 212 mtree_Sflag = 1; 213 break; 214 case 't': 215 tflag = 1; 216 break; 217 case 'u': 218 uflag = 1; 219 break; 220 case 'U': 221 Uflag = uflag = 1; 222 break; 223 case 'w': 224 wflag = 1; 225 break; 226 case 'W': 227 mtree_Wflag = 1; 228 break; 229 case 'x': 230 ftsoptions |= FTS_XDEV; 231 break; 232 case 'X': 233 read_excludes_file(optarg); 234 break; 235 case '?': 236 default: 237 usage(); 238 } 239 } 240 argc -= optind; 241 argv += optind; 242 243 if (argc) 244 usage(); 245 246 switch (flavor) { 247 case F_FREEBSD9: 248 if (cflag && iflag) { 249 warnx("-c and -i passed, replacing -i with -j for " 250 "FreeBSD compatibility"); 251 iflag = 0; 252 jflag = 1; 253 } 254 if (dflag && !bflag) { 255 warnx("Adding -b to -d for FreeBSD compatibility"); 256 bflag = 1; 257 } 258 if (uflag && !iflag) { 259 warnx("Adding -i to -%c for FreeBSD compatibility", 260 Uflag ? 'U' : 'u'); 261 iflag = 1; 262 } 263 if (uflag && !tflag) { 264 warnx("Adding -t to -%c for FreeBSD compatibility", 265 Uflag ? 'U' : 'u'); 266 tflag = 1; 267 } 268 if (wflag) 269 warnx("The -w flag is a no-op"); 270 break; 271 default: 272 if (wflag) 273 usage(); 274 } 275 276 if (spec2 && (cflag || Cflag || Dflag)) 277 mtree_err("Double -f, -c, -C and -D flags are mutually " 278 "exclusive"); 279 280 if (dir && spec2) 281 mtree_err("Double -f and -p flags are mutually exclusive"); 282 283 if (dir && chdir(dir)) 284 mtree_err("%s: %s", dir, strerror(errno)); 285 286 if ((cflag || sflag) && !getcwd(fullpath, sizeof(fullpath))) 287 mtree_err("%s", strerror(errno)); 288 289 if ((cflag && Cflag) || (cflag && Dflag) || (Cflag && Dflag)) 290 mtree_err("-c, -C and -D flags are mutually exclusive"); 291 292 if (iflag && mflag) 293 mtree_err("-i and -m flags are mutually exclusive"); 294 295 if (lflag && uflag) 296 mtree_err("-l and -u flags are mutually exclusive"); 297 298 if (cflag) { 299 cwalk(stdout); 300 exit(0); 301 } 302 if (Cflag || Dflag) { 303 dump_nodes(stdout, "", spec(spec1), Dflag); 304 exit(0); 305 } 306 if (spec2 != NULL) 307 status = mtree_specspec(spec1, spec2); 308 else 309 status = verify(spec1); 310 if (Uflag && (status == MISMATCHEXIT)) 311 status = 0; 312 exit(status); 313} 314 315static void 316usage(void) 317{ 318 unsigned int i; 319 320 fprintf(stderr, 321 "usage: %s [-bCcDdejLlMnPqrStUuWx] [-i|-m] [-E tags]\n" 322 "\t\t[-f spec] [-f spec]\n" 323 "\t\t[-I tags] [-K keywords] [-k keywords] [-N dbdir] [-p path]\n" 324 "\t\t[-R keywords] [-s seed] [-X exclude-file]\n" 325 "\t\t[-F flavor]\n", 326 getprogname()); 327 fprintf(stderr, "\nflavors:"); 328 for (i = 0; i < __arraycount(flavors); i++) 329 fprintf(stderr, " %s", flavors[i].name); 330 fprintf(stderr, "\n"); 331 exit(1); 332} 333