11553Srgrimes/*- 21553Srgrimes * Copyright (c) 1989, 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[] = "@(#)compare.c 8.1 (Berkeley) 6/6/93"; 33114601Sobrien#endif /* not lint */ 3430027Scharnier#endif 35114601Sobrien#include <sys/cdefs.h> 36114601Sobrien__FBSDID("$FreeBSD$"); 371553Srgrimes 381553Srgrimes#include <sys/param.h> 391553Srgrimes#include <sys/stat.h> 40121853Sbde#include <sys/time.h> 41121853Sbde 4230027Scharnier#include <err.h> 4330027Scharnier#include <errno.h> 441553Srgrimes#include <fcntl.h> 451553Srgrimes#include <fts.h> 4644303Swollman#ifdef MD5 4730027Scharnier#include <md5.h> 4844303Swollman#endif 49121853Sbde#ifdef RMD160 50121853Sbde#include <ripemd.h> 51121853Sbde#endif 5244303Swollman#ifdef SHA1 5344303Swollman#include <sha.h> 5444303Swollman#endif 55144295Stobez#ifdef SHA256 56144295Stobez#include <sha256.h> 57144295Stobez#endif 58100070Sdes#include <stdint.h> 591553Srgrimes#include <stdio.h> 601553Srgrimes#include <time.h> 611553Srgrimes#include <unistd.h> 62121853Sbde#include <vis.h> 63121853Sbde 641553Srgrimes#include "mtree.h" 651553Srgrimes#include "extern.h" 661553Srgrimes 671553Srgrimes#define INDENTNAMELEN 8 681553Srgrimes#define LABEL \ 691553Srgrimes if (!label++) { \ 7066584Sphk len = printf("%s changed\n", RP(p)); \ 7166584Sphk tab = "\t"; \ 721553Srgrimes } 731553Srgrimes 741553Srgrimesint 75121299Sphkcompare(char *name __unused, NODE *s, FTSENT *p) 761553Srgrimes{ 77121853Sbde struct timeval tv[2]; 78112214Srobert uint32_t val; 791553Srgrimes int fd, label; 80112214Srobert off_t len; 8199802Salfred char *cp; 8299802Salfred const char *tab = ""; 8361749Sjoe char *fflags; 841553Srgrimes 851553Srgrimes label = 0; 861553Srgrimes switch(s->type) { 871553Srgrimes case F_BLOCK: 881553Srgrimes if (!S_ISBLK(p->fts_statp->st_mode)) 891553Srgrimes goto typeerr; 901553Srgrimes break; 911553Srgrimes case F_CHAR: 921553Srgrimes if (!S_ISCHR(p->fts_statp->st_mode)) 931553Srgrimes goto typeerr; 941553Srgrimes break; 951553Srgrimes case F_DIR: 961553Srgrimes if (!S_ISDIR(p->fts_statp->st_mode)) 971553Srgrimes goto typeerr; 981553Srgrimes break; 991553Srgrimes case F_FIFO: 1001553Srgrimes if (!S_ISFIFO(p->fts_statp->st_mode)) 1011553Srgrimes goto typeerr; 1021553Srgrimes break; 1031553Srgrimes case F_FILE: 1041553Srgrimes if (!S_ISREG(p->fts_statp->st_mode)) 1051553Srgrimes goto typeerr; 1061553Srgrimes break; 1071553Srgrimes case F_LINK: 1081553Srgrimes if (!S_ISLNK(p->fts_statp->st_mode)) 1091553Srgrimes goto typeerr; 1101553Srgrimes break; 1111553Srgrimes case F_SOCK: 1121553Srgrimes if (!S_ISSOCK(p->fts_statp->st_mode)) { 1131553Srgrimestypeerr: LABEL; 11466584Sphk (void)printf("\ttype expected %s found %s\n", 1151553Srgrimes ftype(s->type), inotype(p->fts_statp->st_mode)); 11666747Sphk return (label); 1171553Srgrimes } 1181553Srgrimes break; 1191553Srgrimes } 1201553Srgrimes /* Set the uid/gid first, then set the mode. */ 1211553Srgrimes if (s->flags & (F_UID | F_UNAME) && s->st_uid != p->fts_statp->st_uid) { 1221553Srgrimes LABEL; 12366584Sphk (void)printf("%suser expected %lu found %lu", 12438020Sbde tab, (u_long)s->st_uid, (u_long)p->fts_statp->st_uid); 1251553Srgrimes if (uflag) 1261553Srgrimes if (chown(p->fts_accpath, s->st_uid, -1)) 12766584Sphk (void)printf(" not modified: %s\n", 1281553Srgrimes strerror(errno)); 1291553Srgrimes else 13066584Sphk (void)printf(" modified\n"); 1311553Srgrimes else 13266584Sphk (void)printf("\n"); 1331553Srgrimes tab = "\t"; 1341553Srgrimes } 1351553Srgrimes if (s->flags & (F_GID | F_GNAME) && s->st_gid != p->fts_statp->st_gid) { 1361553Srgrimes LABEL; 13766584Sphk (void)printf("%sgid expected %lu found %lu", 13838020Sbde tab, (u_long)s->st_gid, (u_long)p->fts_statp->st_gid); 1391553Srgrimes if (uflag) 1401553Srgrimes if (chown(p->fts_accpath, -1, s->st_gid)) 14166584Sphk (void)printf(" not modified: %s\n", 1421553Srgrimes strerror(errno)); 1431553Srgrimes else 14466584Sphk (void)printf(" modified\n"); 1451553Srgrimes else 14666584Sphk (void)printf("\n"); 1471553Srgrimes tab = "\t"; 1481553Srgrimes } 1491553Srgrimes if (s->flags & F_MODE && 15066746Sphk !S_ISLNK(p->fts_statp->st_mode) && 1511553Srgrimes s->st_mode != (p->fts_statp->st_mode & MBITS)) { 1521553Srgrimes LABEL; 15366584Sphk (void)printf("%spermissions expected %#o found %#o", 1541553Srgrimes tab, s->st_mode, p->fts_statp->st_mode & MBITS); 1551553Srgrimes if (uflag) 1561553Srgrimes if (chmod(p->fts_accpath, s->st_mode)) 15766584Sphk (void)printf(" not modified: %s\n", 1581553Srgrimes strerror(errno)); 1591553Srgrimes else 16066584Sphk (void)printf(" modified\n"); 1611553Srgrimes else 16266584Sphk (void)printf("\n"); 1631553Srgrimes tab = "\t"; 1641553Srgrimes } 1651553Srgrimes if (s->flags & F_NLINK && s->type != F_DIR && 1661553Srgrimes s->st_nlink != p->fts_statp->st_nlink) { 1671553Srgrimes LABEL; 16866584Sphk (void)printf("%slink_count expected %u found %u\n", 1691553Srgrimes tab, s->st_nlink, p->fts_statp->st_nlink); 1701553Srgrimes tab = "\t"; 1711553Srgrimes } 17266584Sphk if (s->flags & F_SIZE && s->st_size != p->fts_statp->st_size && 17366584Sphk !S_ISDIR(p->fts_statp->st_mode)) { 1741553Srgrimes LABEL; 175100070Sdes (void)printf("%ssize expected %jd found %jd\n", tab, 176100070Sdes (intmax_t)s->st_size, (intmax_t)p->fts_statp->st_size); 1771553Srgrimes tab = "\t"; 1781553Srgrimes } 1791553Srgrimes /* 1801553Srgrimes * XXX 1811553Srgrimes * Catches nano-second differences, but doesn't display them. 1821553Srgrimes */ 1833052Sdg if ((s->flags & F_TIME) && 184205793Sed ((s->st_mtimespec.tv_sec != p->fts_statp->st_mtim.tv_sec) || 185205793Sed (s->st_mtimespec.tv_nsec != p->fts_statp->st_mtim.tv_nsec))) { 1861553Srgrimes LABEL; 18766584Sphk (void)printf("%smodification time expected %.24s ", 18818404Snate tab, ctime(&s->st_mtimespec.tv_sec)); 189121798Sphk (void)printf("found %.24s", 190205793Sed ctime(&p->fts_statp->st_mtim.tv_sec)); 191121798Sphk if (uflag) { 192121798Sphk tv[0].tv_sec = s->st_mtimespec.tv_sec; 193121798Sphk tv[0].tv_usec = s->st_mtimespec.tv_nsec / 1000; 194121798Sphk tv[1] = tv[0]; 195121798Sphk if (utimes(p->fts_accpath, tv)) 196121798Sphk (void)printf(" not modified: %s\n", 197121798Sphk strerror(errno)); 198121798Sphk else 199121798Sphk (void)printf(" modified\n"); 200121798Sphk } else 201121798Sphk (void)printf("\n"); 2021553Srgrimes tab = "\t"; 2031553Srgrimes } 20451705Sbillf if (s->flags & F_CKSUM) { 2051553Srgrimes if ((fd = open(p->fts_accpath, O_RDONLY, 0)) < 0) { 2061553Srgrimes LABEL; 2071553Srgrimes (void)printf("%scksum: %s: %s\n", 2081553Srgrimes tab, p->fts_accpath, strerror(errno)); 2091553Srgrimes tab = "\t"; 2101553Srgrimes } else if (crc(fd, &val, &len)) { 2111553Srgrimes (void)close(fd); 2121553Srgrimes LABEL; 2131553Srgrimes (void)printf("%scksum: %s: %s\n", 2141553Srgrimes tab, p->fts_accpath, strerror(errno)); 2151553Srgrimes tab = "\t"; 2161553Srgrimes } else { 2171553Srgrimes (void)close(fd); 2181553Srgrimes if (s->cksum != val) { 2191553Srgrimes LABEL; 22066584Sphk (void)printf("%scksum expected %lu found %lu\n", 221112214Srobert tab, s->cksum, (unsigned long)val); 222112194Stobez tab = "\t"; 2231553Srgrimes } 2241553Srgrimes } 22551705Sbillf } 22654375Sjoe if ((s->flags & F_FLAGS) && s->st_flags != p->fts_statp->st_flags) { 22754375Sjoe LABEL; 22861749Sjoe fflags = flags_to_string(s->st_flags); 22966584Sphk (void)printf("%sflags expected \"%s\"", tab, fflags); 23061749Sjoe free(fflags); 23161749Sjoe 23261749Sjoe fflags = flags_to_string(p->fts_statp->st_flags); 23366584Sphk (void)printf(" found \"%s\"", fflags); 23461749Sjoe free(fflags); 23561749Sjoe 23654375Sjoe if (uflag) 23754375Sjoe if (chflags(p->fts_accpath, s->st_flags)) 23866584Sphk (void)printf(" not modified: %s\n", 23954375Sjoe strerror(errno)); 24054375Sjoe else 24166584Sphk (void)printf(" modified\n"); 24254375Sjoe else 24366584Sphk (void)printf("\n"); 24454375Sjoe tab = "\t"; 24554375Sjoe } 24644303Swollman#ifdef MD5 2476286Swollman if (s->flags & F_MD5) { 2489490Sphk char *new_digest, buf[33]; 2498857Srgrimes 25044303Swollman new_digest = MD5File(p->fts_accpath, buf); 2516286Swollman if (!new_digest) { 2526286Swollman LABEL; 25366584Sphk printf("%sMD5: %s: %s\n", tab, p->fts_accpath, 2546286Swollman strerror(errno)); 2556286Swollman tab = "\t"; 2566286Swollman } else if (strcmp(new_digest, s->md5digest)) { 2576286Swollman LABEL; 25866584Sphk printf("%sMD5 expected %s found %s\n", tab, s->md5digest, 2596286Swollman new_digest); 2606286Swollman tab = "\t"; 2616286Swollman } 2626286Swollman } 26344303Swollman#endif /* MD5 */ 26444303Swollman#ifdef SHA1 26544303Swollman if (s->flags & F_SHA1) { 26644303Swollman char *new_digest, buf[41]; 2676286Swollman 26844303Swollman new_digest = SHA1_File(p->fts_accpath, buf); 26944303Swollman if (!new_digest) { 27044303Swollman LABEL; 27166584Sphk printf("%sSHA-1: %s: %s\n", tab, p->fts_accpath, 27244303Swollman strerror(errno)); 27344303Swollman tab = "\t"; 27444303Swollman } else if (strcmp(new_digest, s->sha1digest)) { 27544303Swollman LABEL; 276121300Sphk printf("%sSHA-1 expected %s found %s\n", 27766584Sphk tab, s->sha1digest, new_digest); 27844303Swollman tab = "\t"; 27944303Swollman } 28044303Swollman } 28144303Swollman#endif /* SHA1 */ 28244303Swollman#ifdef RMD160 28344303Swollman if (s->flags & F_RMD160) { 28444303Swollman char *new_digest, buf[41]; 28544303Swollman 28644303Swollman new_digest = RIPEMD160_File(p->fts_accpath, buf); 28744303Swollman if (!new_digest) { 28844303Swollman LABEL; 28966584Sphk printf("%sRIPEMD160: %s: %s\n", tab, 29044303Swollman p->fts_accpath, strerror(errno)); 29144303Swollman tab = "\t"; 29244303Swollman } else if (strcmp(new_digest, s->rmd160digest)) { 29344303Swollman LABEL; 29466584Sphk printf("%sRIPEMD160 expected %s found %s\n", 29566584Sphk tab, s->rmd160digest, new_digest); 29644303Swollman tab = "\t"; 29744303Swollman } 29844303Swollman } 29944303Swollman#endif /* RMD160 */ 300144295Stobez#ifdef SHA256 301144295Stobez if (s->flags & F_SHA256) { 302144295Stobez char *new_digest, buf[65]; 30344303Swollman 304144295Stobez new_digest = SHA256_File(p->fts_accpath, buf); 305144295Stobez if (!new_digest) { 306144295Stobez LABEL; 307144295Stobez printf("%sSHA-256: %s: %s\n", tab, p->fts_accpath, 308144295Stobez strerror(errno)); 309144295Stobez tab = "\t"; 310144295Stobez } else if (strcmp(new_digest, s->sha256digest)) { 311144295Stobez LABEL; 312144295Stobez printf("%sSHA-256 expected %s found %s\n", 313144295Stobez tab, s->sha256digest, new_digest); 314144295Stobez tab = "\t"; 315144295Stobez } 316144295Stobez } 317144295Stobez#endif /* SHA256 */ 318144295Stobez 31965812Ssheldonh if (s->flags & F_SLINK && 32065812Ssheldonh strcmp(cp = rlink(p->fts_accpath), s->slink)) { 3211553Srgrimes LABEL; 32266584Sphk (void)printf("%slink_ref expected %s found %s\n", 323112194Stobez tab, s->slink, cp); 3241553Srgrimes } 3251553Srgrimes return (label); 3261553Srgrimes} 3271553Srgrimes 32899802Salfredconst char * 329121299Sphkinotype(u_int type) 3301553Srgrimes{ 3311553Srgrimes switch(type & S_IFMT) { 3321553Srgrimes case S_IFBLK: 3331553Srgrimes return ("block"); 3341553Srgrimes case S_IFCHR: 3351553Srgrimes return ("char"); 3361553Srgrimes case S_IFDIR: 3371553Srgrimes return ("dir"); 3381553Srgrimes case S_IFIFO: 3391553Srgrimes return ("fifo"); 3401553Srgrimes case S_IFREG: 3411553Srgrimes return ("file"); 3421553Srgrimes case S_IFLNK: 3431553Srgrimes return ("link"); 3441553Srgrimes case S_IFSOCK: 3451553Srgrimes return ("socket"); 3461553Srgrimes default: 3471553Srgrimes return ("unknown"); 3481553Srgrimes } 3491553Srgrimes /* NOTREACHED */ 3501553Srgrimes} 3511553Srgrimes 352122141Sphkconst char * 353121299Sphkftype(u_int type) 3541553Srgrimes{ 3551553Srgrimes switch(type) { 3561553Srgrimes case F_BLOCK: 3571553Srgrimes return ("block"); 3581553Srgrimes case F_CHAR: 3591553Srgrimes return ("char"); 3601553Srgrimes case F_DIR: 3611553Srgrimes return ("dir"); 3621553Srgrimes case F_FIFO: 3631553Srgrimes return ("fifo"); 3641553Srgrimes case F_FILE: 3651553Srgrimes return ("file"); 3661553Srgrimes case F_LINK: 3671553Srgrimes return ("link"); 3681553Srgrimes case F_SOCK: 3691553Srgrimes return ("socket"); 3701553Srgrimes default: 3711553Srgrimes return ("unknown"); 3721553Srgrimes } 3731553Srgrimes /* NOTREACHED */ 3741553Srgrimes} 3751553Srgrimes 3761553Srgrimeschar * 377121299Sphkrlink(char *name) 3781553Srgrimes{ 379121734Sphk static char lbuf[MAXPATHLEN * 4]; 380121299Sphk int len; 381121853Sbde char tbuf[MAXPATHLEN]; 3821553Srgrimes 383121734Sphk if ((len = readlink(name, tbuf, sizeof(tbuf) - 1)) == -1) 38430027Scharnier err(1, "line %d: %s", lineno, name); 385121734Sphk tbuf[len] = '\0'; 386121734Sphk strvis(lbuf, tbuf, VIS_WHITE | VIS_OCTAL); 3871553Srgrimes return (lbuf); 3881553Srgrimes} 389