1258655Sbrooks/* $NetBSD: compare.c,v 1.58 2013/11/21 18:39:50 christos Exp $ */ 2244541Sbrooks 3244541Sbrooks/*- 4244541Sbrooks * Copyright (c) 1989, 1993 5244541Sbrooks * The Regents of the University of California. All rights reserved. 6244541Sbrooks * 7244541Sbrooks * Redistribution and use in source and binary forms, with or without 8244541Sbrooks * modification, are permitted provided that the following conditions 9244541Sbrooks * are met: 10244541Sbrooks * 1. Redistributions of source code must retain the above copyright 11244541Sbrooks * notice, this list of conditions and the following disclaimer. 12244541Sbrooks * 2. Redistributions in binary form must reproduce the above copyright 13244541Sbrooks * notice, this list of conditions and the following disclaimer in the 14244541Sbrooks * documentation and/or other materials provided with the distribution. 15244541Sbrooks * 3. Neither the name of the University nor the names of its contributors 16244541Sbrooks * may be used to endorse or promote products derived from this software 17244541Sbrooks * without specific prior written permission. 18244541Sbrooks * 19244541Sbrooks * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20244541Sbrooks * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21244541Sbrooks * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22244541Sbrooks * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23244541Sbrooks * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24244541Sbrooks * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25244541Sbrooks * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26244541Sbrooks * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27244541Sbrooks * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28244541Sbrooks * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29244541Sbrooks * SUCH DAMAGE. 30244541Sbrooks */ 31244541Sbrooks 32244541Sbrooks#if HAVE_NBTOOL_CONFIG_H 33244541Sbrooks#include "nbtool_config.h" 34244541Sbrooks#endif 35244541Sbrooks 36244541Sbrooks#include <sys/cdefs.h> 37244541Sbrooks#if defined(__RCSID) && !defined(lint) 38244541Sbrooks#if 0 39244541Sbrooksstatic char sccsid[] = "@(#)compare.c 8.1 (Berkeley) 6/6/93"; 40244541Sbrooks#else 41258655Sbrooks__RCSID("$NetBSD: compare.c,v 1.58 2013/11/21 18:39:50 christos Exp $"); 42244541Sbrooks#endif 43244541Sbrooks#endif /* not lint */ 44244541Sbrooks 45244541Sbrooks#include <sys/param.h> 46244541Sbrooks#include <sys/stat.h> 47244541Sbrooks 48244541Sbrooks#include <errno.h> 49244541Sbrooks#include <fcntl.h> 50258655Sbrooks#include <stdio.h> 51256996Sbrooks#include <stdint.h> 52244541Sbrooks#include <stdlib.h> 53244541Sbrooks#include <string.h> 54244541Sbrooks#include <time.h> 55244541Sbrooks#include <unistd.h> 56244541Sbrooks 57244541Sbrooks#ifndef NO_MD5 58244541Sbrooks#include <md5.h> 59244541Sbrooks#endif 60244541Sbrooks#ifndef NO_RMD160 61244541Sbrooks#include <rmd160.h> 62244541Sbrooks#endif 63244541Sbrooks#ifndef NO_SHA1 64244541Sbrooks#include <sha1.h> 65244541Sbrooks#endif 66244541Sbrooks#ifndef NO_SHA2 67244541Sbrooks#include <sha2.h> 68244541Sbrooks#endif 69244541Sbrooks 70244541Sbrooks#include "extern.h" 71244541Sbrooks 72244541Sbrooks#define INDENTNAMELEN 8 73244541Sbrooks#define MARK \ 74244541Sbrooksdo { \ 75258655Sbrooks if (flavor == F_FREEBSD9) { \ 76258655Sbrooks len = printf("%s changed\n", RP(p)); \ 77244541Sbrooks tab = "\t"; \ 78244541Sbrooks } else { \ 79258655Sbrooks len = printf("%s: ", RP(p)); \ 80258655Sbrooks if (len > INDENTNAMELEN) { \ 81258655Sbrooks tab = "\t"; \ 82258655Sbrooks printf("\n"); \ 83258655Sbrooks } else { \ 84258655Sbrooks tab = ""; \ 85258655Sbrooks printf("%*s", INDENTNAMELEN - (int)len, ""); \ 86258655Sbrooks } \ 87244541Sbrooks } \ 88244541Sbrooks} while (0) 89244541Sbrooks#define LABEL if (!label++) MARK 90244541Sbrooks 91244541Sbrooks#if HAVE_STRUCT_STAT_ST_FLAGS 92244541Sbrooks 93244541Sbrooks 94244541Sbrooks#define CHANGEFLAGS \ 95244541Sbrooks if (flags != p->fts_statp->st_flags) { \ 96244541Sbrooks char *sf; \ 97244541Sbrooks if (!label) { \ 98244541Sbrooks MARK; \ 99244541Sbrooks sf = flags_to_string(p->fts_statp->st_flags, "none"); \ 100244541Sbrooks printf("%sflags (\"%s\"", tab, sf); \ 101244541Sbrooks free(sf); \ 102244541Sbrooks } \ 103244541Sbrooks if (lchflags(p->fts_accpath, flags)) { \ 104244541Sbrooks label++; \ 105244541Sbrooks printf(", not modified: %s)\n", \ 106244541Sbrooks strerror(errno)); \ 107244541Sbrooks } else { \ 108244541Sbrooks sf = flags_to_string(flags, "none"); \ 109244541Sbrooks printf(", modified to \"%s\")\n", sf); \ 110244541Sbrooks free(sf); \ 111244541Sbrooks } \ 112244541Sbrooks } 113244541Sbrooks 114244541Sbrooks/* SETFLAGS: 115244541Sbrooks * given pflags, additionally set those flags specified in s->st_flags and 116244541Sbrooks * selected by mask (the other flags are left unchanged). 117244541Sbrooks */ 118244541Sbrooks#define SETFLAGS(pflags, mask) \ 119244541Sbrooksdo { \ 120244541Sbrooks flags = (s->st_flags & (mask)) | (pflags); \ 121244541Sbrooks CHANGEFLAGS; \ 122244541Sbrooks} while (0) 123244541Sbrooks 124244541Sbrooks/* CLEARFLAGS: 125244541Sbrooks * given pflags, reset the flags specified in s->st_flags and selected by mask 126244541Sbrooks * (the other flags are left unchanged). 127244541Sbrooks */ 128244541Sbrooks#define CLEARFLAGS(pflags, mask) \ 129244541Sbrooksdo { \ 130244541Sbrooks flags = (~(s->st_flags & (mask)) & CH_MASK) & (pflags); \ 131244541Sbrooks CHANGEFLAGS; \ 132244541Sbrooks} while (0) 133244541Sbrooks#endif /* HAVE_STRUCT_STAT_ST_FLAGS */ 134244541Sbrooks 135244541Sbrooksint 136244541Sbrookscompare(NODE *s, FTSENT *p) 137244541Sbrooks{ 138244541Sbrooks u_int32_t len, val, flags; 139244541Sbrooks int fd, label; 140244541Sbrooks const char *cp, *tab; 141244541Sbrooks#if !defined(NO_MD5) || !defined(NO_RMD160) || !defined(NO_SHA1) || !defined(NO_SHA2) 142244541Sbrooks char *digestbuf; 143244541Sbrooks#endif 144244541Sbrooks 145244541Sbrooks tab = NULL; 146244541Sbrooks label = 0; 147244541Sbrooks switch(s->type) { 148244541Sbrooks case F_BLOCK: 149244541Sbrooks if (!S_ISBLK(p->fts_statp->st_mode)) 150244541Sbrooks goto typeerr; 151244541Sbrooks break; 152244541Sbrooks case F_CHAR: 153244541Sbrooks if (!S_ISCHR(p->fts_statp->st_mode)) 154244541Sbrooks goto typeerr; 155244541Sbrooks break; 156244541Sbrooks case F_DIR: 157244541Sbrooks if (!S_ISDIR(p->fts_statp->st_mode)) 158244541Sbrooks goto typeerr; 159244541Sbrooks break; 160244541Sbrooks case F_FIFO: 161244541Sbrooks if (!S_ISFIFO(p->fts_statp->st_mode)) 162244541Sbrooks goto typeerr; 163244541Sbrooks break; 164244541Sbrooks case F_FILE: 165244541Sbrooks if (!S_ISREG(p->fts_statp->st_mode)) 166244541Sbrooks goto typeerr; 167244541Sbrooks break; 168244541Sbrooks case F_LINK: 169244541Sbrooks if (!S_ISLNK(p->fts_statp->st_mode)) 170244541Sbrooks goto typeerr; 171244541Sbrooks break; 172244541Sbrooks#ifdef S_ISSOCK 173244541Sbrooks case F_SOCK: 174244541Sbrooks if (!S_ISSOCK(p->fts_statp->st_mode)) 175244541Sbrooks goto typeerr; 176244541Sbrooks break; 177244541Sbrooks#endif 178244541Sbrookstypeerr: LABEL; 179258655Sbrooks printf(flavor == F_FREEBSD9 ? 180258655Sbrooks "\ttype expected %s found %s\n" : "\ttype (%s, %s)\n", 181244541Sbrooks nodetype(s->type), inotype(p->fts_statp->st_mode)); 182244541Sbrooks return (label); 183244541Sbrooks } 184244541Sbrooks if (mtree_Wflag) 185244541Sbrooks goto afterpermwhack; 186244541Sbrooks#if HAVE_STRUCT_STAT_ST_FLAGS 187244541Sbrooks if (iflag && !uflag) { 188244541Sbrooks if (s->flags & F_FLAGS) 189244541Sbrooks SETFLAGS(p->fts_statp->st_flags, SP_FLGS); 190244541Sbrooks return (label); 191244541Sbrooks } 192244541Sbrooks if (mflag && !uflag) { 193244541Sbrooks if (s->flags & F_FLAGS) 194244541Sbrooks CLEARFLAGS(p->fts_statp->st_flags, SP_FLGS); 195244541Sbrooks return (label); 196244541Sbrooks } 197244541Sbrooks#endif 198244541Sbrooks if (s->flags & F_DEV && 199244541Sbrooks (s->type == F_BLOCK || s->type == F_CHAR) && 200244541Sbrooks s->st_rdev != p->fts_statp->st_rdev) { 201244541Sbrooks LABEL; 202258655Sbrooks printf(flavor == F_FREEBSD9 ? 203258655Sbrooks "%sdevice expected %#jx found %#jx" : 204258655Sbrooks "%sdevice (%#jx, %#jx", 205256996Sbrooks tab, (uintmax_t)s->st_rdev, 206256996Sbrooks (uintmax_t)p->fts_statp->st_rdev); 207244541Sbrooks if (uflag) { 208244541Sbrooks if ((unlink(p->fts_accpath) == -1) || 209244541Sbrooks (mknod(p->fts_accpath, 210244541Sbrooks s->st_mode | nodetoino(s->type), 211244541Sbrooks s->st_rdev) == -1) || 212244541Sbrooks (lchown(p->fts_accpath, p->fts_statp->st_uid, 213244541Sbrooks p->fts_statp->st_gid) == -1) ) 214258655Sbrooks printf(", not modified: %s%s\n", 215258655Sbrooks strerror(errno), 216258655Sbrooks flavor == F_FREEBSD9 ? "" : ")"); 217244541Sbrooks else 218258655Sbrooks printf(", modified%s\n", 219258655Sbrooks flavor == F_FREEBSD9 ? "" : ")"); 220244541Sbrooks } else 221244541Sbrooks printf(")\n"); 222244541Sbrooks tab = "\t"; 223244541Sbrooks } 224244541Sbrooks /* Set the uid/gid first, then set the mode. */ 225244541Sbrooks if (s->flags & (F_UID | F_UNAME) && s->st_uid != p->fts_statp->st_uid) { 226244541Sbrooks LABEL; 227258655Sbrooks printf(flavor == F_FREEBSD9 ? 228258655Sbrooks "%suser expected %lu found %lu" : "%suser (%lu, %lu", 229244541Sbrooks tab, (u_long)s->st_uid, (u_long)p->fts_statp->st_uid); 230244541Sbrooks if (uflag) { 231244541Sbrooks if (lchown(p->fts_accpath, s->st_uid, -1)) 232258655Sbrooks printf(", not modified: %s%s\n", 233258655Sbrooks strerror(errno), 234258655Sbrooks flavor == F_FREEBSD9 ? "" : ")"); 235244541Sbrooks else 236258655Sbrooks printf(", modified%s\n", 237258655Sbrooks flavor == F_FREEBSD9 ? "" : ")"); 238244541Sbrooks } else 239244541Sbrooks printf(")\n"); 240244541Sbrooks tab = "\t"; 241244541Sbrooks } 242244541Sbrooks if (s->flags & (F_GID | F_GNAME) && s->st_gid != p->fts_statp->st_gid) { 243244541Sbrooks LABEL; 244258655Sbrooks printf(flavor == F_FREEBSD9 ? 245258655Sbrooks "%sgid expected %lu found %lu" : "%sgid (%lu, %lu", 246244541Sbrooks tab, (u_long)s->st_gid, (u_long)p->fts_statp->st_gid); 247244541Sbrooks if (uflag) { 248244541Sbrooks if (lchown(p->fts_accpath, -1, s->st_gid)) 249258655Sbrooks printf(", not modified: %s%s\n", 250258655Sbrooks strerror(errno), 251258655Sbrooks flavor == F_FREEBSD9 ? "" : ")"); 252244541Sbrooks else 253258655Sbrooks printf(", modified%s\n", 254258655Sbrooks flavor == F_FREEBSD9 ? "" : ")"); 255244541Sbrooks } 256244541Sbrooks else 257244541Sbrooks printf(")\n"); 258244541Sbrooks tab = "\t"; 259244541Sbrooks } 260244541Sbrooks if (s->flags & F_MODE && 261244541Sbrooks s->st_mode != (p->fts_statp->st_mode & MBITS)) { 262244541Sbrooks if (lflag) { 263244541Sbrooks mode_t tmode, mode; 264244541Sbrooks 265244541Sbrooks tmode = s->st_mode; 266244541Sbrooks mode = p->fts_statp->st_mode & MBITS; 267244541Sbrooks /* 268244541Sbrooks * if none of the suid/sgid/etc bits are set, 269244541Sbrooks * then if the mode is a subset of the target, 270244541Sbrooks * skip. 271244541Sbrooks */ 272244541Sbrooks if (!((tmode & ~(S_IRWXU|S_IRWXG|S_IRWXO)) || 273244541Sbrooks (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO)))) 274244541Sbrooks if ((mode | tmode) == tmode) 275244541Sbrooks goto skip; 276244541Sbrooks } 277244541Sbrooks 278244541Sbrooks LABEL; 279258655Sbrooks printf(flavor == F_FREEBSD9 ? 280258655Sbrooks "%spermissions expcted %#lo found %#lo" : 281258655Sbrooks "%spermissions (%#lo, %#lo", 282244541Sbrooks tab, (u_long)s->st_mode, 283244541Sbrooks (u_long)p->fts_statp->st_mode & MBITS); 284244541Sbrooks if (uflag) { 285244541Sbrooks if (lchmod(p->fts_accpath, s->st_mode)) 286258655Sbrooks printf(", not modified: %s%s\n", 287258655Sbrooks strerror(errno), 288258655Sbrooks flavor == F_FREEBSD9 ? "" : ")"); 289244541Sbrooks else 290258655Sbrooks printf(", modified%s\n", 291258655Sbrooks flavor == F_FREEBSD9 ? "" : ")"); 292244541Sbrooks } 293244541Sbrooks else 294244541Sbrooks printf(")\n"); 295244541Sbrooks tab = "\t"; 296244541Sbrooks skip: ; 297244541Sbrooks } 298244541Sbrooks if (s->flags & F_NLINK && s->type != F_DIR && 299244541Sbrooks s->st_nlink != p->fts_statp->st_nlink) { 300244541Sbrooks LABEL; 301258655Sbrooks printf(flavor == F_FREEBSD9 ? 302258655Sbrooks "%slink count expected %lu found %lu\n" : 303258655Sbrooks "%slink count (%lu, %lu)\n", 304244541Sbrooks tab, (u_long)s->st_nlink, (u_long)p->fts_statp->st_nlink); 305244541Sbrooks tab = "\t"; 306244541Sbrooks } 307244541Sbrooks if (s->flags & F_SIZE && s->st_size != p->fts_statp->st_size) { 308244541Sbrooks LABEL; 309258655Sbrooks printf(flavor == F_FREEBSD9 ? 310258655Sbrooks "%ssize expected %ju found %ju\n" : "%ssize (%ju, %ju)\n", 311256996Sbrooks tab, (uintmax_t)s->st_size, 312256996Sbrooks (uintmax_t)p->fts_statp->st_size); 313244541Sbrooks tab = "\t"; 314244541Sbrooks } 315244541Sbrooks /* 316244541Sbrooks * XXX 317244541Sbrooks * Since utimes(2) only takes a timeval, there's no point in 318244541Sbrooks * comparing the low bits of the timespec nanosecond field. This 319244541Sbrooks * will only result in mismatches that we can never fix. 320244541Sbrooks * 321244541Sbrooks * Doesn't display microsecond differences. 322244541Sbrooks */ 323244541Sbrooks if (s->flags & F_TIME) { 324244541Sbrooks struct timeval tv[2]; 325244541Sbrooks struct stat *ps = p->fts_statp; 326244541Sbrooks time_t smtime = s->st_mtimespec.tv_sec; 327244541Sbrooks 328244541Sbrooks#if defined(BSD4_4) && !defined(HAVE_NBTOOL_CONFIG_H) 329244541Sbrooks time_t pmtime = ps->st_mtimespec.tv_sec; 330244541Sbrooks 331244541Sbrooks TIMESPEC_TO_TIMEVAL(&tv[0], &s->st_mtimespec); 332244541Sbrooks TIMESPEC_TO_TIMEVAL(&tv[1], &ps->st_mtimespec); 333244541Sbrooks#else 334244541Sbrooks time_t pmtime = (time_t)ps->st_mtime; 335244541Sbrooks 336244541Sbrooks tv[0].tv_sec = smtime; 337244541Sbrooks tv[0].tv_usec = 0; 338244541Sbrooks tv[1].tv_sec = pmtime; 339244541Sbrooks tv[1].tv_usec = 0; 340244541Sbrooks#endif 341244541Sbrooks 342244541Sbrooks if (tv[0].tv_sec != tv[1].tv_sec || 343244541Sbrooks tv[0].tv_usec != tv[1].tv_usec) { 344244541Sbrooks LABEL; 345258655Sbrooks printf(flavor == F_FREEBSD9 ? 346258655Sbrooks "%smodification time expected %.24s found " : 347258655Sbrooks "%smodification time (%.24s, ", 348244541Sbrooks tab, ctime(&smtime)); 349244541Sbrooks printf("%.24s", ctime(&pmtime)); 350244541Sbrooks if (tflag) { 351244541Sbrooks tv[1] = tv[0]; 352244541Sbrooks if (utimes(p->fts_accpath, tv)) 353258655Sbrooks printf(", not modified: %s%s\n", 354258655Sbrooks strerror(errno), 355258655Sbrooks flavor == F_FREEBSD9 ? "" : ")"); 356244541Sbrooks else 357258655Sbrooks printf(", modified%s\n", 358258655Sbrooks flavor == F_FREEBSD9 ? "" : ")"); 359244541Sbrooks } else 360258655Sbrooks printf("%s\n", flavor == F_FREEBSD9 ? "" : ")"); 361244541Sbrooks tab = "\t"; 362244541Sbrooks } 363244541Sbrooks } 364244541Sbrooks#if HAVE_STRUCT_STAT_ST_FLAGS 365244541Sbrooks /* 366244541Sbrooks * XXX 367244541Sbrooks * since lchflags(2) will reset file times, the utimes() above 368244541Sbrooks * may have been useless! oh well, we'd rather have correct 369244541Sbrooks * flags, rather than times? 370244541Sbrooks */ 371244541Sbrooks if ((s->flags & F_FLAGS) && ((s->st_flags != p->fts_statp->st_flags) 372244541Sbrooks || mflag || iflag)) { 373244541Sbrooks if (s->st_flags != p->fts_statp->st_flags) { 374244541Sbrooks char *f_s; 375244541Sbrooks LABEL; 376244541Sbrooks f_s = flags_to_string(s->st_flags, "none"); 377258655Sbrooks printf(flavor == F_FREEBSD9 ? 378258655Sbrooks "%sflags expected \"%s\" found " : 379258655Sbrooks "%sflags (\"%s\" is not ", tab, f_s); 380244541Sbrooks free(f_s); 381244541Sbrooks f_s = flags_to_string(p->fts_statp->st_flags, "none"); 382244541Sbrooks printf("\"%s\"", f_s); 383244541Sbrooks free(f_s); 384244541Sbrooks } 385244541Sbrooks if (uflag) { 386244541Sbrooks if (iflag) 387244541Sbrooks SETFLAGS(0, CH_MASK); 388244541Sbrooks else if (mflag) 389244541Sbrooks CLEARFLAGS(0, SP_FLGS); 390244541Sbrooks else 391244541Sbrooks SETFLAGS(0, (~SP_FLGS & CH_MASK)); 392244541Sbrooks } else 393258655Sbrooks printf("%s\n", flavor == F_FREEBSD9 ? "" : ")"); 394244541Sbrooks tab = "\t"; 395244541Sbrooks } 396244541Sbrooks#endif /* HAVE_STRUCT_STAT_ST_FLAGS */ 397244541Sbrooks 398244541Sbrooks /* 399244541Sbrooks * from this point, no more permission checking or whacking 400244541Sbrooks * occurs, only checking of stuff like checksums and symlinks. 401244541Sbrooks */ 402244541Sbrooks afterpermwhack: 403244541Sbrooks if (s->flags & F_CKSUM) { 404244541Sbrooks if ((fd = open(p->fts_accpath, O_RDONLY, 0)) < 0) { 405244541Sbrooks LABEL; 406244541Sbrooks printf("%scksum: %s: %s\n", 407244541Sbrooks tab, p->fts_accpath, strerror(errno)); 408244541Sbrooks tab = "\t"; 409244541Sbrooks } else if (crc(fd, &val, &len)) { 410244541Sbrooks close(fd); 411244541Sbrooks LABEL; 412244541Sbrooks printf("%scksum: %s: %s\n", 413244541Sbrooks tab, p->fts_accpath, strerror(errno)); 414244541Sbrooks tab = "\t"; 415244541Sbrooks } else { 416244541Sbrooks close(fd); 417244541Sbrooks if (s->cksum != val) { 418244541Sbrooks LABEL; 419258655Sbrooks printf(flavor == F_FREEBSD9 ? 420258655Sbrooks "%scksum expected %lu found %lu\n" : 421258655Sbrooks "%scksum (%lu, %lu)\n", 422244541Sbrooks tab, s->cksum, (unsigned long)val); 423244541Sbrooks } 424244541Sbrooks tab = "\t"; 425244541Sbrooks } 426244541Sbrooks } 427244541Sbrooks#ifndef NO_MD5 428244541Sbrooks if (s->flags & F_MD5) { 429244541Sbrooks if ((digestbuf = MD5File(p->fts_accpath, NULL)) == NULL) { 430244541Sbrooks LABEL; 431244541Sbrooks printf("%s%s: %s: %s\n", 432244541Sbrooks tab, MD5KEY, p->fts_accpath, strerror(errno)); 433244541Sbrooks tab = "\t"; 434244541Sbrooks } else { 435244541Sbrooks if (strcmp(s->md5digest, digestbuf)) { 436244541Sbrooks LABEL; 437258655Sbrooks printf(flavor == F_FREEBSD9 ? 438258655Sbrooks "%s%s expected %s found %s\n" : 439258655Sbrooks "%s%s (0x%s, 0x%s)\n", 440244541Sbrooks tab, MD5KEY, s->md5digest, digestbuf); 441244541Sbrooks } 442244541Sbrooks tab = "\t"; 443244541Sbrooks free(digestbuf); 444244541Sbrooks } 445244541Sbrooks } 446244541Sbrooks#endif /* ! NO_MD5 */ 447244541Sbrooks#ifndef NO_RMD160 448244541Sbrooks if (s->flags & F_RMD160) { 449244541Sbrooks if ((digestbuf = RMD160File(p->fts_accpath, NULL)) == NULL) { 450244541Sbrooks LABEL; 451244541Sbrooks printf("%s%s: %s: %s\n", 452244541Sbrooks tab, RMD160KEY, p->fts_accpath, strerror(errno)); 453244541Sbrooks tab = "\t"; 454244541Sbrooks } else { 455244541Sbrooks if (strcmp(s->rmd160digest, digestbuf)) { 456244541Sbrooks LABEL; 457258655Sbrooks printf(flavor == F_FREEBSD9 ? 458258655Sbrooks "%s%s expected %s found %s\n" : 459258655Sbrooks "%s%s (0x%s, 0x%s)\n", 460244541Sbrooks tab, RMD160KEY, s->rmd160digest, digestbuf); 461244541Sbrooks } 462244541Sbrooks tab = "\t"; 463244541Sbrooks free(digestbuf); 464244541Sbrooks } 465244541Sbrooks } 466244541Sbrooks#endif /* ! NO_RMD160 */ 467244541Sbrooks#ifndef NO_SHA1 468244541Sbrooks if (s->flags & F_SHA1) { 469244541Sbrooks if ((digestbuf = SHA1File(p->fts_accpath, NULL)) == NULL) { 470244541Sbrooks LABEL; 471244541Sbrooks printf("%s%s: %s: %s\n", 472244541Sbrooks tab, SHA1KEY, p->fts_accpath, strerror(errno)); 473244541Sbrooks tab = "\t"; 474244541Sbrooks } else { 475244541Sbrooks if (strcmp(s->sha1digest, digestbuf)) { 476244541Sbrooks LABEL; 477258655Sbrooks printf(flavor == F_FREEBSD9 ? 478258655Sbrooks "%s%s expected %s found %s\n" : 479258655Sbrooks "%s%s (0x%s, 0x%s)\n", 480244541Sbrooks tab, SHA1KEY, s->sha1digest, digestbuf); 481244541Sbrooks } 482244541Sbrooks tab = "\t"; 483244541Sbrooks free(digestbuf); 484244541Sbrooks } 485244541Sbrooks } 486244541Sbrooks#endif /* ! NO_SHA1 */ 487244541Sbrooks#ifndef NO_SHA2 488244541Sbrooks if (s->flags & F_SHA256) { 489244541Sbrooks if ((digestbuf = SHA256_File(p->fts_accpath, NULL)) == NULL) { 490244541Sbrooks LABEL; 491244541Sbrooks printf("%s%s: %s: %s\n", 492244541Sbrooks tab, SHA256KEY, p->fts_accpath, strerror(errno)); 493244541Sbrooks tab = "\t"; 494244541Sbrooks } else { 495244541Sbrooks if (strcmp(s->sha256digest, digestbuf)) { 496244541Sbrooks LABEL; 497258655Sbrooks printf(flavor == F_FREEBSD9 ? 498258655Sbrooks "%s%s expected %s found %s\n" : 499258655Sbrooks "%s%s (0x%s, 0x%s)\n", 500244541Sbrooks tab, SHA256KEY, s->sha256digest, digestbuf); 501244541Sbrooks } 502244541Sbrooks tab = "\t"; 503244541Sbrooks free(digestbuf); 504244541Sbrooks } 505244541Sbrooks } 506244541Sbrooks#ifdef SHA384_BLOCK_LENGTH 507244541Sbrooks if (s->flags & F_SHA384) { 508244541Sbrooks if ((digestbuf = SHA384_File(p->fts_accpath, NULL)) == NULL) { 509244541Sbrooks LABEL; 510244541Sbrooks printf("%s%s: %s: %s\n", 511244541Sbrooks tab, SHA384KEY, p->fts_accpath, strerror(errno)); 512244541Sbrooks tab = "\t"; 513244541Sbrooks } else { 514244541Sbrooks if (strcmp(s->sha384digest, digestbuf)) { 515244541Sbrooks LABEL; 516258655Sbrooks printf(flavor == F_FREEBSD9 ? 517258655Sbrooks "%s%s expected %s found %s\n" : 518258655Sbrooks "%s%s (0x%s, 0x%s)\n", 519244541Sbrooks tab, SHA384KEY, s->sha384digest, digestbuf); 520244541Sbrooks } 521244541Sbrooks tab = "\t"; 522244541Sbrooks free(digestbuf); 523244541Sbrooks } 524244541Sbrooks } 525244541Sbrooks#endif 526244541Sbrooks if (s->flags & F_SHA512) { 527244541Sbrooks if ((digestbuf = SHA512_File(p->fts_accpath, NULL)) == NULL) { 528244541Sbrooks LABEL; 529244541Sbrooks printf("%s%s: %s: %s\n", 530244541Sbrooks tab, SHA512KEY, p->fts_accpath, strerror(errno)); 531244541Sbrooks tab = "\t"; 532244541Sbrooks } else { 533244541Sbrooks if (strcmp(s->sha512digest, digestbuf)) { 534244541Sbrooks LABEL; 535258655Sbrooks printf(flavor == F_FREEBSD9 ? 536258655Sbrooks "%s%s expected %s found %s\n" : 537258655Sbrooks "%s%s (0x%s, 0x%s)\n", 538244541Sbrooks tab, SHA512KEY, s->sha512digest, digestbuf); 539244541Sbrooks } 540244541Sbrooks tab = "\t"; 541244541Sbrooks free(digestbuf); 542244541Sbrooks } 543244541Sbrooks } 544244541Sbrooks#endif /* ! NO_SHA2 */ 545244541Sbrooks if (s->flags & F_SLINK && 546244541Sbrooks strcmp(cp = rlink(p->fts_accpath), s->slink)) { 547244541Sbrooks LABEL; 548258655Sbrooks printf(flavor == F_FREEBSD9 ? 549258655Sbrooks "%slink ref expected %s found %s" : 550258655Sbrooks "%slink ref (%s, %s", tab, cp, s->slink); 551244541Sbrooks if (uflag) { 552244541Sbrooks if ((unlink(p->fts_accpath) == -1) || 553244541Sbrooks (symlink(s->slink, p->fts_accpath) == -1) ) 554258655Sbrooks printf(", not modified: %s%s\n", 555258655Sbrooks strerror(errno), 556258655Sbrooks flavor == F_FREEBSD9 ? "" : ")"); 557244541Sbrooks else 558258655Sbrooks printf(", modified%s\n", 559258655Sbrooks flavor == F_FREEBSD9 ? "" : ")"); 560244541Sbrooks } else 561258655Sbrooks printf("%s\n", flavor == F_FREEBSD9 ? "" : ")"); 562244541Sbrooks } 563244541Sbrooks return (label); 564244541Sbrooks} 565244541Sbrooks 566244541Sbrooksconst char * 567244541Sbrooksrlink(const char *name) 568244541Sbrooks{ 569244541Sbrooks static char lbuf[MAXPATHLEN]; 570244541Sbrooks int len; 571244541Sbrooks 572244541Sbrooks if ((len = readlink(name, lbuf, sizeof(lbuf) - 1)) == -1) 573244541Sbrooks mtree_err("%s: %s", name, strerror(errno)); 574244541Sbrooks lbuf[len] = '\0'; 575244541Sbrooks return (lbuf); 576244541Sbrooks} 577