compare.c revision 65812
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 65812 2000-09-13 12:54:33Z sheldonh $"; 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 661553Srgrimesstatic char *ftype __P((u_int)); 671553Srgrimes 681553Srgrimes#define INDENTNAMELEN 8 691553Srgrimes#define LABEL \ 701553Srgrimes if (!label++) { \ 711553Srgrimes len = printf("%s: ", RP(p)); \ 721553Srgrimes if (len > INDENTNAMELEN) { \ 731553Srgrimes tab = "\t"; \ 741553Srgrimes (void)printf("\n"); \ 751553Srgrimes } else { \ 761553Srgrimes tab = ""; \ 772860Srgrimes (void)printf("%*s", INDENTNAMELEN - (int)len, ""); \ 781553Srgrimes } \ 791553Srgrimes } 801553Srgrimes 811553Srgrimesint 821553Srgrimescompare(name, s, p) 831553Srgrimes char *name; 841553Srgrimes register NODE *s; 851553Srgrimes register FTSENT *p; 861553Srgrimes{ 871553Srgrimes extern int uflag; 881553Srgrimes u_long len, val; 891553Srgrimes int fd, label; 902860Srgrimes char *cp, *tab = ""; 9161749Sjoe char *fflags; 921553Srgrimes 931553Srgrimes label = 0; 941553Srgrimes switch(s->type) { 951553Srgrimes case F_BLOCK: 961553Srgrimes if (!S_ISBLK(p->fts_statp->st_mode)) 971553Srgrimes goto typeerr; 981553Srgrimes break; 991553Srgrimes case F_CHAR: 1001553Srgrimes if (!S_ISCHR(p->fts_statp->st_mode)) 1011553Srgrimes goto typeerr; 1021553Srgrimes break; 1031553Srgrimes case F_DIR: 1041553Srgrimes if (!S_ISDIR(p->fts_statp->st_mode)) 1051553Srgrimes goto typeerr; 1061553Srgrimes break; 1071553Srgrimes case F_FIFO: 1081553Srgrimes if (!S_ISFIFO(p->fts_statp->st_mode)) 1091553Srgrimes goto typeerr; 1101553Srgrimes break; 1111553Srgrimes case F_FILE: 1121553Srgrimes if (!S_ISREG(p->fts_statp->st_mode)) 1131553Srgrimes goto typeerr; 1141553Srgrimes break; 1151553Srgrimes case F_LINK: 1161553Srgrimes if (!S_ISLNK(p->fts_statp->st_mode)) 1171553Srgrimes goto typeerr; 1181553Srgrimes break; 1191553Srgrimes case F_SOCK: 1201553Srgrimes if (!S_ISSOCK(p->fts_statp->st_mode)) { 1211553Srgrimestypeerr: LABEL; 1221553Srgrimes (void)printf("\ttype (%s, %s)\n", 1231553Srgrimes ftype(s->type), inotype(p->fts_statp->st_mode)); 1241553Srgrimes } 1251553Srgrimes break; 1261553Srgrimes } 1271553Srgrimes /* Set the uid/gid first, then set the mode. */ 1281553Srgrimes if (s->flags & (F_UID | F_UNAME) && s->st_uid != p->fts_statp->st_uid) { 1291553Srgrimes LABEL; 1302860Srgrimes (void)printf("%suser (%lu, %lu", 13138020Sbde tab, (u_long)s->st_uid, (u_long)p->fts_statp->st_uid); 1321553Srgrimes if (uflag) 1331553Srgrimes if (chown(p->fts_accpath, s->st_uid, -1)) 1341553Srgrimes (void)printf(", not modified: %s)\n", 1351553Srgrimes strerror(errno)); 1361553Srgrimes else 1371553Srgrimes (void)printf(", modified)\n"); 1381553Srgrimes else 1391553Srgrimes (void)printf(")\n"); 1401553Srgrimes tab = "\t"; 1411553Srgrimes } 1421553Srgrimes if (s->flags & (F_GID | F_GNAME) && s->st_gid != p->fts_statp->st_gid) { 1431553Srgrimes LABEL; 1442860Srgrimes (void)printf("%sgid (%lu, %lu", 14538020Sbde tab, (u_long)s->st_gid, (u_long)p->fts_statp->st_gid); 1461553Srgrimes if (uflag) 1471553Srgrimes if (chown(p->fts_accpath, -1, s->st_gid)) 1481553Srgrimes (void)printf(", not modified: %s)\n", 1491553Srgrimes strerror(errno)); 1501553Srgrimes else 1511553Srgrimes (void)printf(", modified)\n"); 1521553Srgrimes else 1531553Srgrimes (void)printf(")\n"); 1541553Srgrimes tab = "\t"; 1551553Srgrimes } 1561553Srgrimes if (s->flags & F_MODE && 1571553Srgrimes s->st_mode != (p->fts_statp->st_mode & MBITS)) { 1581553Srgrimes LABEL; 1591553Srgrimes (void)printf("%spermissions (%#o, %#o", 1601553Srgrimes tab, s->st_mode, p->fts_statp->st_mode & MBITS); 1611553Srgrimes if (uflag) 1621553Srgrimes if (chmod(p->fts_accpath, s->st_mode)) 1631553Srgrimes (void)printf(", not modified: %s)\n", 1641553Srgrimes strerror(errno)); 1651553Srgrimes else 1661553Srgrimes (void)printf(", modified)\n"); 1671553Srgrimes else 1681553Srgrimes (void)printf(")\n"); 1691553Srgrimes tab = "\t"; 1701553Srgrimes } 1711553Srgrimes if (s->flags & F_NLINK && s->type != F_DIR && 1721553Srgrimes s->st_nlink != p->fts_statp->st_nlink) { 1731553Srgrimes LABEL; 1741553Srgrimes (void)printf("%slink count (%u, %u)\n", 1751553Srgrimes tab, s->st_nlink, p->fts_statp->st_nlink); 1761553Srgrimes tab = "\t"; 1771553Srgrimes } 1781553Srgrimes if (s->flags & F_SIZE && s->st_size != p->fts_statp->st_size) { 1791553Srgrimes LABEL; 1801553Srgrimes (void)printf("%ssize (%qd, %qd)\n", 1811553Srgrimes tab, s->st_size, p->fts_statp->st_size); 1821553Srgrimes tab = "\t"; 1831553Srgrimes } 1841553Srgrimes /* 1851553Srgrimes * XXX 1861553Srgrimes * Catches nano-second differences, but doesn't display them. 1871553Srgrimes */ 1883052Sdg if ((s->flags & F_TIME) && 18918404Snate ((s->st_mtimespec.tv_sec != p->fts_statp->st_mtimespec.tv_sec) || 19018404Snate (s->st_mtimespec.tv_nsec != p->fts_statp->st_mtimespec.tv_nsec))) { 1911553Srgrimes LABEL; 1921553Srgrimes (void)printf("%smodification time (%.24s, ", 19318404Snate tab, ctime(&s->st_mtimespec.tv_sec)); 1941553Srgrimes (void)printf("%.24s)\n", 19518404Snate ctime(&p->fts_statp->st_mtimespec.tv_sec)); 1961553Srgrimes tab = "\t"; 1971553Srgrimes } 19851705Sbillf if (s->flags & F_CKSUM) { 1991553Srgrimes if ((fd = open(p->fts_accpath, O_RDONLY, 0)) < 0) { 2001553Srgrimes LABEL; 2011553Srgrimes (void)printf("%scksum: %s: %s\n", 2021553Srgrimes tab, p->fts_accpath, strerror(errno)); 2031553Srgrimes tab = "\t"; 2041553Srgrimes } else if (crc(fd, &val, &len)) { 2051553Srgrimes (void)close(fd); 2061553Srgrimes LABEL; 2071553Srgrimes (void)printf("%scksum: %s: %s\n", 2081553Srgrimes tab, p->fts_accpath, strerror(errno)); 2091553Srgrimes tab = "\t"; 2101553Srgrimes } else { 2111553Srgrimes (void)close(fd); 2121553Srgrimes if (s->cksum != val) { 2131553Srgrimes LABEL; 2148857Srgrimes (void)printf("%scksum (%lu, %lu)\n", 2151553Srgrimes tab, s->cksum, val); 2161553Srgrimes } 2171553Srgrimes tab = "\t"; 2181553Srgrimes } 21951705Sbillf } 22054375Sjoe /* 22154375Sjoe * XXX 22254375Sjoe * since chflags(2) will reset file times, the utimes() above 22354375Sjoe * may have been useless! oh well, we'd rather have correct 22454375Sjoe * flags, rather than times? 22554375Sjoe */ 22654375Sjoe if ((s->flags & F_FLAGS) && s->st_flags != p->fts_statp->st_flags) { 22754375Sjoe LABEL; 22861749Sjoe fflags = flags_to_string(s->st_flags); 22961749Sjoe (void)printf("%sflags (\"%s\" is not ", tab, fflags); 23061749Sjoe free(fflags); 23161749Sjoe 23261749Sjoe fflags = flags_to_string(p->fts_statp->st_flags); 23361749Sjoe (void)printf("\"%s\"", fflags); 23461749Sjoe free(fflags); 23561749Sjoe 23654375Sjoe if (uflag) 23754375Sjoe if (chflags(p->fts_accpath, s->st_flags)) 23854375Sjoe (void)printf(", not modified: %s)\n", 23954375Sjoe strerror(errno)); 24054375Sjoe else 24154375Sjoe (void)printf(", modified)\n"); 24254375Sjoe else 24354375Sjoe (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; 2536286Swollman printf("%sMD5File: %s: %s\n", tab, p->fts_accpath, 2546286Swollman strerror(errno)); 2556286Swollman tab = "\t"; 2566286Swollman } else if (strcmp(new_digest, s->md5digest)) { 2576286Swollman LABEL; 2588857Srgrimes printf("%sMD5 (%s, %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; 27144303Swollman printf("%sSHA1_File: %s: %s\n", tab, p->fts_accpath, 27244303Swollman strerror(errno)); 27344303Swollman tab = "\t"; 27444303Swollman } else if (strcmp(new_digest, s->sha1digest)) { 27544303Swollman LABEL; 27644303Swollman printf("%sSHA-1 (%s, %s)\n", tab, s->sha1digest, 27744303Swollman 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; 28944303Swollman printf("%sRIPEMD160_File: %s: %s\n", tab, 29044303Swollman p->fts_accpath, strerror(errno)); 29144303Swollman tab = "\t"; 29244303Swollman } else if (strcmp(new_digest, s->rmd160digest)) { 29344303Swollman LABEL; 29444303Swollman printf("%sRIPEMD160 (%s, %s)\n", tab, s->rmd160digest, 29544303Swollman new_digest); 29644303Swollman tab = "\t"; 29744303Swollman } 29844303Swollman } 29944303Swollman#endif /* RMD160 */ 30044303Swollman 30165812Ssheldonh if (s->flags & F_SLINK && 30265812Ssheldonh strcmp(cp = rlink(p->fts_accpath), s->slink)) { 3031553Srgrimes LABEL; 3041553Srgrimes (void)printf("%slink ref (%s, %s)\n", tab, cp, s->slink); 3051553Srgrimes } 3061553Srgrimes return (label); 3071553Srgrimes} 3081553Srgrimes 3091553Srgrimeschar * 3101553Srgrimesinotype(type) 3111553Srgrimes u_int type; 3121553Srgrimes{ 3131553Srgrimes switch(type & S_IFMT) { 3141553Srgrimes case S_IFBLK: 3151553Srgrimes return ("block"); 3161553Srgrimes case S_IFCHR: 3171553Srgrimes return ("char"); 3181553Srgrimes case S_IFDIR: 3191553Srgrimes return ("dir"); 3201553Srgrimes case S_IFIFO: 3211553Srgrimes return ("fifo"); 3221553Srgrimes case S_IFREG: 3231553Srgrimes return ("file"); 3241553Srgrimes case S_IFLNK: 3251553Srgrimes return ("link"); 3261553Srgrimes case S_IFSOCK: 3271553Srgrimes return ("socket"); 3281553Srgrimes default: 3291553Srgrimes return ("unknown"); 3301553Srgrimes } 3311553Srgrimes /* NOTREACHED */ 3321553Srgrimes} 3331553Srgrimes 3341553Srgrimesstatic char * 3351553Srgrimesftype(type) 3361553Srgrimes u_int type; 3371553Srgrimes{ 3381553Srgrimes switch(type) { 3391553Srgrimes case F_BLOCK: 3401553Srgrimes return ("block"); 3411553Srgrimes case F_CHAR: 3421553Srgrimes return ("char"); 3431553Srgrimes case F_DIR: 3441553Srgrimes return ("dir"); 3451553Srgrimes case F_FIFO: 3461553Srgrimes return ("fifo"); 3471553Srgrimes case F_FILE: 3481553Srgrimes return ("file"); 3491553Srgrimes case F_LINK: 3501553Srgrimes return ("link"); 3511553Srgrimes case F_SOCK: 3521553Srgrimes return ("socket"); 3531553Srgrimes default: 3541553Srgrimes return ("unknown"); 3551553Srgrimes } 3561553Srgrimes /* NOTREACHED */ 3571553Srgrimes} 3581553Srgrimes 3591553Srgrimeschar * 3601553Srgrimesrlink(name) 3611553Srgrimes char *name; 3621553Srgrimes{ 3631553Srgrimes static char lbuf[MAXPATHLEN]; 3641553Srgrimes register int len; 3651553Srgrimes 36636796Simp if ((len = readlink(name, lbuf, sizeof(lbuf) - 1)) == -1) 36730027Scharnier err(1, "line %d: %s", lineno, name); 3681553Srgrimes lbuf[len] = '\0'; 3691553Srgrimes return (lbuf); 3701553Srgrimes} 371