1*c6ec7d31SBrooks Davis /* $NetBSD: verify.c,v 1.43 2012/10/05 01:31:05 christos Exp $ */ 2*c6ec7d31SBrooks Davis 3*c6ec7d31SBrooks Davis /*- 4*c6ec7d31SBrooks Davis * Copyright (c) 1990, 1993 5*c6ec7d31SBrooks Davis * The Regents of the University of California. All rights reserved. 6*c6ec7d31SBrooks Davis * 7*c6ec7d31SBrooks Davis * Redistribution and use in source and binary forms, with or without 8*c6ec7d31SBrooks Davis * modification, are permitted provided that the following conditions 9*c6ec7d31SBrooks Davis * are met: 10*c6ec7d31SBrooks Davis * 1. Redistributions of source code must retain the above copyright 11*c6ec7d31SBrooks Davis * notice, this list of conditions and the following disclaimer. 12*c6ec7d31SBrooks Davis * 2. Redistributions in binary form must reproduce the above copyright 13*c6ec7d31SBrooks Davis * notice, this list of conditions and the following disclaimer in the 14*c6ec7d31SBrooks Davis * documentation and/or other materials provided with the distribution. 15*c6ec7d31SBrooks Davis * 3. Neither the name of the University nor the names of its contributors 16*c6ec7d31SBrooks Davis * may be used to endorse or promote products derived from this software 17*c6ec7d31SBrooks Davis * without specific prior written permission. 18*c6ec7d31SBrooks Davis * 19*c6ec7d31SBrooks Davis * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20*c6ec7d31SBrooks Davis * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21*c6ec7d31SBrooks Davis * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22*c6ec7d31SBrooks Davis * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23*c6ec7d31SBrooks Davis * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24*c6ec7d31SBrooks Davis * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25*c6ec7d31SBrooks Davis * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26*c6ec7d31SBrooks Davis * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27*c6ec7d31SBrooks Davis * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28*c6ec7d31SBrooks Davis * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29*c6ec7d31SBrooks Davis * SUCH DAMAGE. 30*c6ec7d31SBrooks Davis */ 31*c6ec7d31SBrooks Davis 32*c6ec7d31SBrooks Davis #if HAVE_NBTOOL_CONFIG_H 33*c6ec7d31SBrooks Davis #include "nbtool_config.h" 34*c6ec7d31SBrooks Davis #endif 35*c6ec7d31SBrooks Davis 36*c6ec7d31SBrooks Davis #include <sys/cdefs.h> 37*c6ec7d31SBrooks Davis #if defined(__RCSID) && !defined(lint) 38*c6ec7d31SBrooks Davis #if 0 39*c6ec7d31SBrooks Davis static char sccsid[] = "@(#)verify.c 8.1 (Berkeley) 6/6/93"; 40*c6ec7d31SBrooks Davis #else 41*c6ec7d31SBrooks Davis __RCSID("$NetBSD: verify.c,v 1.43 2012/10/05 01:31:05 christos Exp $"); 42*c6ec7d31SBrooks Davis #endif 43*c6ec7d31SBrooks Davis #endif /* not lint */ 44*c6ec7d31SBrooks Davis 45*c6ec7d31SBrooks Davis #include <sys/param.h> 46*c6ec7d31SBrooks Davis #include <sys/stat.h> 47*c6ec7d31SBrooks Davis 48*c6ec7d31SBrooks Davis #if ! HAVE_NBTOOL_CONFIG_H 49*c6ec7d31SBrooks Davis #include <dirent.h> 50*c6ec7d31SBrooks Davis #endif 51*c6ec7d31SBrooks Davis 52*c6ec7d31SBrooks Davis #include <errno.h> 53*c6ec7d31SBrooks Davis #include <fnmatch.h> 54*c6ec7d31SBrooks Davis #include <stdio.h> 55*c6ec7d31SBrooks Davis #include <string.h> 56*c6ec7d31SBrooks Davis #include <unistd.h> 57*c6ec7d31SBrooks Davis 58*c6ec7d31SBrooks Davis #include "extern.h" 59*c6ec7d31SBrooks Davis 60*c6ec7d31SBrooks Davis static NODE *root; 61*c6ec7d31SBrooks Davis static char path[MAXPATHLEN]; 62*c6ec7d31SBrooks Davis 63*c6ec7d31SBrooks Davis static void miss(NODE *, char *); 64*c6ec7d31SBrooks Davis static int vwalk(void); 65*c6ec7d31SBrooks Davis 66*c6ec7d31SBrooks Davis int 67*c6ec7d31SBrooks Davis verify(FILE *fi) 68*c6ec7d31SBrooks Davis { 69*c6ec7d31SBrooks Davis int rval; 70*c6ec7d31SBrooks Davis 71*c6ec7d31SBrooks Davis root = spec(fi); 72*c6ec7d31SBrooks Davis rval = vwalk(); 73*c6ec7d31SBrooks Davis miss(root, path); 74*c6ec7d31SBrooks Davis return (rval); 75*c6ec7d31SBrooks Davis } 76*c6ec7d31SBrooks Davis 77*c6ec7d31SBrooks Davis static int 78*c6ec7d31SBrooks Davis vwalk(void) 79*c6ec7d31SBrooks Davis { 80*c6ec7d31SBrooks Davis FTS *t; 81*c6ec7d31SBrooks Davis FTSENT *p; 82*c6ec7d31SBrooks Davis NODE *ep, *level; 83*c6ec7d31SBrooks Davis int specdepth, rval; 84*c6ec7d31SBrooks Davis char *argv[2]; 85*c6ec7d31SBrooks Davis char dot[] = "."; 86*c6ec7d31SBrooks Davis argv[0] = dot; 87*c6ec7d31SBrooks Davis argv[1] = NULL; 88*c6ec7d31SBrooks Davis 89*c6ec7d31SBrooks Davis if ((t = fts_open(argv, ftsoptions, NULL)) == NULL) 90*c6ec7d31SBrooks Davis mtree_err("fts_open: %s", strerror(errno)); 91*c6ec7d31SBrooks Davis level = root; 92*c6ec7d31SBrooks Davis specdepth = rval = 0; 93*c6ec7d31SBrooks Davis while ((p = fts_read(t)) != NULL) { 94*c6ec7d31SBrooks Davis if (check_excludes(p->fts_name, p->fts_path)) { 95*c6ec7d31SBrooks Davis fts_set(t, p, FTS_SKIP); 96*c6ec7d31SBrooks Davis continue; 97*c6ec7d31SBrooks Davis } 98*c6ec7d31SBrooks Davis switch(p->fts_info) { 99*c6ec7d31SBrooks Davis case FTS_D: 100*c6ec7d31SBrooks Davis case FTS_SL: 101*c6ec7d31SBrooks Davis break; 102*c6ec7d31SBrooks Davis case FTS_DP: 103*c6ec7d31SBrooks Davis if (specdepth > p->fts_level) { 104*c6ec7d31SBrooks Davis for (level = level->parent; level->prev; 105*c6ec7d31SBrooks Davis level = level->prev) 106*c6ec7d31SBrooks Davis continue; 107*c6ec7d31SBrooks Davis --specdepth; 108*c6ec7d31SBrooks Davis } 109*c6ec7d31SBrooks Davis continue; 110*c6ec7d31SBrooks Davis case FTS_DNR: 111*c6ec7d31SBrooks Davis case FTS_ERR: 112*c6ec7d31SBrooks Davis case FTS_NS: 113*c6ec7d31SBrooks Davis warnx("%s: %s", RP(p), strerror(p->fts_errno)); 114*c6ec7d31SBrooks Davis continue; 115*c6ec7d31SBrooks Davis default: 116*c6ec7d31SBrooks Davis if (dflag) 117*c6ec7d31SBrooks Davis continue; 118*c6ec7d31SBrooks Davis } 119*c6ec7d31SBrooks Davis 120*c6ec7d31SBrooks Davis if (specdepth != p->fts_level) 121*c6ec7d31SBrooks Davis goto extra; 122*c6ec7d31SBrooks Davis for (ep = level; ep; ep = ep->next) 123*c6ec7d31SBrooks Davis if ((ep->flags & F_MAGIC && 124*c6ec7d31SBrooks Davis !fnmatch(ep->name, p->fts_name, FNM_PATHNAME)) || 125*c6ec7d31SBrooks Davis !strcmp(ep->name, p->fts_name)) { 126*c6ec7d31SBrooks Davis ep->flags |= F_VISIT; 127*c6ec7d31SBrooks Davis if ((ep->flags & F_NOCHANGE) == 0 && 128*c6ec7d31SBrooks Davis compare(ep, p)) 129*c6ec7d31SBrooks Davis rval = MISMATCHEXIT; 130*c6ec7d31SBrooks Davis if (!(ep->flags & F_IGN) && 131*c6ec7d31SBrooks Davis ep->type == F_DIR && 132*c6ec7d31SBrooks Davis p->fts_info == FTS_D) { 133*c6ec7d31SBrooks Davis if (ep->child) { 134*c6ec7d31SBrooks Davis level = ep->child; 135*c6ec7d31SBrooks Davis ++specdepth; 136*c6ec7d31SBrooks Davis } 137*c6ec7d31SBrooks Davis } else 138*c6ec7d31SBrooks Davis fts_set(t, p, FTS_SKIP); 139*c6ec7d31SBrooks Davis break; 140*c6ec7d31SBrooks Davis } 141*c6ec7d31SBrooks Davis 142*c6ec7d31SBrooks Davis if (ep) 143*c6ec7d31SBrooks Davis continue; 144*c6ec7d31SBrooks Davis extra: 145*c6ec7d31SBrooks Davis if (!eflag && !(dflag && p->fts_info == FTS_SL)) { 146*c6ec7d31SBrooks Davis printf("extra: %s", RP(p)); 147*c6ec7d31SBrooks Davis if (rflag) { 148*c6ec7d31SBrooks Davis if ((S_ISDIR(p->fts_statp->st_mode) 149*c6ec7d31SBrooks Davis ? rmdir : unlink)(p->fts_accpath)) { 150*c6ec7d31SBrooks Davis printf(", not removed: %s", 151*c6ec7d31SBrooks Davis strerror(errno)); 152*c6ec7d31SBrooks Davis } else 153*c6ec7d31SBrooks Davis printf(", removed"); 154*c6ec7d31SBrooks Davis } 155*c6ec7d31SBrooks Davis putchar('\n'); 156*c6ec7d31SBrooks Davis } 157*c6ec7d31SBrooks Davis fts_set(t, p, FTS_SKIP); 158*c6ec7d31SBrooks Davis } 159*c6ec7d31SBrooks Davis fts_close(t); 160*c6ec7d31SBrooks Davis if (sflag) 161*c6ec7d31SBrooks Davis warnx("%s checksum: %u", fullpath, crc_total); 162*c6ec7d31SBrooks Davis return (rval); 163*c6ec7d31SBrooks Davis } 164*c6ec7d31SBrooks Davis 165*c6ec7d31SBrooks Davis static void 166*c6ec7d31SBrooks Davis miss(NODE *p, char *tail) 167*c6ec7d31SBrooks Davis { 168*c6ec7d31SBrooks Davis int create; 169*c6ec7d31SBrooks Davis char *tp; 170*c6ec7d31SBrooks Davis const char *type; 171*c6ec7d31SBrooks Davis u_int32_t flags; 172*c6ec7d31SBrooks Davis 173*c6ec7d31SBrooks Davis for (; p; p = p->next) { 174*c6ec7d31SBrooks Davis if (p->flags & F_OPT && !(p->flags & F_VISIT)) 175*c6ec7d31SBrooks Davis continue; 176*c6ec7d31SBrooks Davis if (p->type != F_DIR && (dflag || p->flags & F_VISIT)) 177*c6ec7d31SBrooks Davis continue; 178*c6ec7d31SBrooks Davis strcpy(tail, p->name); 179*c6ec7d31SBrooks Davis if (!(p->flags & F_VISIT)) { 180*c6ec7d31SBrooks Davis /* Don't print missing message if file exists as a 181*c6ec7d31SBrooks Davis symbolic link and the -q flag is set. */ 182*c6ec7d31SBrooks Davis struct stat statbuf; 183*c6ec7d31SBrooks Davis 184*c6ec7d31SBrooks Davis if (qflag && stat(path, &statbuf) == 0 && 185*c6ec7d31SBrooks Davis S_ISDIR(statbuf.st_mode)) 186*c6ec7d31SBrooks Davis p->flags |= F_VISIT; 187*c6ec7d31SBrooks Davis else 188*c6ec7d31SBrooks Davis (void)printf("%s missing", path); 189*c6ec7d31SBrooks Davis } 190*c6ec7d31SBrooks Davis switch (p->type) { 191*c6ec7d31SBrooks Davis case F_BLOCK: 192*c6ec7d31SBrooks Davis case F_CHAR: 193*c6ec7d31SBrooks Davis type = "device"; 194*c6ec7d31SBrooks Davis break; 195*c6ec7d31SBrooks Davis case F_DIR: 196*c6ec7d31SBrooks Davis type = "directory"; 197*c6ec7d31SBrooks Davis break; 198*c6ec7d31SBrooks Davis case F_LINK: 199*c6ec7d31SBrooks Davis type = "symlink"; 200*c6ec7d31SBrooks Davis break; 201*c6ec7d31SBrooks Davis default: 202*c6ec7d31SBrooks Davis putchar('\n'); 203*c6ec7d31SBrooks Davis continue; 204*c6ec7d31SBrooks Davis } 205*c6ec7d31SBrooks Davis 206*c6ec7d31SBrooks Davis create = 0; 207*c6ec7d31SBrooks Davis if (!(p->flags & F_VISIT) && uflag) { 208*c6ec7d31SBrooks Davis if (mtree_Wflag || p->type == F_LINK) 209*c6ec7d31SBrooks Davis goto createit; 210*c6ec7d31SBrooks Davis if (!(p->flags & (F_UID | F_UNAME))) 211*c6ec7d31SBrooks Davis printf( 212*c6ec7d31SBrooks Davis " (%s not created: user not specified)", type); 213*c6ec7d31SBrooks Davis else if (!(p->flags & (F_GID | F_GNAME))) 214*c6ec7d31SBrooks Davis printf( 215*c6ec7d31SBrooks Davis " (%s not created: group not specified)", type); 216*c6ec7d31SBrooks Davis else if (!(p->flags & F_MODE)) 217*c6ec7d31SBrooks Davis printf( 218*c6ec7d31SBrooks Davis " (%s not created: mode not specified)", type); 219*c6ec7d31SBrooks Davis else 220*c6ec7d31SBrooks Davis createit: 221*c6ec7d31SBrooks Davis switch (p->type) { 222*c6ec7d31SBrooks Davis case F_BLOCK: 223*c6ec7d31SBrooks Davis case F_CHAR: 224*c6ec7d31SBrooks Davis if (mtree_Wflag) 225*c6ec7d31SBrooks Davis continue; 226*c6ec7d31SBrooks Davis if (!(p->flags & F_DEV)) 227*c6ec7d31SBrooks Davis printf( 228*c6ec7d31SBrooks Davis " (%s not created: device not specified)", 229*c6ec7d31SBrooks Davis type); 230*c6ec7d31SBrooks Davis else if (mknod(path, 231*c6ec7d31SBrooks Davis p->st_mode | nodetoino(p->type), 232*c6ec7d31SBrooks Davis p->st_rdev) == -1) 233*c6ec7d31SBrooks Davis printf(" (%s not created: %s)\n", 234*c6ec7d31SBrooks Davis type, strerror(errno)); 235*c6ec7d31SBrooks Davis else 236*c6ec7d31SBrooks Davis create = 1; 237*c6ec7d31SBrooks Davis break; 238*c6ec7d31SBrooks Davis case F_LINK: 239*c6ec7d31SBrooks Davis if (!(p->flags & F_SLINK)) 240*c6ec7d31SBrooks Davis printf( 241*c6ec7d31SBrooks Davis " (%s not created: link not specified)\n", 242*c6ec7d31SBrooks Davis type); 243*c6ec7d31SBrooks Davis else if (symlink(p->slink, path)) 244*c6ec7d31SBrooks Davis printf( 245*c6ec7d31SBrooks Davis " (%s not created: %s)\n", 246*c6ec7d31SBrooks Davis type, strerror(errno)); 247*c6ec7d31SBrooks Davis else 248*c6ec7d31SBrooks Davis create = 1; 249*c6ec7d31SBrooks Davis break; 250*c6ec7d31SBrooks Davis case F_DIR: 251*c6ec7d31SBrooks Davis if (mkdir(path, S_IRWXU|S_IRWXG|S_IRWXO)) 252*c6ec7d31SBrooks Davis printf(" (not created: %s)", 253*c6ec7d31SBrooks Davis strerror(errno)); 254*c6ec7d31SBrooks Davis else 255*c6ec7d31SBrooks Davis create = 1; 256*c6ec7d31SBrooks Davis break; 257*c6ec7d31SBrooks Davis default: 258*c6ec7d31SBrooks Davis mtree_err("can't create create %s", 259*c6ec7d31SBrooks Davis nodetype(p->type)); 260*c6ec7d31SBrooks Davis } 261*c6ec7d31SBrooks Davis } 262*c6ec7d31SBrooks Davis if (create) 263*c6ec7d31SBrooks Davis printf(" (created)"); 264*c6ec7d31SBrooks Davis if (p->type == F_DIR) { 265*c6ec7d31SBrooks Davis if (!(p->flags & F_VISIT)) 266*c6ec7d31SBrooks Davis putchar('\n'); 267*c6ec7d31SBrooks Davis for (tp = tail; *tp; ++tp) 268*c6ec7d31SBrooks Davis continue; 269*c6ec7d31SBrooks Davis *tp = '/'; 270*c6ec7d31SBrooks Davis miss(p->child, tp + 1); 271*c6ec7d31SBrooks Davis *tp = '\0'; 272*c6ec7d31SBrooks Davis } else 273*c6ec7d31SBrooks Davis putchar('\n'); 274*c6ec7d31SBrooks Davis 275*c6ec7d31SBrooks Davis if (!create || mtree_Wflag) 276*c6ec7d31SBrooks Davis continue; 277*c6ec7d31SBrooks Davis if ((p->flags & (F_UID | F_UNAME)) && 278*c6ec7d31SBrooks Davis (p->flags & (F_GID | F_GNAME)) && 279*c6ec7d31SBrooks Davis (lchown(path, p->st_uid, p->st_gid))) { 280*c6ec7d31SBrooks Davis printf("%s: user/group/mode not modified: %s\n", 281*c6ec7d31SBrooks Davis path, strerror(errno)); 282*c6ec7d31SBrooks Davis printf("%s: warning: file mode %snot set\n", path, 283*c6ec7d31SBrooks Davis (p->flags & F_FLAGS) ? "and file flags " : ""); 284*c6ec7d31SBrooks Davis continue; 285*c6ec7d31SBrooks Davis } 286*c6ec7d31SBrooks Davis if (p->flags & F_MODE) { 287*c6ec7d31SBrooks Davis if (lchmod(path, p->st_mode)) 288*c6ec7d31SBrooks Davis printf("%s: permissions not set: %s\n", 289*c6ec7d31SBrooks Davis path, strerror(errno)); 290*c6ec7d31SBrooks Davis } 291*c6ec7d31SBrooks Davis #if HAVE_STRUCT_STAT_ST_FLAGS 292*c6ec7d31SBrooks Davis if ((p->flags & F_FLAGS) && p->st_flags) { 293*c6ec7d31SBrooks Davis if (iflag) 294*c6ec7d31SBrooks Davis flags = p->st_flags; 295*c6ec7d31SBrooks Davis else 296*c6ec7d31SBrooks Davis flags = p->st_flags & ~SP_FLGS; 297*c6ec7d31SBrooks Davis if (lchflags(path, flags)) 298*c6ec7d31SBrooks Davis printf("%s: file flags not set: %s\n", 299*c6ec7d31SBrooks Davis path, strerror(errno)); 300*c6ec7d31SBrooks Davis } 301*c6ec7d31SBrooks Davis #endif /* HAVE_STRUCT_STAT_ST_FLAGS */ 302*c6ec7d31SBrooks Davis } 303*c6ec7d31SBrooks Davis } 304