verify.c revision 122135
1168404Spjd/*- 2168404Spjd * Copyright (c) 1990, 1993 3168404Spjd * The Regents of the University of California. All rights reserved. 4168404Spjd * 5168404Spjd * Redistribution and use in source and binary forms, with or without 6168404Spjd * modification, are permitted provided that the following conditions 7168404Spjd * are met: 8168404Spjd * 1. Redistributions of source code must retain the above copyright 9168404Spjd * notice, this list of conditions and the following disclaimer. 10168404Spjd * 2. Redistributions in binary form must reproduce the above copyright 11168404Spjd * notice, this list of conditions and the following disclaimer in the 12168404Spjd * documentation and/or other materials provided with the distribution. 13168404Spjd * 3. Neither the name of the University nor the names of its contributors 14168404Spjd * may be used to endorse or promote products derived from this software 15168404Spjd * without specific prior written permission. 16168404Spjd * 17168404Spjd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18168404Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19168404Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20168404Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21168404Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22168404Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23168404Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24168404Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25168404Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26168404Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27168404Spjd * SUCH DAMAGE. 28168404Spjd */ 29168404Spjd 30168404Spjd#if 0 31168404Spjd#ifndef lint 32168404Spjdstatic char sccsid[] = "@(#)verify.c 8.1 (Berkeley) 6/6/93"; 33168404Spjd#endif /* not lint */ 34168404Spjd#endif 35168404Spjd#include <sys/cdefs.h> 36168404Spjd__FBSDID("$FreeBSD: head/usr.sbin/mtree/verify.c 122135 2003-11-05 20:07:40Z phk $"); 37168404Spjd 38168404Spjd#include <sys/param.h> 39168404Spjd#include <sys/stat.h> 40168404Spjd#include <dirent.h> 41168404Spjd#include <err.h> 42168404Spjd#include <errno.h> 43168404Spjd#include <fts.h> 44168404Spjd#include <fnmatch.h> 45168404Spjd#include <stdio.h> 46168404Spjd#include <unistd.h> 47168404Spjd#include "mtree.h" 48168404Spjd#include "extern.h" 49168404Spjd 50168404Spjdextern int ftsoptions; 51168404Spjdextern int dflag, eflag, qflag, rflag, sflag, uflag; 52168404Spjdextern char fullpath[MAXPATHLEN]; 53168404Spjdextern int lineno; 54168404Spjd 55168404Spjdstatic NODE *root; 56168404Spjdstatic char path[MAXPATHLEN]; 57168404Spjd 58168404Spjdstatic void miss(NODE *, char *); 59168404Spjdstatic int vwalk(void); 60168404Spjd 61168404Spjdint 62168404Spjdmtree_verifyspec(FILE *fi) 63168404Spjd{ 64168404Spjd int rval; 65168404Spjd 66168404Spjd root = mtree_readspec(fi); 67168404Spjd rval = vwalk(); 68168404Spjd miss(root, path); 69168404Spjd return (rval); 70168404Spjd} 71168404Spjd 72168404Spjdstatic int 73168404Spjdvwalk(void) 74168404Spjd{ 75168404Spjd FTS *t; 76168404Spjd FTSENT *p; 77168404Spjd NODE *ep, *level; 78168404Spjd int specdepth, rval; 79168404Spjd char *argv[2]; 80168404Spjd char dot[] = "."; 81168404Spjd 82168404Spjd argv[0] = dot; 83168404Spjd argv[1] = NULL; 84168404Spjd if ((t = fts_open(argv, ftsoptions, NULL)) == NULL) 85168404Spjd err(1, "line %d: fts_open", lineno); 86168404Spjd level = root; 87168404Spjd specdepth = rval = 0; 88168404Spjd while ((p = fts_read(t))) { 89168404Spjd if (check_excludes(p->fts_name, p->fts_path)) { 90168404Spjd fts_set(t, p, FTS_SKIP); 91168404Spjd continue; 92168404Spjd } 93168404Spjd switch(p->fts_info) { 94168404Spjd case FTS_D: 95168404Spjd case FTS_SL: 96168404Spjd break; 97168404Spjd case FTS_DP: 98168404Spjd if (specdepth > p->fts_level) { 99168404Spjd for (level = level->parent; level->prev; 100168404Spjd level = level->prev); 101168404Spjd --specdepth; 102168404Spjd } 103168404Spjd continue; 104168404Spjd case FTS_DNR: 105168404Spjd case FTS_ERR: 106168404Spjd case FTS_NS: 107168404Spjd warnx("%s: %s", RP(p), strerror(p->fts_errno)); 108168404Spjd continue; 109168404Spjd default: 110168404Spjd if (dflag) 111168404Spjd continue; 112168404Spjd } 113168404Spjd 114168404Spjd if (specdepth != p->fts_level) 115168404Spjd goto extra; 116168404Spjd for (ep = level; ep; ep = ep->next) 117168404Spjd if ((ep->flags & F_MAGIC && 118168404Spjd !fnmatch(ep->name, p->fts_name, FNM_PATHNAME)) || 119168404Spjd !strcmp(ep->name, p->fts_name)) { 120168404Spjd ep->flags |= F_VISIT; 121168404Spjd if ((ep->flags & F_NOCHANGE) == 0 && 122168404Spjd compare(ep->name, ep, p)) 123168404Spjd rval = MISMATCHEXIT; 124168404Spjd if (ep->flags & F_IGN) 125168404Spjd (void)fts_set(t, p, FTS_SKIP); 126168404Spjd else if (ep->child && ep->type == F_DIR && 127168404Spjd p->fts_info == FTS_D) { 128168404Spjd level = ep->child; 129168404Spjd ++specdepth; 130168404Spjd } 131168404Spjd break; 132168404Spjd } 133168404Spjd 134168404Spjd if (ep) 135168404Spjd continue; 136168404Spjdextra: 137168404Spjd if (!eflag) { 138168404Spjd (void)printf("%s extra", RP(p)); 139168404Spjd if (rflag) { 140168404Spjd if ((S_ISDIR(p->fts_statp->st_mode) 141168404Spjd ? rmdir : unlink)(p->fts_accpath)) { 142168404Spjd (void)printf(", not removed: %s", 143168404Spjd strerror(errno)); 144168404Spjd } else 145168404Spjd (void)printf(", removed"); 146168404Spjd } 147168404Spjd (void)putchar('\n'); 148168404Spjd } 149168404Spjd (void)fts_set(t, p, FTS_SKIP); 150168404Spjd } 151168404Spjd (void)fts_close(t); 152168404Spjd if (sflag) 153168404Spjd warnx("%s checksum: %lu", fullpath, (unsigned long)crc_total); 154168404Spjd return (rval); 155168404Spjd} 156168404Spjd 157168404Spjdstatic void 158168404Spjdmiss(NODE *p, char *tail) 159168404Spjd{ 160168404Spjd int create; 161168404Spjd char *tp; 162168404Spjd const char *type; 163168404Spjd 164168404Spjd for (; p; p = p->next) { 165168404Spjd if (p->type != F_DIR && (dflag || p->flags & F_VISIT)) 166168404Spjd continue; 167168404Spjd (void)strcpy(tail, p->name); 168168404Spjd if (!(p->flags & F_VISIT)) { 169168404Spjd /* Don't print missing message if file exists as a 170168404Spjd symbolic link and the -q flag is set. */ 171168404Spjd struct stat statbuf; 172168404Spjd 173168404Spjd if (qflag && stat(path, &statbuf) == 0) 174168404Spjd p->flags |= F_VISIT; 175168404Spjd else 176168404Spjd (void)printf("%s missing", path); 177168404Spjd } 178168404Spjd if (p->type != F_DIR && p->type != F_LINK) { 179168404Spjd putchar('\n'); 180168404Spjd continue; 181168404Spjd } 182168404Spjd 183168404Spjd create = 0; 184168404Spjd if (p->type == F_LINK) 185168404Spjd type = "symlink"; 186168404Spjd else 187168404Spjd type = "directory"; 188168404Spjd if (!(p->flags & F_VISIT) && uflag) { 189168404Spjd if (!(p->flags & (F_UID | F_UNAME))) 190168404Spjd (void)printf(" (%s not created: user not specified)", type); 191168404Spjd else if (!(p->flags & (F_GID | F_GNAME))) 192168404Spjd (void)printf(" (%s not created: group not specified)", type); 193168404Spjd else if (p->type == F_LINK) { 194168404Spjd if (symlink(p->slink, path)) 195168404Spjd (void)printf(" (symlink not created: %s)\n", 196168404Spjd strerror(errno)); 197168404Spjd else 198168404Spjd (void)printf(" (created)\n"); 199168404Spjd if (lchown(path, p->st_uid, p->st_gid)) 200168404Spjd (void)printf("%s: user/group not modified: %s\n", 201168404Spjd path, strerror(errno)); 202168404Spjd continue; 203168404Spjd } else if (!(p->flags & F_MODE)) 204168404Spjd (void)printf(" (directory not created: mode not specified)"); 205168404Spjd else if (mkdir(path, S_IRWXU)) 206168404Spjd (void)printf(" (directory not created: %s)", 207168404Spjd strerror(errno)); 208168404Spjd else { 209168404Spjd create = 1; 210168404Spjd (void)printf(" (created)"); 211168404Spjd } 212168404Spjd } 213168404Spjd if (!(p->flags & F_VISIT)) 214168404Spjd (void)putchar('\n'); 215168404Spjd 216168404Spjd for (tp = tail; *tp; ++tp); 217168404Spjd *tp = '/'; 218168404Spjd miss(p->child, tp + 1); 219168404Spjd *tp = '\0'; 220168404Spjd 221168404Spjd if (!create) 222168404Spjd continue; 223168404Spjd if (chown(path, p->st_uid, p->st_gid)) { 224168404Spjd (void)printf("%s: user/group/mode not modified: %s\n", 225168404Spjd path, strerror(errno)); 226168404Spjd (void)printf("%s: warning: file mode %snot set\n", path, 227168404Spjd (p->flags & F_FLAGS) ? "and file flags " : ""); 228168404Spjd continue; 229168404Spjd } 230168404Spjd if (chmod(path, p->st_mode)) 231168404Spjd (void)printf("%s: permissions not set: %s\n", 232168404Spjd path, strerror(errno)); 233168404Spjd if ((p->flags & F_FLAGS) && p->st_flags && 234168404Spjd chflags(path, p->st_flags)) 235168404Spjd (void)printf("%s: file flags not set: %s\n", 236168404Spjd path, strerror(errno)); 237168404Spjd } 238168404Spjd} 239168404Spjd