compare.c revision 66746
1158795Sdelphij/*- 2141261Sdelphij * Copyright (c) 1989, 1993 3141261Sdelphij * The Regents of the University of California. All rights reserved. 4141261Sdelphij * 5158795Sdelphij * Redistribution and use in source and binary forms, with or without 6141261Sdelphij * modification, are permitted provided that the following conditions 7141261Sdelphij * are met: 8141261Sdelphij * 1. Redistributions of source code must retain the above copyright 9141261Sdelphij * notice, this list of conditions and the following disclaimer. 10141261Sdelphij * 2. Redistributions in binary form must reproduce the above copyright 11141261Sdelphij * notice, this list of conditions and the following disclaimer in the 12141261Sdelphij * documentation and/or other materials provided with the distribution. 13141261Sdelphij * 3. All advertising materials mentioning features or use of this software 14141261Sdelphij * must display the following acknowledgement: 15141261Sdelphij * This product includes software developed by the University of 16141261Sdelphij * California, Berkeley and its contributors. 17141261Sdelphij * 4. Neither the name of the University nor the names of its contributors 18141261Sdelphij * may be used to endorse or promote products derived from this software 19141261Sdelphij * without specific prior written permission. 20141261Sdelphij * 21141261Sdelphij * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22141261Sdelphij * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23141261Sdelphij * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24141261Sdelphij * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25141261Sdelphij * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26141261Sdelphij * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27141261Sdelphij * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28141261Sdelphij * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29141261Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30141261Sdelphij * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31141261Sdelphij * SUCH DAMAGE. 32141261Sdelphij */ 33141261Sdelphij 34141261Sdelphij#ifndef lint 35141261Sdelphij#if 0 36141261Sdelphijstatic char sccsid[] = "@(#)compare.c 8.1 (Berkeley) 6/6/93"; 37141261Sdelphij#endif 38141261Sdelphijstatic const char rcsid[] = 39141261Sdelphij "$FreeBSD: head/usr.sbin/mtree/compare.c 66746 2000-10-06 12:27:36Z phk $"; 40158795Sdelphij#endif /* not lint */ 41158795Sdelphij 42158795Sdelphij#include <sys/param.h> 43141261Sdelphij#include <sys/stat.h> 44141261Sdelphij#include <err.h> 45141261Sdelphij#include <errno.h> 46141261Sdelphij#include <fcntl.h> 47141261Sdelphij#include <fts.h> 48141261Sdelphij#ifdef MD5 49141261Sdelphij#include <md5.h> 50141261Sdelphij#endif 51141261Sdelphij#ifdef SHA1 52141261Sdelphij#include <sha.h> 53158795Sdelphij#endif 54158795Sdelphij#ifdef RMD160 55141261Sdelphij#include <ripemd.h> 56158795Sdelphij#endif 57158795Sdelphij#include <stdio.h> 58158795Sdelphij#include <time.h> 59158795Sdelphij#include <unistd.h> 60141261Sdelphij#include "mtree.h" 61158795Sdelphij#include "extern.h" 62158795Sdelphij 63158795Sdelphijextern int uflag; 64141261Sdelphijextern int lineno; 65158795Sdelphij 66158795Sdelphijstatic char *ftype __P((u_int)); 67141261Sdelphij 68158795Sdelphij#define INDENTNAMELEN 8 69158795Sdelphij#define LABEL \ 70158795Sdelphij if (!label++) { \ 71158795Sdelphij len = printf("%s changed\n", RP(p)); \ 72158795Sdelphij tab = "\t"; \ 73158795Sdelphij } 74158795Sdelphij 75158795Sdelphijint 76158795Sdelphijcompare(name, s, p) 77158795Sdelphij char *name; 78158795Sdelphij register NODE *s; 79158795Sdelphij register FTSENT *p; 80141261Sdelphij{ 81158795Sdelphij extern int uflag; 82158795Sdelphij u_long len, val; 83158795Sdelphij int fd, label; 84158795Sdelphij char *cp, *tab = ""; 85158795Sdelphij char *fflags; 86158795Sdelphij 87158795Sdelphij label = 0; 88141261Sdelphij switch(s->type) { 89141261Sdelphij case F_BLOCK: 90141261Sdelphij if (!S_ISBLK(p->fts_statp->st_mode)) 91158795Sdelphij goto typeerr; 92141261Sdelphij break; 93158795Sdelphij case F_CHAR: 94141261Sdelphij if (!S_ISCHR(p->fts_statp->st_mode)) 95141261Sdelphij goto typeerr; 96141261Sdelphij break; 97141261Sdelphij case F_DIR: 98158795Sdelphij if (!S_ISDIR(p->fts_statp->st_mode)) 99141261Sdelphij goto typeerr; 100141261Sdelphij break; 101141261Sdelphij case F_FIFO: 102141261Sdelphij if (!S_ISFIFO(p->fts_statp->st_mode)) 103141261Sdelphij goto typeerr; 104141261Sdelphij break; 105141261Sdelphij case F_FILE: 106141261Sdelphij if (!S_ISREG(p->fts_statp->st_mode)) 107141261Sdelphij goto typeerr; 108141261Sdelphij break; 109141261Sdelphij case F_LINK: 110141261Sdelphij if (!S_ISLNK(p->fts_statp->st_mode)) 111141261Sdelphij goto typeerr; 112158795Sdelphij break; 113158795Sdelphij case F_SOCK: 114158795Sdelphij if (!S_ISSOCK(p->fts_statp->st_mode)) { 115158795Sdelphijtypeerr: LABEL; 116158795Sdelphij (void)printf("\ttype expected %s found %s\n", 117158795Sdelphij ftype(s->type), inotype(p->fts_statp->st_mode)); 118158795Sdelphij } 119158795Sdelphij break; 120158795Sdelphij } 121158795Sdelphij /* Set the uid/gid first, then set the mode. */ 122158795Sdelphij if (s->flags & (F_UID | F_UNAME) && s->st_uid != p->fts_statp->st_uid) { 123158795Sdelphij LABEL; 124158795Sdelphij (void)printf("%suser expected %lu found %lu", 125141261Sdelphij tab, (u_long)s->st_uid, (u_long)p->fts_statp->st_uid); 126158795Sdelphij if (uflag) 127158795Sdelphij if (chown(p->fts_accpath, s->st_uid, -1)) 128158795Sdelphij (void)printf(" not modified: %s\n", 129158795Sdelphij strerror(errno)); 130141261Sdelphij else 131158795Sdelphij (void)printf(" modified\n"); 132158795Sdelphij else 133141261Sdelphij (void)printf("\n"); 134158795Sdelphij tab = "\t"; 135158795Sdelphij } 136158795Sdelphij if (s->flags & (F_GID | F_GNAME) && s->st_gid != p->fts_statp->st_gid) { 137158795Sdelphij LABEL; 138141261Sdelphij (void)printf("%sgid expected %lu found %lu", 139158795Sdelphij tab, (u_long)s->st_gid, (u_long)p->fts_statp->st_gid); 140141261Sdelphij if (uflag) 141141261Sdelphij if (chown(p->fts_accpath, -1, s->st_gid)) 142141261Sdelphij (void)printf(" not modified: %s\n", 143141261Sdelphij strerror(errno)); 144158795Sdelphij else 145158795Sdelphij (void)printf(" modified\n"); 146158795Sdelphij else 147158795Sdelphij (void)printf("\n"); 148158795Sdelphij tab = "\t"; 149158795Sdelphij } 150158795Sdelphij if (s->flags & F_MODE && 151158795Sdelphij !S_ISLNK(p->fts_statp->st_mode) && 152158795Sdelphij s->st_mode != (p->fts_statp->st_mode & MBITS)) { 153158795Sdelphij LABEL; 154141261Sdelphij (void)printf("%spermissions expected %#o found %#o", 155141261Sdelphij tab, s->st_mode, p->fts_statp->st_mode & MBITS); 156141261Sdelphij if (uflag) 157158795Sdelphij if (chmod(p->fts_accpath, s->st_mode)) 158141261Sdelphij (void)printf(" not modified: %s\n", 159158795Sdelphij strerror(errno)); 160158795Sdelphij else 161158795Sdelphij (void)printf(" modified\n"); 162158795Sdelphij else 163141261Sdelphij (void)printf("\n"); 164141261Sdelphij tab = "\t"; 165141261Sdelphij } 166141261Sdelphij if (s->flags & F_NLINK && s->type != F_DIR && 167141261Sdelphij s->st_nlink != p->fts_statp->st_nlink) { 168158795Sdelphij LABEL; 169141261Sdelphij (void)printf("%slink_count expected %u found %u\n", 170158795Sdelphij tab, s->st_nlink, p->fts_statp->st_nlink); 171141261Sdelphij tab = "\t"; 172158795Sdelphij } 173158795Sdelphij if (s->flags & F_SIZE && s->st_size != p->fts_statp->st_size && 174158795Sdelphij !S_ISDIR(p->fts_statp->st_mode)) { 175158795Sdelphij LABEL; 176141261Sdelphij (void)printf("%ssize expected %qd found %qd\n", 177158795Sdelphij tab, s->st_size, p->fts_statp->st_size); 178141261Sdelphij tab = "\t"; 179158795Sdelphij } 180158795Sdelphij /* 181158795Sdelphij * XXX 182141261Sdelphij * Catches nano-second differences, but doesn't display them. 183158795Sdelphij */ 184158795Sdelphij if ((s->flags & F_TIME) && 185158795Sdelphij ((s->st_mtimespec.tv_sec != p->fts_statp->st_mtimespec.tv_sec) || 186158795Sdelphij (s->st_mtimespec.tv_nsec != p->fts_statp->st_mtimespec.tv_nsec))) { 187158795Sdelphij LABEL; 188158795Sdelphij (void)printf("%smodification time expected %.24s ", 189158795Sdelphij tab, ctime(&s->st_mtimespec.tv_sec)); 190158795Sdelphij (void)printf("found %.24s\n", 191158795Sdelphij ctime(&p->fts_statp->st_mtimespec.tv_sec)); 192158795Sdelphij tab = "\t"; 193158795Sdelphij } 194158795Sdelphij if (s->flags & F_CKSUM) { 195158795Sdelphij if ((fd = open(p->fts_accpath, O_RDONLY, 0)) < 0) { 196158795Sdelphij LABEL; 197158795Sdelphij (void)printf("%scksum: %s: %s\n", 198158795Sdelphij tab, p->fts_accpath, strerror(errno)); 199158795Sdelphij tab = "\t"; 200158795Sdelphij } else if (crc(fd, &val, &len)) { 201158795Sdelphij (void)close(fd); 202158795Sdelphij LABEL; 203158795Sdelphij (void)printf("%scksum: %s: %s\n", 204158795Sdelphij tab, p->fts_accpath, strerror(errno)); 205158795Sdelphij tab = "\t"; 206158795Sdelphij } else { 207158795Sdelphij (void)close(fd); 208158795Sdelphij if (s->cksum != val) { 209158795Sdelphij LABEL; 210158795Sdelphij (void)printf("%scksum expected %lu found %lu\n", 211158795Sdelphij tab, s->cksum, val); 212158795Sdelphij } 213158795Sdelphij tab = "\t"; 214158795Sdelphij } 215158795Sdelphij } 216158795Sdelphij /* 217158795Sdelphij * XXX 218158795Sdelphij * since chflags(2) will reset file times, the utimes() above 219158795Sdelphij * may have been useless! oh well, we'd rather have correct 220141261Sdelphij * flags, rather than times? 221158795Sdelphij */ 222158795Sdelphij if ((s->flags & F_FLAGS) && s->st_flags != p->fts_statp->st_flags) { 223158795Sdelphij LABEL; 224158795Sdelphij fflags = flags_to_string(s->st_flags); 225158795Sdelphij (void)printf("%sflags expected \"%s\"", tab, fflags); 226141261Sdelphij free(fflags); 227158795Sdelphij 228141261Sdelphij fflags = flags_to_string(p->fts_statp->st_flags); 229158795Sdelphij (void)printf(" found \"%s\"", fflags); 230141261Sdelphij free(fflags); 231158795Sdelphij 232158795Sdelphij if (uflag) 233158795Sdelphij if (chflags(p->fts_accpath, s->st_flags)) 234158795Sdelphij (void)printf(" not modified: %s\n", 235141261Sdelphij strerror(errno)); 236141261Sdelphij else 237141261Sdelphij (void)printf(" modified\n"); 238158795Sdelphij else 239158795Sdelphij (void)printf("\n"); 240141261Sdelphij tab = "\t"; 241158795Sdelphij } 242141261Sdelphij#ifdef MD5 243158795Sdelphij if (s->flags & F_MD5) { 244158795Sdelphij char *new_digest, buf[33]; 245158795Sdelphij 246141261Sdelphij new_digest = MD5File(p->fts_accpath, buf); 247158795Sdelphij if (!new_digest) { 248141261Sdelphij LABEL; 249158795Sdelphij printf("%sMD5: %s: %s\n", tab, p->fts_accpath, 250141261Sdelphij strerror(errno)); 251158795Sdelphij tab = "\t"; 252141261Sdelphij } else if (strcmp(new_digest, s->md5digest)) { 253141261Sdelphij LABEL; 254141261Sdelphij printf("%sMD5 expected %s found %s\n", tab, s->md5digest, 255141261Sdelphij new_digest); 256141261Sdelphij tab = "\t"; 257158795Sdelphij } 258141261Sdelphij } 259141261Sdelphij#endif /* MD5 */ 260141261Sdelphij#ifdef SHA1 261141261Sdelphij if (s->flags & F_SHA1) { 262158795Sdelphij char *new_digest, buf[41]; 263141261Sdelphij 264141261Sdelphij new_digest = SHA1_File(p->fts_accpath, buf); 265141261Sdelphij if (!new_digest) { 266158795Sdelphij LABEL; 267141261Sdelphij printf("%sSHA-1: %s: %s\n", tab, p->fts_accpath, 268141261Sdelphij strerror(errno)); 269158795Sdelphij tab = "\t"; 270158795Sdelphij } else if (strcmp(new_digest, s->sha1digest)) { 271141261Sdelphij LABEL; 272141261Sdelphij printf("%sSHA-1 expected %s found %s\n", 273158795Sdelphij tab, s->sha1digest, new_digest); 274141261Sdelphij tab = "\t"; 275158795Sdelphij } 276141261Sdelphij } 277158795Sdelphij#endif /* SHA1 */ 278158795Sdelphij#ifdef RMD160 279158795Sdelphij if (s->flags & F_RMD160) { 280158795Sdelphij char *new_digest, buf[41]; 281158795Sdelphij 282158795Sdelphij new_digest = RIPEMD160_File(p->fts_accpath, buf); 283158795Sdelphij if (!new_digest) { 284158795Sdelphij LABEL; 285158795Sdelphij printf("%sRIPEMD160: %s: %s\n", tab, 286158795Sdelphij p->fts_accpath, strerror(errno)); 287158795Sdelphij tab = "\t"; 288158795Sdelphij } else if (strcmp(new_digest, s->rmd160digest)) { 289158795Sdelphij LABEL; 290158795Sdelphij printf("%sRIPEMD160 expected %s found %s\n", 291158795Sdelphij tab, s->rmd160digest, new_digest); 292158795Sdelphij tab = "\t"; 293158795Sdelphij } 294158795Sdelphij } 295158795Sdelphij#endif /* RMD160 */ 296158795Sdelphij 297158795Sdelphij if (s->flags & F_SLINK && 298158795Sdelphij strcmp(cp = rlink(p->fts_accpath), s->slink)) { 299158795Sdelphij LABEL; 300158795Sdelphij (void)printf("%slink_ref expected %s found %s\n", 301158795Sdelphij tab, cp, s->slink); 302158795Sdelphij } 303158795Sdelphij return (label); 304158795Sdelphij} 305158795Sdelphij 306158795Sdelphijchar * 307158795Sdelphijinotype(type) 308158795Sdelphij u_int type; 309158795Sdelphij{ 310158795Sdelphij switch(type & S_IFMT) { 311158795Sdelphij case S_IFBLK: 312158795Sdelphij return ("block"); 313158795Sdelphij case S_IFCHR: 314141261Sdelphij return ("char"); 315141261Sdelphij case S_IFDIR: 316141261Sdelphij return ("dir"); 317141261Sdelphij case S_IFIFO: 318141261Sdelphij return ("fifo"); 319158795Sdelphij case S_IFREG: 320158795Sdelphij return ("file"); 321141261Sdelphij case S_IFLNK: 322158795Sdelphij return ("link"); 323141261Sdelphij case S_IFSOCK: 324158795Sdelphij return ("socket"); 325141261Sdelphij default: 326 return ("unknown"); 327 } 328 /* NOTREACHED */ 329} 330 331static char * 332ftype(type) 333 u_int type; 334{ 335 switch(type) { 336 case F_BLOCK: 337 return ("block"); 338 case F_CHAR: 339 return ("char"); 340 case F_DIR: 341 return ("dir"); 342 case F_FIFO: 343 return ("fifo"); 344 case F_FILE: 345 return ("file"); 346 case F_LINK: 347 return ("link"); 348 case F_SOCK: 349 return ("socket"); 350 default: 351 return ("unknown"); 352 } 353 /* NOTREACHED */ 354} 355 356char * 357rlink(name) 358 char *name; 359{ 360 static char lbuf[MAXPATHLEN]; 361 register int len; 362 363 if ((len = readlink(name, lbuf, sizeof(lbuf) - 1)) == -1) 364 err(1, "line %d: %s", lineno, name); 365 lbuf[len] = '\0'; 366 return (lbuf); 367} 368