compare.c revision 99802
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. 131553Srgrimes * 3. All advertising materials mentioning features or use of this software 141553Srgrimes * must display the following acknowledgement: 151553Srgrimes * This product includes software developed by the University of 161553Srgrimes * California, Berkeley and its contributors. 171553Srgrimes * 4. Neither the name of the University nor the names of its contributors 181553Srgrimes * may be used to endorse or promote products derived from this software 191553Srgrimes * without specific prior written permission. 201553Srgrimes * 211553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241553Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311553Srgrimes * SUCH DAMAGE. 321553Srgrimes */ 331553Srgrimes 341553Srgrimes#ifndef lint 3530027Scharnier#if 0 361553Srgrimesstatic char sccsid[] = "@(#)compare.c 8.1 (Berkeley) 6/6/93"; 3730027Scharnier#endif 3830027Scharnierstatic const char rcsid[] = 3950479Speter "$FreeBSD: head/usr.sbin/mtree/compare.c 99802 2002-07-11 18:42:53Z alfred $"; 401553Srgrimes#endif /* not lint */ 411553Srgrimes 421553Srgrimes#include <sys/param.h> 431553Srgrimes#include <sys/stat.h> 4430027Scharnier#include <err.h> 4530027Scharnier#include <errno.h> 461553Srgrimes#include <fcntl.h> 471553Srgrimes#include <fts.h> 4844303Swollman#ifdef MD5 4930027Scharnier#include <md5.h> 5044303Swollman#endif 5144303Swollman#ifdef SHA1 5244303Swollman#include <sha.h> 5344303Swollman#endif 5444303Swollman#ifdef RMD160 5544303Swollman#include <ripemd.h> 5644303Swollman#endif 571553Srgrimes#include <stdio.h> 581553Srgrimes#include <time.h> 591553Srgrimes#include <unistd.h> 601553Srgrimes#include "mtree.h" 611553Srgrimes#include "extern.h" 621553Srgrimes 631553Srgrimesextern int uflag; 6430027Scharnierextern int lineno; 651553Srgrimes 6699802Salfredstatic const char *ftype(u_int); 671553Srgrimes 681553Srgrimes#define INDENTNAMELEN 8 691553Srgrimes#define LABEL \ 701553Srgrimes if (!label++) { \ 7166584Sphk len = printf("%s changed\n", RP(p)); \ 7266584Sphk tab = "\t"; \ 731553Srgrimes } 741553Srgrimes 751553Srgrimesint 761553Srgrimescompare(name, s, p) 7799802Salfred char *name __unused; 781553Srgrimes register NODE *s; 791553Srgrimes register FTSENT *p; 801553Srgrimes{ 811553Srgrimes extern int uflag; 821553Srgrimes u_long len, val; 831553Srgrimes int fd, label; 8499802Salfred char *cp; 8599802Salfred const char *tab = ""; 8661749Sjoe char *fflags; 871553Srgrimes 881553Srgrimes label = 0; 891553Srgrimes switch(s->type) { 901553Srgrimes case F_BLOCK: 911553Srgrimes if (!S_ISBLK(p->fts_statp->st_mode)) 921553Srgrimes goto typeerr; 931553Srgrimes break; 941553Srgrimes case F_CHAR: 951553Srgrimes if (!S_ISCHR(p->fts_statp->st_mode)) 961553Srgrimes goto typeerr; 971553Srgrimes break; 981553Srgrimes case F_DIR: 991553Srgrimes if (!S_ISDIR(p->fts_statp->st_mode)) 1001553Srgrimes goto typeerr; 1011553Srgrimes break; 1021553Srgrimes case F_FIFO: 1031553Srgrimes if (!S_ISFIFO(p->fts_statp->st_mode)) 1041553Srgrimes goto typeerr; 1051553Srgrimes break; 1061553Srgrimes case F_FILE: 1071553Srgrimes if (!S_ISREG(p->fts_statp->st_mode)) 1081553Srgrimes goto typeerr; 1091553Srgrimes break; 1101553Srgrimes case F_LINK: 1111553Srgrimes if (!S_ISLNK(p->fts_statp->st_mode)) 1121553Srgrimes goto typeerr; 1131553Srgrimes break; 1141553Srgrimes case F_SOCK: 1151553Srgrimes if (!S_ISSOCK(p->fts_statp->st_mode)) { 1161553Srgrimestypeerr: LABEL; 11766584Sphk (void)printf("\ttype expected %s found %s\n", 1181553Srgrimes ftype(s->type), inotype(p->fts_statp->st_mode)); 11966747Sphk return (label); 1201553Srgrimes } 1211553Srgrimes break; 1221553Srgrimes } 1231553Srgrimes /* Set the uid/gid first, then set the mode. */ 1241553Srgrimes if (s->flags & (F_UID | F_UNAME) && s->st_uid != p->fts_statp->st_uid) { 1251553Srgrimes LABEL; 12666584Sphk (void)printf("%suser expected %lu found %lu", 12738020Sbde tab, (u_long)s->st_uid, (u_long)p->fts_statp->st_uid); 1281553Srgrimes if (uflag) 1291553Srgrimes if (chown(p->fts_accpath, s->st_uid, -1)) 13066584Sphk (void)printf(" not modified: %s\n", 1311553Srgrimes strerror(errno)); 1321553Srgrimes else 13366584Sphk (void)printf(" modified\n"); 1341553Srgrimes else 13566584Sphk (void)printf("\n"); 1361553Srgrimes tab = "\t"; 1371553Srgrimes } 1381553Srgrimes if (s->flags & (F_GID | F_GNAME) && s->st_gid != p->fts_statp->st_gid) { 1391553Srgrimes LABEL; 14066584Sphk (void)printf("%sgid expected %lu found %lu", 14138020Sbde tab, (u_long)s->st_gid, (u_long)p->fts_statp->st_gid); 1421553Srgrimes if (uflag) 1431553Srgrimes if (chown(p->fts_accpath, -1, s->st_gid)) 14466584Sphk (void)printf(" not modified: %s\n", 1451553Srgrimes strerror(errno)); 1461553Srgrimes else 14766584Sphk (void)printf(" modified\n"); 1481553Srgrimes else 14966584Sphk (void)printf("\n"); 1501553Srgrimes tab = "\t"; 1511553Srgrimes } 1521553Srgrimes if (s->flags & F_MODE && 15366746Sphk !S_ISLNK(p->fts_statp->st_mode) && 1541553Srgrimes s->st_mode != (p->fts_statp->st_mode & MBITS)) { 1551553Srgrimes LABEL; 15666584Sphk (void)printf("%spermissions expected %#o found %#o", 1571553Srgrimes tab, s->st_mode, p->fts_statp->st_mode & MBITS); 1581553Srgrimes if (uflag) 1591553Srgrimes if (chmod(p->fts_accpath, s->st_mode)) 16066584Sphk (void)printf(" not modified: %s\n", 1611553Srgrimes strerror(errno)); 1621553Srgrimes else 16366584Sphk (void)printf(" modified\n"); 1641553Srgrimes else 16566584Sphk (void)printf("\n"); 1661553Srgrimes tab = "\t"; 1671553Srgrimes } 1681553Srgrimes if (s->flags & F_NLINK && s->type != F_DIR && 1691553Srgrimes s->st_nlink != p->fts_statp->st_nlink) { 1701553Srgrimes LABEL; 17166584Sphk (void)printf("%slink_count expected %u found %u\n", 1721553Srgrimes tab, s->st_nlink, p->fts_statp->st_nlink); 1731553Srgrimes tab = "\t"; 1741553Srgrimes } 17566584Sphk if (s->flags & F_SIZE && s->st_size != p->fts_statp->st_size && 17666584Sphk !S_ISDIR(p->fts_statp->st_mode)) { 1771553Srgrimes LABEL; 17866584Sphk (void)printf("%ssize expected %qd found %qd\n", 1791553Srgrimes tab, s->st_size, p->fts_statp->st_size); 1801553Srgrimes tab = "\t"; 1811553Srgrimes } 1821553Srgrimes /* 1831553Srgrimes * XXX 1841553Srgrimes * Catches nano-second differences, but doesn't display them. 1851553Srgrimes */ 1863052Sdg if ((s->flags & F_TIME) && 18718404Snate ((s->st_mtimespec.tv_sec != p->fts_statp->st_mtimespec.tv_sec) || 18818404Snate (s->st_mtimespec.tv_nsec != p->fts_statp->st_mtimespec.tv_nsec))) { 1891553Srgrimes LABEL; 19066584Sphk (void)printf("%smodification time expected %.24s ", 19118404Snate tab, ctime(&s->st_mtimespec.tv_sec)); 19266584Sphk (void)printf("found %.24s\n", 19318404Snate ctime(&p->fts_statp->st_mtimespec.tv_sec)); 1941553Srgrimes tab = "\t"; 1951553Srgrimes } 19651705Sbillf if (s->flags & F_CKSUM) { 1971553Srgrimes if ((fd = open(p->fts_accpath, O_RDONLY, 0)) < 0) { 1981553Srgrimes LABEL; 1991553Srgrimes (void)printf("%scksum: %s: %s\n", 2001553Srgrimes tab, p->fts_accpath, strerror(errno)); 2011553Srgrimes tab = "\t"; 2021553Srgrimes } else if (crc(fd, &val, &len)) { 2031553Srgrimes (void)close(fd); 2041553Srgrimes LABEL; 2051553Srgrimes (void)printf("%scksum: %s: %s\n", 2061553Srgrimes tab, p->fts_accpath, strerror(errno)); 2071553Srgrimes tab = "\t"; 2081553Srgrimes } else { 2091553Srgrimes (void)close(fd); 2101553Srgrimes if (s->cksum != val) { 2111553Srgrimes LABEL; 21266584Sphk (void)printf("%scksum expected %lu found %lu\n", 2131553Srgrimes tab, s->cksum, val); 2141553Srgrimes } 2151553Srgrimes tab = "\t"; 2161553Srgrimes } 21751705Sbillf } 21854375Sjoe /* 21954375Sjoe * XXX 22054375Sjoe * since chflags(2) will reset file times, the utimes() above 22154375Sjoe * may have been useless! oh well, we'd rather have correct 22254375Sjoe * flags, rather than times? 22354375Sjoe */ 22454375Sjoe if ((s->flags & F_FLAGS) && s->st_flags != p->fts_statp->st_flags) { 22554375Sjoe LABEL; 22661749Sjoe fflags = flags_to_string(s->st_flags); 22766584Sphk (void)printf("%sflags expected \"%s\"", tab, fflags); 22861749Sjoe free(fflags); 22961749Sjoe 23061749Sjoe fflags = flags_to_string(p->fts_statp->st_flags); 23166584Sphk (void)printf(" found \"%s\"", fflags); 23261749Sjoe free(fflags); 23361749Sjoe 23454375Sjoe if (uflag) 23554375Sjoe if (chflags(p->fts_accpath, s->st_flags)) 23666584Sphk (void)printf(" not modified: %s\n", 23754375Sjoe strerror(errno)); 23854375Sjoe else 23966584Sphk (void)printf(" modified\n"); 24054375Sjoe else 24166584Sphk (void)printf("\n"); 24254375Sjoe tab = "\t"; 24354375Sjoe } 24444303Swollman#ifdef MD5 2456286Swollman if (s->flags & F_MD5) { 2469490Sphk char *new_digest, buf[33]; 2478857Srgrimes 24844303Swollman new_digest = MD5File(p->fts_accpath, buf); 2496286Swollman if (!new_digest) { 2506286Swollman LABEL; 25166584Sphk printf("%sMD5: %s: %s\n", tab, p->fts_accpath, 2526286Swollman strerror(errno)); 2536286Swollman tab = "\t"; 2546286Swollman } else if (strcmp(new_digest, s->md5digest)) { 2556286Swollman LABEL; 25666584Sphk printf("%sMD5 expected %s found %s\n", tab, s->md5digest, 2576286Swollman new_digest); 2586286Swollman tab = "\t"; 2596286Swollman } 2606286Swollman } 26144303Swollman#endif /* MD5 */ 26244303Swollman#ifdef SHA1 26344303Swollman if (s->flags & F_SHA1) { 26444303Swollman char *new_digest, buf[41]; 2656286Swollman 26644303Swollman new_digest = SHA1_File(p->fts_accpath, buf); 26744303Swollman if (!new_digest) { 26844303Swollman LABEL; 26966584Sphk printf("%sSHA-1: %s: %s\n", tab, p->fts_accpath, 27044303Swollman strerror(errno)); 27144303Swollman tab = "\t"; 27244303Swollman } else if (strcmp(new_digest, s->sha1digest)) { 27344303Swollman LABEL; 27466584Sphk printf("%sSHA-1 expected %s found %s\n", 27566584Sphk tab, s->sha1digest, new_digest); 27644303Swollman tab = "\t"; 27744303Swollman } 27844303Swollman } 27944303Swollman#endif /* SHA1 */ 28044303Swollman#ifdef RMD160 28144303Swollman if (s->flags & F_RMD160) { 28244303Swollman char *new_digest, buf[41]; 28344303Swollman 28444303Swollman new_digest = RIPEMD160_File(p->fts_accpath, buf); 28544303Swollman if (!new_digest) { 28644303Swollman LABEL; 28766584Sphk printf("%sRIPEMD160: %s: %s\n", tab, 28844303Swollman p->fts_accpath, strerror(errno)); 28944303Swollman tab = "\t"; 29044303Swollman } else if (strcmp(new_digest, s->rmd160digest)) { 29144303Swollman LABEL; 29266584Sphk printf("%sRIPEMD160 expected %s found %s\n", 29366584Sphk tab, s->rmd160digest, new_digest); 29444303Swollman tab = "\t"; 29544303Swollman } 29644303Swollman } 29744303Swollman#endif /* RMD160 */ 29844303Swollman 29965812Ssheldonh if (s->flags & F_SLINK && 30065812Ssheldonh strcmp(cp = rlink(p->fts_accpath), s->slink)) { 3011553Srgrimes LABEL; 30266584Sphk (void)printf("%slink_ref expected %s found %s\n", 30366584Sphk tab, cp, s->slink); 3041553Srgrimes } 3051553Srgrimes return (label); 3061553Srgrimes} 3071553Srgrimes 30899802Salfredconst char * 3091553Srgrimesinotype(type) 3101553Srgrimes u_int type; 3111553Srgrimes{ 3121553Srgrimes switch(type & S_IFMT) { 3131553Srgrimes case S_IFBLK: 3141553Srgrimes return ("block"); 3151553Srgrimes case S_IFCHR: 3161553Srgrimes return ("char"); 3171553Srgrimes case S_IFDIR: 3181553Srgrimes return ("dir"); 3191553Srgrimes case S_IFIFO: 3201553Srgrimes return ("fifo"); 3211553Srgrimes case S_IFREG: 3221553Srgrimes return ("file"); 3231553Srgrimes case S_IFLNK: 3241553Srgrimes return ("link"); 3251553Srgrimes case S_IFSOCK: 3261553Srgrimes return ("socket"); 3271553Srgrimes default: 3281553Srgrimes return ("unknown"); 3291553Srgrimes } 3301553Srgrimes /* NOTREACHED */ 3311553Srgrimes} 3321553Srgrimes 33399802Salfredstatic const char * 3341553Srgrimesftype(type) 3351553Srgrimes u_int type; 3361553Srgrimes{ 3371553Srgrimes switch(type) { 3381553Srgrimes case F_BLOCK: 3391553Srgrimes return ("block"); 3401553Srgrimes case F_CHAR: 3411553Srgrimes return ("char"); 3421553Srgrimes case F_DIR: 3431553Srgrimes return ("dir"); 3441553Srgrimes case F_FIFO: 3451553Srgrimes return ("fifo"); 3461553Srgrimes case F_FILE: 3471553Srgrimes return ("file"); 3481553Srgrimes case F_LINK: 3491553Srgrimes return ("link"); 3501553Srgrimes case F_SOCK: 3511553Srgrimes return ("socket"); 3521553Srgrimes default: 3531553Srgrimes return ("unknown"); 3541553Srgrimes } 3551553Srgrimes /* NOTREACHED */ 3561553Srgrimes} 3571553Srgrimes 3581553Srgrimeschar * 3591553Srgrimesrlink(name) 3601553Srgrimes char *name; 3611553Srgrimes{ 3621553Srgrimes static char lbuf[MAXPATHLEN]; 3631553Srgrimes register int len; 3641553Srgrimes 36536796Simp if ((len = readlink(name, lbuf, sizeof(lbuf) - 1)) == -1) 36630027Scharnier err(1, "line %d: %s", lineno, name); 3671553Srgrimes lbuf[len] = '\0'; 3681553Srgrimes return (lbuf); 3691553Srgrimes} 370