compare.c revision 259065
1253789Srpaulo/*	$NetBSD: compare.c,v 1.58 2013/11/21 18:39:50 christos Exp $	*/
2253789Srpaulo
3253789Srpaulo/*-
4253789Srpaulo * Copyright (c) 1989, 1993
5253789Srpaulo *	The Regents of the University of California.  All rights reserved.
6253789Srpaulo *
7253789Srpaulo * Redistribution and use in source and binary forms, with or without
8253789Srpaulo * modification, are permitted provided that the following conditions
9253789Srpaulo * are met:
10253789Srpaulo * 1. Redistributions of source code must retain the above copyright
11253789Srpaulo *    notice, this list of conditions and the following disclaimer.
12253789Srpaulo * 2. Redistributions in binary form must reproduce the above copyright
13253789Srpaulo *    notice, this list of conditions and the following disclaimer in the
14253789Srpaulo *    documentation and/or other materials provided with the distribution.
15253789Srpaulo * 3. Neither the name of the University nor the names of its contributors
16253789Srpaulo *    may be used to endorse or promote products derived from this software
17253789Srpaulo *    without specific prior written permission.
18253789Srpaulo *
19253789Srpaulo * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20253789Srpaulo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21253789Srpaulo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22253789Srpaulo * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23253789Srpaulo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24253789Srpaulo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25253789Srpaulo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26253789Srpaulo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27253789Srpaulo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28253789Srpaulo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29253789Srpaulo * SUCH DAMAGE.
30253789Srpaulo */
31253789Srpaulo
32253789Srpaulo#if HAVE_NBTOOL_CONFIG_H
33253789Srpaulo#include "nbtool_config.h"
34253789Srpaulo#endif
35253789Srpaulo
36253789Srpaulo#include <sys/cdefs.h>
37253789Srpaulo#if defined(__RCSID) && !defined(lint)
38253789Srpaulo#if 0
39253789Srpaulostatic char sccsid[] = "@(#)compare.c	8.1 (Berkeley) 6/6/93";
40253789Srpaulo#else
41253789Srpaulo__RCSID("$NetBSD: compare.c,v 1.58 2013/11/21 18:39:50 christos Exp $");
42253789Srpaulo#endif
43253789Srpaulo#endif /* not lint */
44253789Srpaulo
45253789Srpaulo#include <sys/param.h>
46253789Srpaulo#include <sys/stat.h>
47253789Srpaulo
48253789Srpaulo#include <errno.h>
49253789Srpaulo#include <fcntl.h>
50253789Srpaulo#include <stdio.h>
51253789Srpaulo#include <stdint.h>
52253789Srpaulo#include <stdlib.h>
53253789Srpaulo#include <string.h>
54253789Srpaulo#include <time.h>
55253789Srpaulo#include <unistd.h>
56253789Srpaulo
57253789Srpaulo#ifndef NO_MD5
58253789Srpaulo#include <md5.h>
59253789Srpaulo#endif
60253789Srpaulo#ifndef NO_RMD160
61253789Srpaulo#include <rmd160.h>
62253789Srpaulo#endif
63253789Srpaulo#ifndef NO_SHA1
64253789Srpaulo#include <sha1.h>
65253789Srpaulo#endif
66253789Srpaulo#ifndef NO_SHA2
67253789Srpaulo#include <sha2.h>
68253789Srpaulo#endif
69253789Srpaulo
70253789Srpaulo#include "extern.h"
71253789Srpaulo
72253789Srpaulo#define	INDENTNAMELEN	8
73253789Srpaulo#define MARK								\
74253789Srpaulodo {									\
75253789Srpaulo	if (flavor == F_FREEBSD9) {					\
76253789Srpaulo		len = printf("%s changed\n", RP(p));			\
77253789Srpaulo		tab = "\t";						\
78253789Srpaulo	} else {							\
79253789Srpaulo		len = printf("%s: ", RP(p));				\
80253789Srpaulo		if (len > INDENTNAMELEN) {				\
81253789Srpaulo			tab = "\t";					\
82253789Srpaulo			printf("\n");					\
83253789Srpaulo		} else {						\
84253789Srpaulo			tab = "";					\
85253789Srpaulo			printf("%*s", INDENTNAMELEN - (int)len, "");	\
86253789Srpaulo		}							\
87253789Srpaulo	}								\
88253789Srpaulo} while (0)
89253789Srpaulo#define	LABEL if (!label++) MARK
90253789Srpaulo
91253789Srpaulo#if HAVE_STRUCT_STAT_ST_FLAGS
92253789Srpaulo
93253789Srpaulo
94253789Srpaulo#define CHANGEFLAGS							\
95253789Srpaulo	if (flags != p->fts_statp->st_flags) {				\
96253789Srpaulo		char *sf;						\
97253789Srpaulo		if (!label) {						\
98253789Srpaulo			MARK;						\
99253789Srpaulo			sf = flags_to_string(p->fts_statp->st_flags, "none"); \
100253789Srpaulo			printf("%sflags (\"%s\"", tab, sf);		\
101273898Shselasky			free(sf);					\
102253789Srpaulo		}							\
103253789Srpaulo		if (lchflags(p->fts_accpath, flags)) {			\
104253789Srpaulo			label++;					\
105253789Srpaulo			printf(", not modified: %s)\n",			\
106253789Srpaulo			    strerror(errno));				\
107253789Srpaulo		} else {						\
108253789Srpaulo			sf = flags_to_string(flags, "none");		\
109253789Srpaulo			printf(", modified to \"%s\")\n", sf);		\
110253789Srpaulo			free(sf);					\
111253789Srpaulo		}							\
112253789Srpaulo	}
113253789Srpaulo
114253789Srpaulo/* SETFLAGS:
115253789Srpaulo * given pflags, additionally set those flags specified in s->st_flags and
116253789Srpaulo * selected by mask (the other flags are left unchanged).
117253789Srpaulo */
118253789Srpaulo#define SETFLAGS(pflags, mask)						\
119253789Srpaulodo {									\
120253789Srpaulo	flags = (s->st_flags & (mask)) | (pflags);			\
121253789Srpaulo	CHANGEFLAGS;							\
122253789Srpaulo} while (0)
123253789Srpaulo
124253789Srpaulo/* CLEARFLAGS:
125253789Srpaulo * given pflags, reset the flags specified in s->st_flags and selected by mask
126267349Shselasky * (the other flags are left unchanged).
127267349Shselasky */
128253789Srpaulo#define CLEARFLAGS(pflags, mask)					\
129253789Srpaulodo {									\
130253789Srpaulo	flags = (~(s->st_flags & (mask)) & CH_MASK) & (pflags);		\
131253789Srpaulo	CHANGEFLAGS;							\
132253789Srpaulo} while (0)
133253789Srpaulo#endif	/* HAVE_STRUCT_STAT_ST_FLAGS */
134253789Srpaulo
135253789Srpauloint
136253789Srpaulocompare(NODE *s, FTSENT *p)
137253789Srpaulo{
138253789Srpaulo	u_int32_t len, val, flags;
139253789Srpaulo	int fd, label;
140253789Srpaulo	const char *cp, *tab;
141253789Srpaulo#if !defined(NO_MD5) || !defined(NO_RMD160) || !defined(NO_SHA1) || !defined(NO_SHA2)
142253789Srpaulo	char *digestbuf;
143253789Srpaulo#endif
144253789Srpaulo
145253789Srpaulo	tab = NULL;
146253789Srpaulo	label = 0;
147253789Srpaulo	switch(s->type) {
148253789Srpaulo	case F_BLOCK:
149253789Srpaulo		if (!S_ISBLK(p->fts_statp->st_mode))
150253789Srpaulo			goto typeerr;
151253789Srpaulo		break;
152253789Srpaulo	case F_CHAR:
153253789Srpaulo		if (!S_ISCHR(p->fts_statp->st_mode))
154253789Srpaulo			goto typeerr;
155253789Srpaulo		break;
156253789Srpaulo	case F_DIR:
157253789Srpaulo		if (!S_ISDIR(p->fts_statp->st_mode))
158253789Srpaulo			goto typeerr;
159253789Srpaulo		break;
160253789Srpaulo	case F_FIFO:
161253789Srpaulo		if (!S_ISFIFO(p->fts_statp->st_mode))
162253789Srpaulo			goto typeerr;
163253789Srpaulo		break;
164253789Srpaulo	case F_FILE:
165253789Srpaulo		if (!S_ISREG(p->fts_statp->st_mode))
166253789Srpaulo			goto typeerr;
167253789Srpaulo		break;
168253789Srpaulo	case F_LINK:
169253789Srpaulo		if (!S_ISLNK(p->fts_statp->st_mode))
170253789Srpaulo			goto typeerr;
171253789Srpaulo		break;
172253789Srpaulo#ifdef S_ISSOCK
173253789Srpaulo	case F_SOCK:
174253789Srpaulo		if (!S_ISSOCK(p->fts_statp->st_mode))
175253789Srpaulo			goto typeerr;
176253789Srpaulo		break;
177253789Srpaulo#endif
178253789Srpaulotypeerr:		LABEL;
179253789Srpaulo		printf(flavor == F_FREEBSD9 ?
180253789Srpaulo		    "\ttype expected %s found %s\n" : "\ttype (%s, %s)\n",
181253789Srpaulo		    nodetype(s->type), inotype(p->fts_statp->st_mode));
182253789Srpaulo		return (label);
183253789Srpaulo	}
184253789Srpaulo	if (mtree_Wflag)
185253789Srpaulo		goto afterpermwhack;
186253789Srpaulo#if HAVE_STRUCT_STAT_ST_FLAGS
187253789Srpaulo	if (iflag && !uflag) {
188253789Srpaulo		if (s->flags & F_FLAGS)
189253789Srpaulo		    SETFLAGS(p->fts_statp->st_flags, SP_FLGS);
190253789Srpaulo		return (label);
191253789Srpaulo        }
192253789Srpaulo	if (mflag && !uflag) {
193266577Shselasky		if (s->flags & F_FLAGS)
194253789Srpaulo		    CLEARFLAGS(p->fts_statp->st_flags, SP_FLGS);
195253789Srpaulo		return (label);
196253789Srpaulo        }
197253789Srpaulo#endif
198253789Srpaulo	if (s->flags & F_DEV &&
199253789Srpaulo	    (s->type == F_BLOCK || s->type == F_CHAR) &&
200253789Srpaulo	    s->st_rdev != p->fts_statp->st_rdev) {
201253789Srpaulo		LABEL;
202253789Srpaulo		printf(flavor == F_FREEBSD9 ?
203253789Srpaulo		    "%sdevice expected %#jx found %#jx" :
204253789Srpaulo		    "%sdevice (%#jx, %#jx",
205253789Srpaulo		    tab, (uintmax_t)s->st_rdev,
206253789Srpaulo		    (uintmax_t)p->fts_statp->st_rdev);
207253789Srpaulo		if (uflag) {
208253789Srpaulo			if ((unlink(p->fts_accpath) == -1) ||
209253789Srpaulo			    (mknod(p->fts_accpath,
210253789Srpaulo			      s->st_mode | nodetoino(s->type),
211253789Srpaulo			      s->st_rdev) == -1) ||
212253789Srpaulo			    (lchown(p->fts_accpath, p->fts_statp->st_uid,
213253789Srpaulo			      p->fts_statp->st_gid) == -1) )
214253789Srpaulo				printf(", not modified: %s%s\n",
215253789Srpaulo				    strerror(errno),
216253789Srpaulo				    flavor == F_FREEBSD9 ? "" : ")");
217267349Shselasky			 else
218267349Shselasky				printf(", modified%s\n",
219267349Shselasky				    flavor == F_FREEBSD9 ? "" : ")");
220267349Shselasky		} else
221267349Shselasky			printf(")\n");
222267349Shselasky		tab = "\t";
223267349Shselasky	}
224253789Srpaulo	/* Set the uid/gid first, then set the mode. */
225253789Srpaulo	if (s->flags & (F_UID | F_UNAME) && s->st_uid != p->fts_statp->st_uid) {
226253789Srpaulo		LABEL;
227253789Srpaulo		printf(flavor == F_FREEBSD9 ?
228253789Srpaulo		    "%suser expected %lu found %lu" : "%suser (%lu, %lu",
229253789Srpaulo		    tab, (u_long)s->st_uid, (u_long)p->fts_statp->st_uid);
230253789Srpaulo		if (uflag) {
231253789Srpaulo			if (lchown(p->fts_accpath, s->st_uid, -1))
232253789Srpaulo				printf(", not modified: %s%s\n",
233253789Srpaulo				    strerror(errno),
234253789Srpaulo				    flavor == F_FREEBSD9 ? "" : ")");
235253789Srpaulo			else
236267349Shselasky				printf(", modified%s\n",
237253789Srpaulo				    flavor == F_FREEBSD9 ? "" : ")");
238253789Srpaulo		} else
239253789Srpaulo			printf(")\n");
240253789Srpaulo		tab = "\t";
241253789Srpaulo	}
242253789Srpaulo	if (s->flags & (F_GID | F_GNAME) && s->st_gid != p->fts_statp->st_gid) {
243253789Srpaulo		LABEL;
244253789Srpaulo		printf(flavor == F_FREEBSD9 ?
245253789Srpaulo		    "%sgid expected %lu found %lu" : "%sgid (%lu, %lu",
246267349Shselasky		    tab, (u_long)s->st_gid, (u_long)p->fts_statp->st_gid);
247253789Srpaulo		if (uflag) {
248253789Srpaulo			if (lchown(p->fts_accpath, -1, s->st_gid))
249267349Shselasky				printf(", not modified: %s%s\n",
250253789Srpaulo				    strerror(errno),
251253789Srpaulo				    flavor == F_FREEBSD9 ? "" : ")");
252253789Srpaulo			else
253253789Srpaulo				printf(", modified%s\n",
254253789Srpaulo				    flavor == F_FREEBSD9 ? "" : ")");
255253789Srpaulo		}
256253789Srpaulo		else
257253789Srpaulo			printf(")\n");
258253789Srpaulo		tab = "\t";
259267349Shselasky	}
260253789Srpaulo	if (s->flags & F_MODE &&
261253789Srpaulo	    s->st_mode != (p->fts_statp->st_mode & MBITS)) {
262253789Srpaulo		if (lflag) {
263253789Srpaulo			mode_t tmode, mode;
264253789Srpaulo
265253789Srpaulo			tmode = s->st_mode;
266253789Srpaulo			mode = p->fts_statp->st_mode & MBITS;
267253789Srpaulo			/*
268253789Srpaulo			 * if none of the suid/sgid/etc bits are set,
269253789Srpaulo			 * then if the mode is a subset of the target,
270253789Srpaulo			 * skip.
271253789Srpaulo			 */
272253789Srpaulo			if (!((tmode & ~(S_IRWXU|S_IRWXG|S_IRWXO)) ||
273253789Srpaulo			    (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO))))
274253789Srpaulo				if ((mode | tmode) == tmode)
275253789Srpaulo					goto skip;
276253789Srpaulo		}
277253789Srpaulo
278253789Srpaulo		LABEL;
279253789Srpaulo		printf(flavor == F_FREEBSD9 ?
280253789Srpaulo		    "%spermissions expcted %#lo found %#lo" :
281253789Srpaulo		    "%spermissions (%#lo, %#lo",
282253789Srpaulo		    tab, (u_long)s->st_mode,
283253789Srpaulo		    (u_long)p->fts_statp->st_mode & MBITS);
284253789Srpaulo		if (uflag) {
285253789Srpaulo			if (lchmod(p->fts_accpath, s->st_mode))
286253789Srpaulo				printf(", not modified: %s%s\n",
287253789Srpaulo				    strerror(errno),
288253789Srpaulo				    flavor == F_FREEBSD9 ? "" : ")");
289253789Srpaulo			else
290253789Srpaulo				printf(", modified%s\n",
291253789Srpaulo				    flavor == F_FREEBSD9 ? "" : ")");
292253789Srpaulo		}
293253789Srpaulo		else
294253789Srpaulo			printf(")\n");
295253789Srpaulo		tab = "\t";
296266577Shselasky	skip:	;
297266577Shselasky	}
298266577Shselasky	if (s->flags & F_NLINK && s->type != F_DIR &&
299266577Shselasky	    s->st_nlink != p->fts_statp->st_nlink) {
300266577Shselasky		LABEL;
301266577Shselasky		printf(flavor == F_FREEBSD9 ?
302266577Shselasky		    "%slink count expected %lu found %lu\n" :
303266577Shselasky		    "%slink count (%lu, %lu)\n",
304266577Shselasky		    tab, (u_long)s->st_nlink, (u_long)p->fts_statp->st_nlink);
305266577Shselasky		tab = "\t";
306266577Shselasky	}
307266577Shselasky	if (s->flags & F_SIZE && s->st_size != p->fts_statp->st_size) {
308266577Shselasky		LABEL;
309266577Shselasky		printf(flavor == F_FREEBSD9 ?
310253789Srpaulo		    "%ssize expected %ju found %ju\n" : "%ssize (%ju, %ju)\n",
311253789Srpaulo		    tab, (uintmax_t)s->st_size,
312253789Srpaulo		    (uintmax_t)p->fts_statp->st_size);
313253789Srpaulo		tab = "\t";
314253789Srpaulo	}
315253789Srpaulo	/*
316253789Srpaulo	 * XXX
317253831Srpaulo	 * Since utimes(2) only takes a timeval, there's no point in
318253789Srpaulo	 * comparing the low bits of the timespec nanosecond field.  This
319253789Srpaulo	 * will only result in mismatches that we can never fix.
320253789Srpaulo	 *
321253789Srpaulo	 * Doesn't display microsecond differences.
322253789Srpaulo	 */
323253789Srpaulo	if (s->flags & F_TIME) {
324253789Srpaulo		struct timeval tv[2];
325276975Shselasky		struct stat *ps = p->fts_statp;
326253789Srpaulo		time_t smtime = s->st_mtimespec.tv_sec;
327253789Srpaulo
328253831Srpaulo#if defined(BSD4_4) && !defined(HAVE_NBTOOL_CONFIG_H)
329253789Srpaulo		time_t pmtime = ps->st_mtimespec.tv_sec;
330253789Srpaulo
331253789Srpaulo		TIMESPEC_TO_TIMEVAL(&tv[0], &s->st_mtimespec);
332253789Srpaulo		TIMESPEC_TO_TIMEVAL(&tv[1], &ps->st_mtimespec);
333253789Srpaulo#else
334253789Srpaulo		time_t pmtime = (time_t)ps->st_mtime;
335253831Srpaulo
336253789Srpaulo		tv[0].tv_sec = smtime;
337253789Srpaulo		tv[0].tv_usec = 0;
338253789Srpaulo		tv[1].tv_sec = pmtime;
339253789Srpaulo		tv[1].tv_usec = 0;
340253789Srpaulo#endif
341253789Srpaulo
342253789Srpaulo		if (tv[0].tv_sec != tv[1].tv_sec ||
343253789Srpaulo		    tv[0].tv_usec != tv[1].tv_usec) {
344253789Srpaulo			LABEL;
345253789Srpaulo			printf(flavor == F_FREEBSD9 ?
346253789Srpaulo			    "%smodification time expected %.24s found " :
347253789Srpaulo			    "%smodification time (%.24s, ",
348253789Srpaulo			    tab, ctime(&smtime));
349253789Srpaulo			printf("%.24s", ctime(&pmtime));
350253789Srpaulo			if (tflag) {
351253789Srpaulo				tv[1] = tv[0];
352253789Srpaulo				if (utimes(p->fts_accpath, tv))
353253789Srpaulo					printf(", not modified: %s%s\n",
354253789Srpaulo					    strerror(errno),
355253789Srpaulo					    flavor == F_FREEBSD9 ? "" : ")");
356253789Srpaulo				else
357253789Srpaulo					printf(", modified%s\n",
358253789Srpaulo					    flavor == F_FREEBSD9 ? "" : ")");
359253789Srpaulo			} else
360253789Srpaulo				printf("%s\n", flavor == F_FREEBSD9 ? "" : ")");
361253789Srpaulo			tab = "\t";
362253789Srpaulo		}
363253789Srpaulo	}
364253789Srpaulo#if HAVE_STRUCT_STAT_ST_FLAGS
365253789Srpaulo	/*
366253789Srpaulo	 * XXX
367253789Srpaulo	 * since lchflags(2) will reset file times, the utimes() above
368253789Srpaulo	 * may have been useless!  oh well, we'd rather have correct
369253789Srpaulo	 * flags, rather than times?
370253789Srpaulo	 */
371253789Srpaulo        if ((s->flags & F_FLAGS) && ((s->st_flags != p->fts_statp->st_flags)
372253789Srpaulo	    || mflag || iflag)) {
373253789Srpaulo		if (s->st_flags != p->fts_statp->st_flags) {
374253789Srpaulo			char *f_s;
375253789Srpaulo			LABEL;
376253789Srpaulo			f_s = flags_to_string(s->st_flags, "none");
377253789Srpaulo			printf(flavor == F_FREEBSD9 ?
378253789Srpaulo			    "%sflags expected \"%s\" found " :
379253789Srpaulo			    "%sflags (\"%s\" is not ", tab, f_s);
380253789Srpaulo			free(f_s);
381253789Srpaulo			f_s = flags_to_string(p->fts_statp->st_flags, "none");
382253789Srpaulo			printf("\"%s\"", f_s);
383253789Srpaulo			free(f_s);
384253789Srpaulo		}
385253789Srpaulo		if (uflag) {
386253789Srpaulo			if (iflag)
387253789Srpaulo				SETFLAGS(0, CH_MASK);
388253789Srpaulo			else if (mflag)
389253789Srpaulo				CLEARFLAGS(0, SP_FLGS);
390253789Srpaulo			else
391253789Srpaulo				SETFLAGS(0, (~SP_FLGS & CH_MASK));
392253789Srpaulo		} else
393253789Srpaulo			printf("%s\n", flavor == F_FREEBSD9 ? "" : ")");
394253789Srpaulo		tab = "\t";
395253789Srpaulo	}
396253789Srpaulo#endif	/* HAVE_STRUCT_STAT_ST_FLAGS */
397253789Srpaulo
398253789Srpaulo	/*
399253789Srpaulo	 * from this point, no more permission checking or whacking
400253789Srpaulo	 * occurs, only checking of stuff like checksums and symlinks.
401253831Srpaulo	 */
402253831Srpaulo afterpermwhack:
403253831Srpaulo	if (s->flags & F_CKSUM) {
404253831Srpaulo		if ((fd = open(p->fts_accpath, O_RDONLY, 0)) < 0) {
405253831Srpaulo			LABEL;
406253789Srpaulo			printf("%scksum: %s: %s\n",
407253789Srpaulo			    tab, p->fts_accpath, strerror(errno));
408253789Srpaulo			tab = "\t";
409253789Srpaulo		} else if (crc(fd, &val, &len)) {
410253789Srpaulo			close(fd);
411253789Srpaulo			LABEL;
412253789Srpaulo			printf("%scksum: %s: %s\n",
413253789Srpaulo			    tab, p->fts_accpath, strerror(errno));
414253789Srpaulo			tab = "\t";
415253789Srpaulo		} else {
416253789Srpaulo			close(fd);
417253789Srpaulo			if (s->cksum != val) {
418253789Srpaulo				LABEL;
419253789Srpaulo				printf(flavor == F_FREEBSD9 ?
420253789Srpaulo				    "%scksum expected %lu found %lu\n" :
421253789Srpaulo				    "%scksum (%lu, %lu)\n",
422253789Srpaulo				    tab, s->cksum, (unsigned long)val);
423253789Srpaulo			}
424253789Srpaulo			tab = "\t";
425253789Srpaulo		}
426253789Srpaulo	}
427253789Srpaulo#ifndef NO_MD5
428253789Srpaulo	if (s->flags & F_MD5) {
429253789Srpaulo		if ((digestbuf = MD5File(p->fts_accpath, NULL)) == NULL) {
430253789Srpaulo			LABEL;
431253789Srpaulo			printf("%s%s: %s: %s\n",
432253789Srpaulo			    tab, MD5KEY, p->fts_accpath, strerror(errno));
433253789Srpaulo			tab = "\t";
434253789Srpaulo		} else {
435253789Srpaulo			if (strcmp(s->md5digest, digestbuf)) {
436253789Srpaulo				LABEL;
437253789Srpaulo				printf(flavor == F_FREEBSD9 ?
438253789Srpaulo				    "%s%s expected %s found %s\n" :
439253789Srpaulo				    "%s%s (0x%s, 0x%s)\n",
440253789Srpaulo				    tab, MD5KEY, s->md5digest, digestbuf);
441253789Srpaulo			}
442253789Srpaulo			tab = "\t";
443253789Srpaulo			free(digestbuf);
444266577Shselasky		}
445253789Srpaulo	}
446253789Srpaulo#endif	/* ! NO_MD5 */
447253789Srpaulo#ifndef NO_RMD160
448253789Srpaulo	if (s->flags & F_RMD160) {
449253789Srpaulo		if ((digestbuf = RMD160File(p->fts_accpath, NULL)) == NULL) {
450253789Srpaulo			LABEL;
451253789Srpaulo			printf("%s%s: %s: %s\n",
452253789Srpaulo			    tab, RMD160KEY, p->fts_accpath, strerror(errno));
453253789Srpaulo			tab = "\t";
454253789Srpaulo		} else {
455253789Srpaulo			if (strcmp(s->rmd160digest, digestbuf)) {
456253789Srpaulo				LABEL;
457253789Srpaulo				printf(flavor == F_FREEBSD9 ?
458253789Srpaulo				    "%s%s expected %s found %s\n" :
459253789Srpaulo				    "%s%s (0x%s, 0x%s)\n",
460253789Srpaulo				    tab, RMD160KEY, s->rmd160digest, digestbuf);
461253789Srpaulo			}
462253789Srpaulo			tab = "\t";
463253789Srpaulo			free(digestbuf);
464253789Srpaulo		}
465253789Srpaulo	}
466253789Srpaulo#endif	/* ! NO_RMD160 */
467253789Srpaulo#ifndef NO_SHA1
468253789Srpaulo	if (s->flags & F_SHA1) {
469253789Srpaulo		if ((digestbuf = SHA1File(p->fts_accpath, NULL)) == NULL) {
470253789Srpaulo			LABEL;
471253789Srpaulo			printf("%s%s: %s: %s\n",
472259453Shselasky			    tab, SHA1KEY, p->fts_accpath, strerror(errno));
473259453Shselasky			tab = "\t";
474259453Shselasky		} else {
475259453Shselasky			if (strcmp(s->sha1digest, digestbuf)) {
476259453Shselasky				LABEL;
477259453Shselasky				printf(flavor == F_FREEBSD9 ?
478259453Shselasky				    "%s%s expected %s found %s\n" :
479253789Srpaulo				    "%s%s (0x%s, 0x%s)\n",
480253789Srpaulo				    tab, SHA1KEY, s->sha1digest, digestbuf);
481253789Srpaulo			}
482253789Srpaulo			tab = "\t";
483253789Srpaulo			free(digestbuf);
484253789Srpaulo		}
485253789Srpaulo	}
486253789Srpaulo#endif	/* ! NO_SHA1 */
487253789Srpaulo#ifndef NO_SHA2
488253789Srpaulo	if (s->flags & F_SHA256) {
489253789Srpaulo		if ((digestbuf = SHA256_File(p->fts_accpath, NULL)) == NULL) {
490253789Srpaulo			LABEL;
491253789Srpaulo			printf("%s%s: %s: %s\n",
492253789Srpaulo			    tab, SHA256KEY, p->fts_accpath, strerror(errno));
493253789Srpaulo			tab = "\t";
494253789Srpaulo		} else {
495253789Srpaulo			if (strcmp(s->sha256digest, digestbuf)) {
496253789Srpaulo				LABEL;
497253789Srpaulo				printf(flavor == F_FREEBSD9 ?
498253789Srpaulo				    "%s%s expected %s found %s\n" :
499253789Srpaulo				    "%s%s (0x%s, 0x%s)\n",
500253789Srpaulo				    tab, SHA256KEY, s->sha256digest, digestbuf);
501253789Srpaulo			}
502253789Srpaulo			tab = "\t";
503253789Srpaulo			free(digestbuf);
504253789Srpaulo		}
505253789Srpaulo	}
506253789Srpaulo#ifdef SHA384_BLOCK_LENGTH
507253789Srpaulo	if (s->flags & F_SHA384) {
508253789Srpaulo		if ((digestbuf = SHA384_File(p->fts_accpath, NULL)) == NULL) {
509253789Srpaulo			LABEL;
510253789Srpaulo			printf("%s%s: %s: %s\n",
511253789Srpaulo			    tab, SHA384KEY, p->fts_accpath, strerror(errno));
512253789Srpaulo			tab = "\t";
513253789Srpaulo		} else {
514253789Srpaulo			if (strcmp(s->sha384digest, digestbuf)) {
515253789Srpaulo				LABEL;
516253789Srpaulo				printf(flavor == F_FREEBSD9 ?
517253789Srpaulo				    "%s%s expected %s found %s\n" :
518253789Srpaulo				    "%s%s (0x%s, 0x%s)\n",
519253789Srpaulo				    tab, SHA384KEY, s->sha384digest, digestbuf);
520253789Srpaulo			}
521253789Srpaulo			tab = "\t";
522253789Srpaulo			free(digestbuf);
523253789Srpaulo		}
524253789Srpaulo	}
525253789Srpaulo#endif
526253789Srpaulo	if (s->flags & F_SHA512) {
527253789Srpaulo		if ((digestbuf = SHA512_File(p->fts_accpath, NULL)) == NULL) {
528253789Srpaulo			LABEL;
529253789Srpaulo			printf("%s%s: %s: %s\n",
530253789Srpaulo			    tab, SHA512KEY, p->fts_accpath, strerror(errno));
531253789Srpaulo			tab = "\t";
532253789Srpaulo		} else {
533253789Srpaulo			if (strcmp(s->sha512digest, digestbuf)) {
534253789Srpaulo				LABEL;
535253789Srpaulo				printf(flavor == F_FREEBSD9 ?
536253789Srpaulo				    "%s%s expected %s found %s\n" :
537253789Srpaulo				    "%s%s (0x%s, 0x%s)\n",
538253789Srpaulo				    tab, SHA512KEY, s->sha512digest, digestbuf);
539253789Srpaulo			}
540253789Srpaulo			tab = "\t";
541253789Srpaulo			free(digestbuf);
542253789Srpaulo		}
543253789Srpaulo	}
544253789Srpaulo#endif	/* ! NO_SHA2 */
545253789Srpaulo	if (s->flags & F_SLINK &&
546253789Srpaulo	    strcmp(cp = rlink(p->fts_accpath), s->slink)) {
547253789Srpaulo		LABEL;
548253789Srpaulo		printf(flavor == F_FREEBSD9 ?
549253789Srpaulo		    "%slink ref expected %s found %s" :
550253789Srpaulo		    "%slink ref (%s, %s", tab, cp, s->slink);
551253789Srpaulo		if (uflag) {
552253789Srpaulo			if ((unlink(p->fts_accpath) == -1) ||
553253789Srpaulo			    (symlink(s->slink, p->fts_accpath) == -1) )
554253789Srpaulo				printf(", not modified: %s%s\n",
555253789Srpaulo				    strerror(errno),
556253789Srpaulo				    flavor == F_FREEBSD9 ? "" : ")");
557253789Srpaulo			else
558253789Srpaulo				printf(", modified%s\n",
559253789Srpaulo				    flavor == F_FREEBSD9 ? "" : ")");
560253789Srpaulo		} else
561253789Srpaulo			printf("%s\n", flavor == F_FREEBSD9 ? "" : ")");
562253789Srpaulo	}
563253789Srpaulo	return (label);
564253789Srpaulo}
565253789Srpaulo
566253789Srpauloconst char *
567253789Srpaulorlink(const char *name)
568253789Srpaulo{
569253789Srpaulo	static char lbuf[MAXPATHLEN];
570253789Srpaulo	int len;
571253789Srpaulo
572253789Srpaulo	if ((len = readlink(name, lbuf, sizeof(lbuf) - 1)) == -1)
573253789Srpaulo		mtree_err("%s: %s", name, strerror(errno));
574253789Srpaulo	lbuf[len] = '\0';
575253789Srpaulo	return (lbuf);
576253789Srpaulo}
577253789Srpaulo