1249293Sed/* $NetBSD: verify.c,v 1.44 2013/02/03 19:15:17 christos Exp $ */ 2244541Sbrooks 3244541Sbrooks/*- 4244541Sbrooks * Copyright (c) 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(__RCSID) && !defined(lint) 38244541Sbrooks#if 0 39244541Sbrooksstatic char sccsid[] = "@(#)verify.c 8.1 (Berkeley) 6/6/93"; 40244541Sbrooks#else 41249293Sed__RCSID("$NetBSD: verify.c,v 1.44 2013/02/03 19:15:17 christos Exp $"); 42244541Sbrooks#endif 43244541Sbrooks#endif /* not lint */ 44244541Sbrooks 45244541Sbrooks#include <sys/param.h> 46244541Sbrooks#include <sys/stat.h> 47244541Sbrooks 48244541Sbrooks#if ! HAVE_NBTOOL_CONFIG_H 49244541Sbrooks#include <dirent.h> 50244541Sbrooks#endif 51244541Sbrooks 52244541Sbrooks#include <errno.h> 53244541Sbrooks#include <fnmatch.h> 54244541Sbrooks#include <stdio.h> 55244541Sbrooks#include <string.h> 56244541Sbrooks#include <unistd.h> 57244541Sbrooks 58244541Sbrooks#include "extern.h" 59244541Sbrooks 60244541Sbrooksstatic NODE *root; 61244541Sbrooksstatic char path[MAXPATHLEN]; 62244541Sbrooks 63244541Sbrooksstatic void miss(NODE *, char *); 64244541Sbrooksstatic int vwalk(void); 65244541Sbrooks 66244541Sbrooksint 67244541Sbrooksverify(FILE *fi) 68244541Sbrooks{ 69244541Sbrooks int rval; 70244541Sbrooks 71244541Sbrooks root = spec(fi); 72244541Sbrooks rval = vwalk(); 73244541Sbrooks miss(root, path); 74244541Sbrooks return (rval); 75244541Sbrooks} 76244541Sbrooks 77244541Sbrooksstatic int 78244541Sbrooksvwalk(void) 79244541Sbrooks{ 80244541Sbrooks FTS *t; 81244541Sbrooks FTSENT *p; 82244541Sbrooks NODE *ep, *level; 83244541Sbrooks int specdepth, rval; 84244541Sbrooks char *argv[2]; 85244541Sbrooks char dot[] = "."; 86244541Sbrooks argv[0] = dot; 87244541Sbrooks argv[1] = NULL; 88244541Sbrooks 89244541Sbrooks if ((t = fts_open(argv, ftsoptions, NULL)) == NULL) 90244541Sbrooks mtree_err("fts_open: %s", strerror(errno)); 91244541Sbrooks level = root; 92244541Sbrooks specdepth = rval = 0; 93244541Sbrooks while ((p = fts_read(t)) != NULL) { 94244541Sbrooks if (check_excludes(p->fts_name, p->fts_path)) { 95244541Sbrooks fts_set(t, p, FTS_SKIP); 96244541Sbrooks continue; 97244541Sbrooks } 98249293Sed if (!find_only(p->fts_path)) { 99249293Sed fts_set(t, p, FTS_SKIP); 100249293Sed continue; 101249293Sed } 102244541Sbrooks switch(p->fts_info) { 103244541Sbrooks case FTS_D: 104244541Sbrooks case FTS_SL: 105244541Sbrooks break; 106244541Sbrooks case FTS_DP: 107244541Sbrooks if (specdepth > p->fts_level) { 108244541Sbrooks for (level = level->parent; level->prev; 109244541Sbrooks level = level->prev) 110244541Sbrooks continue; 111244541Sbrooks --specdepth; 112244541Sbrooks } 113244541Sbrooks continue; 114244541Sbrooks case FTS_DNR: 115244541Sbrooks case FTS_ERR: 116244541Sbrooks case FTS_NS: 117244541Sbrooks warnx("%s: %s", RP(p), strerror(p->fts_errno)); 118244541Sbrooks continue; 119244541Sbrooks default: 120244541Sbrooks if (dflag) 121244541Sbrooks continue; 122244541Sbrooks } 123244541Sbrooks 124244541Sbrooks if (specdepth != p->fts_level) 125244541Sbrooks goto extra; 126244541Sbrooks for (ep = level; ep; ep = ep->next) 127244541Sbrooks if ((ep->flags & F_MAGIC && 128244541Sbrooks !fnmatch(ep->name, p->fts_name, FNM_PATHNAME)) || 129244541Sbrooks !strcmp(ep->name, p->fts_name)) { 130244541Sbrooks ep->flags |= F_VISIT; 131244541Sbrooks if ((ep->flags & F_NOCHANGE) == 0 && 132244541Sbrooks compare(ep, p)) 133244541Sbrooks rval = MISMATCHEXIT; 134244541Sbrooks if (!(ep->flags & F_IGN) && 135244541Sbrooks ep->type == F_DIR && 136244541Sbrooks p->fts_info == FTS_D) { 137244541Sbrooks if (ep->child) { 138244541Sbrooks level = ep->child; 139244541Sbrooks ++specdepth; 140244541Sbrooks } 141244541Sbrooks } else 142244541Sbrooks fts_set(t, p, FTS_SKIP); 143244541Sbrooks break; 144244541Sbrooks } 145244541Sbrooks 146244541Sbrooks if (ep) 147244541Sbrooks continue; 148244541Sbrooks extra: 149244541Sbrooks if (!eflag && !(dflag && p->fts_info == FTS_SL)) { 150244541Sbrooks printf("extra: %s", RP(p)); 151244541Sbrooks if (rflag) { 152244541Sbrooks if ((S_ISDIR(p->fts_statp->st_mode) 153244541Sbrooks ? rmdir : unlink)(p->fts_accpath)) { 154244541Sbrooks printf(", not removed: %s", 155244541Sbrooks strerror(errno)); 156244541Sbrooks } else 157244541Sbrooks printf(", removed"); 158244541Sbrooks } 159244541Sbrooks putchar('\n'); 160244541Sbrooks } 161244541Sbrooks fts_set(t, p, FTS_SKIP); 162244541Sbrooks } 163244541Sbrooks fts_close(t); 164244541Sbrooks if (sflag) 165244541Sbrooks warnx("%s checksum: %u", fullpath, crc_total); 166244541Sbrooks return (rval); 167244541Sbrooks} 168244541Sbrooks 169244541Sbrooksstatic void 170244541Sbrooksmiss(NODE *p, char *tail) 171244541Sbrooks{ 172244541Sbrooks int create; 173244541Sbrooks char *tp; 174244541Sbrooks const char *type; 175244541Sbrooks u_int32_t flags; 176244541Sbrooks 177244541Sbrooks for (; p; p = p->next) { 178244541Sbrooks if (p->flags & F_OPT && !(p->flags & F_VISIT)) 179244541Sbrooks continue; 180244541Sbrooks if (p->type != F_DIR && (dflag || p->flags & F_VISIT)) 181244541Sbrooks continue; 182244541Sbrooks strcpy(tail, p->name); 183244541Sbrooks if (!(p->flags & F_VISIT)) { 184244541Sbrooks /* Don't print missing message if file exists as a 185244541Sbrooks symbolic link and the -q flag is set. */ 186244541Sbrooks struct stat statbuf; 187244541Sbrooks 188244541Sbrooks if (qflag && stat(path, &statbuf) == 0 && 189244541Sbrooks S_ISDIR(statbuf.st_mode)) 190244541Sbrooks p->flags |= F_VISIT; 191244541Sbrooks else 192244541Sbrooks (void)printf("%s missing", path); 193244541Sbrooks } 194244541Sbrooks switch (p->type) { 195244541Sbrooks case F_BLOCK: 196244541Sbrooks case F_CHAR: 197244541Sbrooks type = "device"; 198244541Sbrooks break; 199244541Sbrooks case F_DIR: 200244541Sbrooks type = "directory"; 201244541Sbrooks break; 202244541Sbrooks case F_LINK: 203244541Sbrooks type = "symlink"; 204244541Sbrooks break; 205244541Sbrooks default: 206244541Sbrooks putchar('\n'); 207244541Sbrooks continue; 208244541Sbrooks } 209244541Sbrooks 210244541Sbrooks create = 0; 211244541Sbrooks if (!(p->flags & F_VISIT) && uflag) { 212244541Sbrooks if (mtree_Wflag || p->type == F_LINK) 213244541Sbrooks goto createit; 214244541Sbrooks if (!(p->flags & (F_UID | F_UNAME))) 215244541Sbrooks printf( 216244541Sbrooks " (%s not created: user not specified)", type); 217244541Sbrooks else if (!(p->flags & (F_GID | F_GNAME))) 218244541Sbrooks printf( 219244541Sbrooks " (%s not created: group not specified)", type); 220244541Sbrooks else if (!(p->flags & F_MODE)) 221244541Sbrooks printf( 222244541Sbrooks " (%s not created: mode not specified)", type); 223244541Sbrooks else 224244541Sbrooks createit: 225244541Sbrooks switch (p->type) { 226244541Sbrooks case F_BLOCK: 227244541Sbrooks case F_CHAR: 228244541Sbrooks if (mtree_Wflag) 229244541Sbrooks continue; 230244541Sbrooks if (!(p->flags & F_DEV)) 231244541Sbrooks printf( 232244541Sbrooks " (%s not created: device not specified)", 233244541Sbrooks type); 234244541Sbrooks else if (mknod(path, 235244541Sbrooks p->st_mode | nodetoino(p->type), 236244541Sbrooks p->st_rdev) == -1) 237244541Sbrooks printf(" (%s not created: %s)\n", 238244541Sbrooks type, strerror(errno)); 239244541Sbrooks else 240244541Sbrooks create = 1; 241244541Sbrooks break; 242244541Sbrooks case F_LINK: 243244541Sbrooks if (!(p->flags & F_SLINK)) 244244541Sbrooks printf( 245244541Sbrooks " (%s not created: link not specified)\n", 246244541Sbrooks type); 247244541Sbrooks else if (symlink(p->slink, path)) 248244541Sbrooks printf( 249244541Sbrooks " (%s not created: %s)\n", 250244541Sbrooks type, strerror(errno)); 251244541Sbrooks else 252244541Sbrooks create = 1; 253244541Sbrooks break; 254244541Sbrooks case F_DIR: 255244541Sbrooks if (mkdir(path, S_IRWXU|S_IRWXG|S_IRWXO)) 256244541Sbrooks printf(" (not created: %s)", 257244541Sbrooks strerror(errno)); 258244541Sbrooks else 259244541Sbrooks create = 1; 260244541Sbrooks break; 261244541Sbrooks default: 262244541Sbrooks mtree_err("can't create create %s", 263244541Sbrooks nodetype(p->type)); 264244541Sbrooks } 265244541Sbrooks } 266244541Sbrooks if (create) 267244541Sbrooks printf(" (created)"); 268244541Sbrooks if (p->type == F_DIR) { 269244541Sbrooks if (!(p->flags & F_VISIT)) 270244541Sbrooks putchar('\n'); 271244541Sbrooks for (tp = tail; *tp; ++tp) 272244541Sbrooks continue; 273244541Sbrooks *tp = '/'; 274244541Sbrooks miss(p->child, tp + 1); 275244541Sbrooks *tp = '\0'; 276244541Sbrooks } else 277244541Sbrooks putchar('\n'); 278244541Sbrooks 279244541Sbrooks if (!create || mtree_Wflag) 280244541Sbrooks continue; 281244541Sbrooks if ((p->flags & (F_UID | F_UNAME)) && 282244541Sbrooks (p->flags & (F_GID | F_GNAME)) && 283244541Sbrooks (lchown(path, p->st_uid, p->st_gid))) { 284244541Sbrooks printf("%s: user/group/mode not modified: %s\n", 285244541Sbrooks path, strerror(errno)); 286244541Sbrooks printf("%s: warning: file mode %snot set\n", path, 287244541Sbrooks (p->flags & F_FLAGS) ? "and file flags " : ""); 288244541Sbrooks continue; 289244541Sbrooks } 290244541Sbrooks if (p->flags & F_MODE) { 291244541Sbrooks if (lchmod(path, p->st_mode)) 292244541Sbrooks printf("%s: permissions not set: %s\n", 293244541Sbrooks path, strerror(errno)); 294244541Sbrooks } 295244541Sbrooks#if HAVE_STRUCT_STAT_ST_FLAGS 296244541Sbrooks if ((p->flags & F_FLAGS) && p->st_flags) { 297244541Sbrooks if (iflag) 298244541Sbrooks flags = p->st_flags; 299244541Sbrooks else 300244541Sbrooks flags = p->st_flags & ~SP_FLGS; 301244541Sbrooks if (lchflags(path, flags)) 302244541Sbrooks printf("%s: file flags not set: %s\n", 303244541Sbrooks path, strerror(errno)); 304244541Sbrooks } 305244541Sbrooks#endif /* HAVE_STRUCT_STAT_ST_FLAGS */ 306244541Sbrooks } 307244541Sbrooks} 308