verify.c revision 112214
180708Sjake/*- 280708Sjake * Copyright (c) 1990, 1993 380708Sjake * The Regents of the University of California. All rights reserved. 480708Sjake * 580708Sjake * Redistribution and use in source and binary forms, with or without 680708Sjake * modification, are permitted provided that the following conditions 780708Sjake * are met: 880708Sjake * 1. Redistributions of source code must retain the above copyright 980708Sjake * notice, this list of conditions and the following disclaimer. 1080708Sjake * 2. Redistributions in binary form must reproduce the above copyright 1180708Sjake * notice, this list of conditions and the following disclaimer in the 1280708Sjake * documentation and/or other materials provided with the distribution. 1380708Sjake * 3. All advertising materials mentioning features or use of this software 1480708Sjake * must display the following acknowledgement: 1580708Sjake * This product includes software developed by the University of 1680708Sjake * California, Berkeley and its contributors. 1780708Sjake * 4. Neither the name of the University nor the names of its contributors 1880708Sjake * may be used to endorse or promote products derived from this software 1980708Sjake * without specific prior written permission. 2080708Sjake * 2180708Sjake * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2280708Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2380708Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2480708Sjake * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2580708Sjake * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2680708Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2780708Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2880708Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2980708Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3080708Sjake * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3180708Sjake * SUCH DAMAGE. 3280708Sjake */ 33196994Sphk 34196994Sphk#ifndef lint 35196994Sphk#if 0 3680708Sjakestatic char sccsid[] = "@(#)verify.c 8.1 (Berkeley) 6/6/93"; 3780708Sjake#endif 3880708Sjakestatic const char rcsid[] = 3980708Sjake "$FreeBSD: head/usr.sbin/mtree/verify.c 112214 2003-03-13 23:35:30Z robert $"; 40196994Sphk#endif /* not lint */ 4180708Sjake 42195808Smarius#include <sys/param.h> 43195808Smarius#include <sys/stat.h> 4480708Sjake#include <dirent.h> 4580708Sjake#include <err.h> 4680708Sjake#include <errno.h> 4780708Sjake#include <fts.h> 4880708Sjake#include <fnmatch.h> 4980708Sjake#include <stdio.h> 5080708Sjake#include <unistd.h> 5180708Sjake#include "mtree.h" 52177661Sjb#include "extern.h" 5380708Sjake 5480708Sjakeextern int ftsoptions; 5580708Sjakeextern int dflag, eflag, qflag, rflag, sflag, uflag; 56177661Sjbextern char fullpath[MAXPATHLEN]; 5780708Sjakeextern int lineno; 5891336Sjake 5991336Sjakestatic NODE *root; 6091336Sjakestatic char path[MAXPATHLEN]; 6180708Sjake 6280708Sjakestatic void miss(NODE *, char *); 63195376Ssamstatic int vwalk(void); 64195376Ssam 65195376Ssamint 66195376Ssamverify() 67195376Ssam{ 68195376Ssam int rval; 69195376Ssam 7080708Sjake root = spec(); 71191278Srwatson rval = vwalk(); 72191278Srwatson miss(root, path); 73191278Srwatson return (rval); 74191278Srwatson} 75191309Srwatson 76191276Srwatsonstatic int 77191276Srwatsonvwalk() 7880709Sjake{ 79120710Salc register FTS *t; 8080709Sjake register FTSENT *p; 8180708Sjake register NODE *ep, *level; 8280709Sjake int specdepth, rval; 83120710Salc char *argv[2]; 8480709Sjake char dot[] = "."; 8580708Sjake 8680709Sjake argv[0] = dot; 87120710Salc argv[1] = NULL; 8880709Sjake if ((t = fts_open(argv, ftsoptions, NULL)) == NULL) 8980709Sjake err(1, "line %d: fts_open", lineno); 9080709Sjake level = root; 91120710Salc specdepth = rval = 0; 9280709Sjake while ((p = fts_read(t))) { 9380709Sjake if (check_excludes(p->fts_name, p->fts_path)) { 94165324Skmacy fts_set(t, p, FTS_SKIP); 95165324Skmacy continue; 96165324Skmacy } 97165324Skmacy switch(p->fts_info) { 98165324Skmacy case FTS_D: 99165324Skmacy case FTS_SL: 100165324Skmacy break; 101165324Skmacy case FTS_DP: 10286226Stmm if (specdepth > p->fts_level) { 10386226Stmm for (level = level->parent; level->prev; 10486226Stmm level = level->prev); 10580709Sjake --specdepth; 10680709Sjake } 10780709Sjake continue; 10886226Stmm case FTS_DNR: 10986226Stmm case FTS_ERR: 11086226Stmm case FTS_NS: 11180709Sjake warnx("%s: %s", RP(p), strerror(p->fts_errno)); 112197316Salc continue; 113197316Salc default: 114118239Speter if (dflag) 11588781Sjake continue; 116118239Speter } 117116355Salc 11891360Sjake if (specdepth != p->fts_level) 11983366Sjulian goto extra; 120151344Skris for (ep = level; ep; ep = ep->next) 121151344Skris if ((ep->flags & F_MAGIC && 122151344Skris !fnmatch(ep->name, p->fts_name, FNM_PATHNAME)) || 123151344Skris !strcmp(ep->name, p->fts_name)) { 124151344Skris ep->flags |= F_VISIT; 125151344Skris if ((ep->flags & F_NOCHANGE) == 0 && 126151344Skris compare(ep->name, ep, p)) 127151344Skris rval = MISMATCHEXIT; 12883366Sjulian if (ep->flags & F_IGN) 12980708Sjake (void)fts_set(t, p, FTS_SKIP); 13080708Sjake else if (ep->child && ep->type == F_DIR && 13180708Sjake p->fts_info == FTS_D) { 13280709Sjake level = ep->child; 13380708Sjake ++specdepth; 13480708Sjake } 13580708Sjake break; 13680708Sjake } 13780708Sjake 13880708Sjake if (ep) 13980708Sjake continue; 14080708Sjakeextra: 14180708Sjake if (!eflag) { 14280708Sjake (void)printf("%s extra", RP(p)); 143196994Sphk if (rflag) { 144 if ((S_ISDIR(p->fts_statp->st_mode) 145 ? rmdir : unlink)(p->fts_accpath)) { 146 (void)printf(", not removed: %s", 147 strerror(errno)); 148 } else 149 (void)printf(", removed"); 150 } 151 (void)putchar('\n'); 152 } 153 (void)fts_set(t, p, FTS_SKIP); 154 } 155 (void)fts_close(t); 156 if (sflag) 157 warnx("%s checksum: %lu", fullpath, (unsigned long)crc_total); 158 return (rval); 159} 160 161static void 162miss(p, tail) 163 register NODE *p; 164 register char *tail; 165{ 166 register int create; 167 register char *tp; 168 const char *type; 169 170 for (; p; p = p->next) { 171 if (p->type != F_DIR && (dflag || p->flags & F_VISIT)) 172 continue; 173 (void)strcpy(tail, p->name); 174 if (!(p->flags & F_VISIT)) { 175 /* Don't print missing message if file exists as a 176 symbolic link and the -q flag is set. */ 177 struct stat statbuf; 178 179 if (qflag && stat(path, &statbuf) == 0) 180 p->flags |= F_VISIT; 181 else 182 (void)printf("%s missing", path); 183 } 184 if (p->type != F_DIR && p->type != F_LINK) { 185 putchar('\n'); 186 continue; 187 } 188 189 create = 0; 190 if (p->type == F_LINK) 191 type = "symlink"; 192 else 193 type = "directory"; 194 if (!(p->flags & F_VISIT) && uflag) { 195 if (!(p->flags & (F_UID | F_UNAME))) 196 (void)printf(" (%s not created: user not specified)", type); 197 else if (!(p->flags & (F_GID | F_GNAME))) 198 (void)printf(" (%s not created: group not specified)", type); 199 else if (p->type == F_LINK) { 200 if (symlink(p->slink, path)) 201 (void)printf(" (symlink not created: %s)\n", 202 strerror(errno)); 203 else 204 (void)printf(" (created)\n"); 205 if (lchown(path, p->st_uid, p->st_gid)) 206 (void)printf("%s: user/group not modified: %s\n", 207 path, strerror(errno)); 208 continue; 209 } else if (!(p->flags & F_MODE)) 210 (void)printf(" (directory not created: mode not specified)"); 211 else if (mkdir(path, S_IRWXU)) 212 (void)printf(" (directory not created: %s)", 213 strerror(errno)); 214 else { 215 create = 1; 216 (void)printf(" (created)"); 217 } 218 } 219 if (!(p->flags & F_VISIT)) 220 (void)putchar('\n'); 221 222 for (tp = tail; *tp; ++tp); 223 *tp = '/'; 224 miss(p->child, tp + 1); 225 *tp = '\0'; 226 227 if (!create) 228 continue; 229 if (chown(path, p->st_uid, p->st_gid)) { 230 (void)printf("%s: user/group/mode not modified: %s\n", 231 path, strerror(errno)); 232 (void)printf("%s: warning: file mode %snot set\n", path, 233 (p->flags & F_FLAGS) ? "and file flags " : ""); 234 continue; 235 } 236 if (chmod(path, p->st_mode)) 237 (void)printf("%s: permissions not set: %s\n", 238 path, strerror(errno)); 239 if ((p->flags & F_FLAGS) && p->st_flags && 240 chflags(path, p->st_flags)) 241 (void)printf("%s: file flags not set: %s\n", 242 path, strerror(errno)); 243 } 244} 245