11553Srgrimes/*- 21553Srgrimes * Copyright (c) 1990, 1993 31553Srgrimes * The Regents of the University of California. All rights reserved. 41553Srgrimes * 51553Srgrimes * Redistribution and use in source and binary forms, with or without 61553Srgrimes * modification, are permitted provided that the following conditions 71553Srgrimes * are met: 81553Srgrimes * 1. Redistributions of source code must retain the above copyright 91553Srgrimes * notice, this list of conditions and the following disclaimer. 101553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111553Srgrimes * notice, this list of conditions and the following disclaimer in the 121553Srgrimes * documentation and/or other materials provided with the distribution. 13121300Sphk * 3. Neither the name of the University nor the names of its contributors 141553Srgrimes * may be used to endorse or promote products derived from this software 151553Srgrimes * without specific prior written permission. 161553Srgrimes * 171553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201553Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271553Srgrimes * SUCH DAMAGE. 281553Srgrimes */ 291553Srgrimes 30114601Sobrien#if 0 311553Srgrimes#ifndef lint 321553Srgrimesstatic char sccsid[] = "@(#)verify.c 8.1 (Berkeley) 6/6/93"; 33114601Sobrien#endif /* not lint */ 3430027Scharnier#endif 35114601Sobrien#include <sys/cdefs.h> 36114601Sobrien__FBSDID("$FreeBSD: releng/10.3/usr.sbin/mtree/verify.c 174403 2007-12-07 12:22:38Z des $"); 371553Srgrimes 381553Srgrimes#include <sys/param.h> 391553Srgrimes#include <sys/stat.h> 401553Srgrimes#include <dirent.h> 4130027Scharnier#include <err.h> 4230027Scharnier#include <errno.h> 431553Srgrimes#include <fts.h> 441553Srgrimes#include <fnmatch.h> 4530027Scharnier#include <stdio.h> 461553Srgrimes#include <unistd.h> 471553Srgrimes#include "mtree.h" 481553Srgrimes#include "extern.h" 491553Srgrimes 501553Srgrimesstatic NODE *root; 511553Srgrimesstatic char path[MAXPATHLEN]; 521553Srgrimes 5399800Salfredstatic void miss(NODE *, char *); 5499800Salfredstatic int vwalk(void); 551553Srgrimes 561553Srgrimesint 57122135Sphkmtree_verifyspec(FILE *fi) 581553Srgrimes{ 591553Srgrimes int rval; 601553Srgrimes 61122135Sphk root = mtree_readspec(fi); 621553Srgrimes rval = vwalk(); 631553Srgrimes miss(root, path); 641553Srgrimes return (rval); 651553Srgrimes} 661553Srgrimes 671553Srgrimesstatic int 68174403Sdesnsort(const FTSENT * const *a, const FTSENT * const *b) 69174403Sdes{ 70174403Sdes return (strcmp((*a)->fts_name, (*b)->fts_name)); 71174403Sdes} 72174403Sdes 73174403Sdesstatic int 74121299Sphkvwalk(void) 751553Srgrimes{ 76121299Sphk FTS *t; 77121299Sphk FTSENT *p; 78121299Sphk NODE *ep, *level; 799675Sbde int specdepth, rval; 801553Srgrimes char *argv[2]; 8199802Salfred char dot[] = "."; 821553Srgrimes 8399802Salfred argv[0] = dot; 841553Srgrimes argv[1] = NULL; 85174403Sdes if ((t = fts_open(argv, ftsoptions, nsort)) == NULL) 8630027Scharnier err(1, "line %d: fts_open", lineno); 871553Srgrimes level = root; 889675Sbde specdepth = rval = 0; 892860Srgrimes while ((p = fts_read(t))) { 9060418Swollman if (check_excludes(p->fts_name, p->fts_path)) { 9160418Swollman fts_set(t, p, FTS_SKIP); 9260418Swollman continue; 9360418Swollman } 941553Srgrimes switch(p->fts_info) { 951553Srgrimes case FTS_D: 9663086Sjoe case FTS_SL: 971553Srgrimes break; 981553Srgrimes case FTS_DP: 999675Sbde if (specdepth > p->fts_level) { 1001553Srgrimes for (level = level->parent; level->prev; 1018857Srgrimes level = level->prev); 1021553Srgrimes --specdepth; 1031553Srgrimes } 1041553Srgrimes continue; 1051553Srgrimes case FTS_DNR: 1061553Srgrimes case FTS_ERR: 1071553Srgrimes case FTS_NS: 10830027Scharnier warnx("%s: %s", RP(p), strerror(p->fts_errno)); 1091553Srgrimes continue; 1101553Srgrimes default: 1111553Srgrimes if (dflag) 1121553Srgrimes continue; 1131553Srgrimes } 1141553Srgrimes 1159675Sbde if (specdepth != p->fts_level) 1169675Sbde goto extra; 1171553Srgrimes for (ep = level; ep; ep = ep->next) 1182860Srgrimes if ((ep->flags & F_MAGIC && 1192860Srgrimes !fnmatch(ep->name, p->fts_name, FNM_PATHNAME)) || 1201553Srgrimes !strcmp(ep->name, p->fts_name)) { 1211553Srgrimes ep->flags |= F_VISIT; 12236670Speter if ((ep->flags & F_NOCHANGE) == 0 && 12336670Speter compare(ep->name, ep, p)) 1241553Srgrimes rval = MISMATCHEXIT; 12536841Speter if (ep->flags & F_IGN) 1261553Srgrimes (void)fts_set(t, p, FTS_SKIP); 1271553Srgrimes else if (ep->child && ep->type == F_DIR && 1281553Srgrimes p->fts_info == FTS_D) { 1291553Srgrimes level = ep->child; 1301553Srgrimes ++specdepth; 1311553Srgrimes } 1321553Srgrimes break; 1331553Srgrimes } 1341553Srgrimes 1351553Srgrimes if (ep) 1361553Srgrimes continue; 1379675Sbdeextra: 1381553Srgrimes if (!eflag) { 13966584Sphk (void)printf("%s extra", RP(p)); 1401553Srgrimes if (rflag) { 1419675Sbde if ((S_ISDIR(p->fts_statp->st_mode) 1429675Sbde ? rmdir : unlink)(p->fts_accpath)) { 1431553Srgrimes (void)printf(", not removed: %s", 1441553Srgrimes strerror(errno)); 1451553Srgrimes } else 1461553Srgrimes (void)printf(", removed"); 1471553Srgrimes } 1481553Srgrimes (void)putchar('\n'); 1491553Srgrimes } 1501553Srgrimes (void)fts_set(t, p, FTS_SKIP); 1511553Srgrimes } 1521553Srgrimes (void)fts_close(t); 1531553Srgrimes if (sflag) 154112214Srobert warnx("%s checksum: %lu", fullpath, (unsigned long)crc_total); 1551553Srgrimes return (rval); 1561553Srgrimes} 1571553Srgrimes 1581553Srgrimesstatic void 159121299Sphkmiss(NODE *p, char *tail) 1601553Srgrimes{ 161121299Sphk int create; 162121299Sphk char *tp; 163148966Sbrian const char *type, *what; 164148966Sbrian int serr; 1651553Srgrimes 1661553Srgrimes for (; p; p = p->next) { 167160083Smaxim if (p->flags & F_OPT && !(p->flags & F_VISIT)) 168160083Smaxim continue; 1691553Srgrimes if (p->type != F_DIR && (dflag || p->flags & F_VISIT)) 1701553Srgrimes continue; 1711553Srgrimes (void)strcpy(tail, p->name); 17263853Simp if (!(p->flags & F_VISIT)) { 17363853Simp /* Don't print missing message if file exists as a 17463853Simp symbolic link and the -q flag is set. */ 17563853Simp struct stat statbuf; 176121300Sphk 17763853Simp if (qflag && stat(path, &statbuf) == 0) 17863853Simp p->flags |= F_VISIT; 17963853Simp else 18066584Sphk (void)printf("%s missing", path); 18163853Simp } 18263087Sjoe if (p->type != F_DIR && p->type != F_LINK) { 1831553Srgrimes putchar('\n'); 1841553Srgrimes continue; 1851553Srgrimes } 1861553Srgrimes 1871553Srgrimes create = 0; 18863087Sjoe if (p->type == F_LINK) 18963087Sjoe type = "symlink"; 19063087Sjoe else 19163087Sjoe type = "directory"; 19251705Sbillf if (!(p->flags & F_VISIT) && uflag) { 1931553Srgrimes if (!(p->flags & (F_UID | F_UNAME))) 19463087Sjoe (void)printf(" (%s not created: user not specified)", type); 1951553Srgrimes else if (!(p->flags & (F_GID | F_GNAME))) 19663087Sjoe (void)printf(" (%s not created: group not specified)", type); 19763087Sjoe else if (p->type == F_LINK) { 19863087Sjoe if (symlink(p->slink, path)) 19963087Sjoe (void)printf(" (symlink not created: %s)\n", 20063087Sjoe strerror(errno)); 20163087Sjoe else 20263087Sjoe (void)printf(" (created)\n"); 203148966Sbrian if (lchown(path, p->st_uid, p->st_gid) == -1) { 204148966Sbrian serr = errno; 205148966Sbrian if (p->st_uid == (uid_t)-1) 206148966Sbrian what = "group"; 207148966Sbrian else if (lchown(path, (uid_t)-1, 208148966Sbrian p->st_gid) == -1) 209148966Sbrian what = "user & group"; 210148966Sbrian else { 211148966Sbrian what = "user"; 212148966Sbrian errno = serr; 213148966Sbrian } 214148966Sbrian (void)printf("%s: %s not modified: %s" 215148966Sbrian "\n", path, what, strerror(errno)); 216148966Sbrian } 21763087Sjoe continue; 21863087Sjoe } else if (!(p->flags & F_MODE)) 21936670Speter (void)printf(" (directory not created: mode not specified)"); 2201553Srgrimes else if (mkdir(path, S_IRWXU)) 22136670Speter (void)printf(" (directory not created: %s)", 2221553Srgrimes strerror(errno)); 2231553Srgrimes else { 2241553Srgrimes create = 1; 2251553Srgrimes (void)printf(" (created)"); 2261553Srgrimes } 22751705Sbillf } 2281553Srgrimes if (!(p->flags & F_VISIT)) 2291553Srgrimes (void)putchar('\n'); 2301553Srgrimes 2311553Srgrimes for (tp = tail; *tp; ++tp); 2321553Srgrimes *tp = '/'; 2331553Srgrimes miss(p->child, tp + 1); 2341553Srgrimes *tp = '\0'; 2351553Srgrimes 2361553Srgrimes if (!create) 2371553Srgrimes continue; 238148966Sbrian if (chown(path, p->st_uid, p->st_gid) == -1) { 239148966Sbrian serr = errno; 240148966Sbrian if (p->st_uid == (uid_t)-1) 241148966Sbrian what = "group"; 242148966Sbrian else if (chown(path, (uid_t)-1, p->st_gid) == -1) 243148966Sbrian what = "user & group"; 244148966Sbrian else { 245148966Sbrian what = "user"; 246148966Sbrian errno = serr; 247148966Sbrian } 248148966Sbrian (void)printf("%s: %s not modified: %s\n", 249148966Sbrian path, what, strerror(errno)); 2501553Srgrimes } 2511553Srgrimes if (chmod(path, p->st_mode)) 2521553Srgrimes (void)printf("%s: permissions not set: %s\n", 2531553Srgrimes path, strerror(errno)); 25454375Sjoe if ((p->flags & F_FLAGS) && p->st_flags && 25554375Sjoe chflags(path, p->st_flags)) 25654375Sjoe (void)printf("%s: file flags not set: %s\n", 25754375Sjoe path, strerror(errno)); 2581553Srgrimes } 2591553Srgrimes} 260