184d9c625SLionel Sambuc /* $NetBSD: compare.c,v 1.58 2013/11/21 18:39:50 christos Exp $ */
2d433a562SThomas Veerman
3d433a562SThomas Veerman /*-
4d433a562SThomas Veerman * Copyright (c) 1989, 1993
5d433a562SThomas Veerman * The Regents of the University of California. All rights reserved.
6d433a562SThomas Veerman *
7d433a562SThomas Veerman * Redistribution and use in source and binary forms, with or without
8d433a562SThomas Veerman * modification, are permitted provided that the following conditions
9d433a562SThomas Veerman * are met:
10d433a562SThomas Veerman * 1. Redistributions of source code must retain the above copyright
11d433a562SThomas Veerman * notice, this list of conditions and the following disclaimer.
12d433a562SThomas Veerman * 2. Redistributions in binary form must reproduce the above copyright
13d433a562SThomas Veerman * notice, this list of conditions and the following disclaimer in the
14d433a562SThomas Veerman * documentation and/or other materials provided with the distribution.
15d433a562SThomas Veerman * 3. Neither the name of the University nor the names of its contributors
16d433a562SThomas Veerman * may be used to endorse or promote products derived from this software
17d433a562SThomas Veerman * without specific prior written permission.
18d433a562SThomas Veerman *
19d433a562SThomas Veerman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20d433a562SThomas Veerman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21d433a562SThomas Veerman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22d433a562SThomas Veerman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23d433a562SThomas Veerman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24d433a562SThomas Veerman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25d433a562SThomas Veerman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26d433a562SThomas Veerman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27d433a562SThomas Veerman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28d433a562SThomas Veerman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29d433a562SThomas Veerman * SUCH DAMAGE.
30d433a562SThomas Veerman */
31d433a562SThomas Veerman
32d433a562SThomas Veerman #if HAVE_NBTOOL_CONFIG_H
33d433a562SThomas Veerman #include "nbtool_config.h"
34d433a562SThomas Veerman #endif
35d433a562SThomas Veerman
36d433a562SThomas Veerman #include <sys/cdefs.h>
37d433a562SThomas Veerman #if defined(__RCSID) && !defined(lint)
38d433a562SThomas Veerman #if 0
39d433a562SThomas Veerman static char sccsid[] = "@(#)compare.c 8.1 (Berkeley) 6/6/93";
40d433a562SThomas Veerman #else
4184d9c625SLionel Sambuc __RCSID("$NetBSD: compare.c,v 1.58 2013/11/21 18:39:50 christos Exp $");
42d433a562SThomas Veerman #endif
43d433a562SThomas Veerman #endif /* not lint */
44d433a562SThomas Veerman
45d433a562SThomas Veerman #include <sys/param.h>
46a8ef0910SBen Gras #include <sys/stat.h>
47d433a562SThomas Veerman
48d433a562SThomas Veerman #include <errno.h>
49d433a562SThomas Veerman #include <fcntl.h>
50d433a562SThomas Veerman #include <stdio.h>
5184d9c625SLionel Sambuc #include <stdint.h>
52d433a562SThomas Veerman #include <stdlib.h>
53d433a562SThomas Veerman #include <string.h>
54d433a562SThomas Veerman #include <time.h>
55d433a562SThomas Veerman #include <unistd.h>
56d433a562SThomas Veerman
57d433a562SThomas Veerman #ifndef NO_MD5
58d433a562SThomas Veerman #include <md5.h>
59d433a562SThomas Veerman #endif
60d433a562SThomas Veerman #ifndef NO_RMD160
61d433a562SThomas Veerman #include <rmd160.h>
62d433a562SThomas Veerman #endif
63d433a562SThomas Veerman #ifndef NO_SHA1
64d433a562SThomas Veerman #include <sha1.h>
65d433a562SThomas Veerman #endif
66d433a562SThomas Veerman #ifndef NO_SHA2
67d433a562SThomas Veerman #include <sha2.h>
68d433a562SThomas Veerman #endif
69d433a562SThomas Veerman
70d433a562SThomas Veerman #include "extern.h"
71d433a562SThomas Veerman
72d433a562SThomas Veerman #define INDENTNAMELEN 8
73d433a562SThomas Veerman #define MARK \
74d433a562SThomas Veerman do { \
7584d9c625SLionel Sambuc if (flavor == F_FREEBSD9) { \
7684d9c625SLionel Sambuc len = printf("%s changed\n", RP(p)); \
7784d9c625SLionel Sambuc tab = "\t"; \
7884d9c625SLionel Sambuc } else { \
79d433a562SThomas Veerman len = printf("%s: ", RP(p)); \
80d433a562SThomas Veerman if (len > INDENTNAMELEN) { \
81d433a562SThomas Veerman tab = "\t"; \
82d433a562SThomas Veerman printf("\n"); \
83d433a562SThomas Veerman } else { \
84d433a562SThomas Veerman tab = ""; \
85d433a562SThomas Veerman printf("%*s", INDENTNAMELEN - (int)len, ""); \
86d433a562SThomas Veerman } \
8784d9c625SLionel Sambuc } \
88d433a562SThomas Veerman } while (0)
89d433a562SThomas Veerman #define LABEL if (!label++) MARK
90d433a562SThomas Veerman
91d433a562SThomas Veerman #if HAVE_STRUCT_STAT_ST_FLAGS
92d433a562SThomas Veerman
93a8ef0910SBen Gras
94d433a562SThomas Veerman #define CHANGEFLAGS \
95d433a562SThomas Veerman if (flags != p->fts_statp->st_flags) { \
96d433a562SThomas Veerman char *sf; \
97d433a562SThomas Veerman if (!label) { \
98d433a562SThomas Veerman MARK; \
99d433a562SThomas Veerman sf = flags_to_string(p->fts_statp->st_flags, "none"); \
100d433a562SThomas Veerman printf("%sflags (\"%s\"", tab, sf); \
101d433a562SThomas Veerman free(sf); \
102d433a562SThomas Veerman } \
103d433a562SThomas Veerman if (lchflags(p->fts_accpath, flags)) { \
104d433a562SThomas Veerman label++; \
105d433a562SThomas Veerman printf(", not modified: %s)\n", \
106d433a562SThomas Veerman strerror(errno)); \
107d433a562SThomas Veerman } else { \
108d433a562SThomas Veerman sf = flags_to_string(flags, "none"); \
109d433a562SThomas Veerman printf(", modified to \"%s\")\n", sf); \
110d433a562SThomas Veerman free(sf); \
111d433a562SThomas Veerman } \
112d433a562SThomas Veerman }
113d433a562SThomas Veerman
114d433a562SThomas Veerman /* SETFLAGS:
115d433a562SThomas Veerman * given pflags, additionally set those flags specified in s->st_flags and
116d433a562SThomas Veerman * selected by mask (the other flags are left unchanged).
117d433a562SThomas Veerman */
118d433a562SThomas Veerman #define SETFLAGS(pflags, mask) \
119d433a562SThomas Veerman do { \
120d433a562SThomas Veerman flags = (s->st_flags & (mask)) | (pflags); \
121d433a562SThomas Veerman CHANGEFLAGS; \
122d433a562SThomas Veerman } while (0)
123d433a562SThomas Veerman
124d433a562SThomas Veerman /* CLEARFLAGS:
125d433a562SThomas Veerman * given pflags, reset the flags specified in s->st_flags and selected by mask
126d433a562SThomas Veerman * (the other flags are left unchanged).
127d433a562SThomas Veerman */
128d433a562SThomas Veerman #define CLEARFLAGS(pflags, mask) \
129d433a562SThomas Veerman do { \
130d433a562SThomas Veerman flags = (~(s->st_flags & (mask)) & CH_MASK) & (pflags); \
131d433a562SThomas Veerman CHANGEFLAGS; \
132d433a562SThomas Veerman } while (0)
133d433a562SThomas Veerman #endif /* HAVE_STRUCT_STAT_ST_FLAGS */
134d433a562SThomas Veerman
135d433a562SThomas Veerman int
compare(NODE * s,FTSENT * p)136d433a562SThomas Veerman compare(NODE *s, FTSENT *p)
137d433a562SThomas Veerman {
138*0a6a1f1dSLionel Sambuc u_int32_t len, val, flags;
139d433a562SThomas Veerman int fd, label;
140d433a562SThomas Veerman const char *cp, *tab;
141d433a562SThomas Veerman #if !defined(NO_MD5) || !defined(NO_RMD160) || !defined(NO_SHA1) || !defined(NO_SHA2)
142d433a562SThomas Veerman char *digestbuf;
143d433a562SThomas Veerman #endif
144d433a562SThomas Veerman
145d433a562SThomas Veerman tab = NULL;
146d433a562SThomas Veerman label = 0;
147d433a562SThomas Veerman switch(s->type) {
148d433a562SThomas Veerman case F_BLOCK:
149d433a562SThomas Veerman if (!S_ISBLK(p->fts_statp->st_mode))
150d433a562SThomas Veerman goto typeerr;
151d433a562SThomas Veerman break;
152d433a562SThomas Veerman case F_CHAR:
153d433a562SThomas Veerman if (!S_ISCHR(p->fts_statp->st_mode))
154d433a562SThomas Veerman goto typeerr;
155d433a562SThomas Veerman break;
156d433a562SThomas Veerman case F_DIR:
157d433a562SThomas Veerman if (!S_ISDIR(p->fts_statp->st_mode))
158d433a562SThomas Veerman goto typeerr;
159d433a562SThomas Veerman break;
160d433a562SThomas Veerman case F_FIFO:
161d433a562SThomas Veerman if (!S_ISFIFO(p->fts_statp->st_mode))
162d433a562SThomas Veerman goto typeerr;
163d433a562SThomas Veerman break;
164d433a562SThomas Veerman case F_FILE:
165d433a562SThomas Veerman if (!S_ISREG(p->fts_statp->st_mode))
166d433a562SThomas Veerman goto typeerr;
167d433a562SThomas Veerman break;
168d433a562SThomas Veerman case F_LINK:
169d433a562SThomas Veerman if (!S_ISLNK(p->fts_statp->st_mode))
170d433a562SThomas Veerman goto typeerr;
171d433a562SThomas Veerman break;
172d433a562SThomas Veerman #ifdef S_ISSOCK
173d433a562SThomas Veerman case F_SOCK:
174d433a562SThomas Veerman if (!S_ISSOCK(p->fts_statp->st_mode))
175d433a562SThomas Veerman goto typeerr;
176d433a562SThomas Veerman break;
177d433a562SThomas Veerman #endif
178d433a562SThomas Veerman typeerr: LABEL;
17984d9c625SLionel Sambuc printf(flavor == F_FREEBSD9 ?
18084d9c625SLionel Sambuc "\ttype expected %s found %s\n" : "\ttype (%s, %s)\n",
181d433a562SThomas Veerman nodetype(s->type), inotype(p->fts_statp->st_mode));
182d433a562SThomas Veerman return (label);
183d433a562SThomas Veerman }
184d433a562SThomas Veerman if (mtree_Wflag)
185d433a562SThomas Veerman goto afterpermwhack;
186a8ef0910SBen Gras #if HAVE_STRUCT_STAT_ST_FLAGS
187d433a562SThomas Veerman if (iflag && !uflag) {
188d433a562SThomas Veerman if (s->flags & F_FLAGS)
189d433a562SThomas Veerman SETFLAGS(p->fts_statp->st_flags, SP_FLGS);
190d433a562SThomas Veerman return (label);
191d433a562SThomas Veerman }
192d433a562SThomas Veerman if (mflag && !uflag) {
193d433a562SThomas Veerman if (s->flags & F_FLAGS)
194d433a562SThomas Veerman CLEARFLAGS(p->fts_statp->st_flags, SP_FLGS);
195d433a562SThomas Veerman return (label);
196d433a562SThomas Veerman }
197d433a562SThomas Veerman #endif
198d433a562SThomas Veerman if (s->flags & F_DEV &&
199d433a562SThomas Veerman (s->type == F_BLOCK || s->type == F_CHAR) &&
200d433a562SThomas Veerman s->st_rdev != p->fts_statp->st_rdev) {
201d433a562SThomas Veerman LABEL;
20284d9c625SLionel Sambuc printf(flavor == F_FREEBSD9 ?
20384d9c625SLionel Sambuc "%sdevice expected %#jx found %#jx" :
20484d9c625SLionel Sambuc "%sdevice (%#jx, %#jx",
20584d9c625SLionel Sambuc tab, (uintmax_t)s->st_rdev,
20684d9c625SLionel Sambuc (uintmax_t)p->fts_statp->st_rdev);
207d433a562SThomas Veerman if (uflag) {
208d433a562SThomas Veerman if ((unlink(p->fts_accpath) == -1) ||
209d433a562SThomas Veerman (mknod(p->fts_accpath,
210d433a562SThomas Veerman s->st_mode | nodetoino(s->type),
211d433a562SThomas Veerman s->st_rdev) == -1) ||
212d433a562SThomas Veerman (lchown(p->fts_accpath, p->fts_statp->st_uid,
213d433a562SThomas Veerman p->fts_statp->st_gid) == -1) )
21484d9c625SLionel Sambuc printf(", not modified: %s%s\n",
21584d9c625SLionel Sambuc strerror(errno),
21684d9c625SLionel Sambuc flavor == F_FREEBSD9 ? "" : ")");
217d433a562SThomas Veerman else
21884d9c625SLionel Sambuc printf(", modified%s\n",
21984d9c625SLionel Sambuc flavor == F_FREEBSD9 ? "" : ")");
220d433a562SThomas Veerman } else
221d433a562SThomas Veerman printf(")\n");
222d433a562SThomas Veerman tab = "\t";
223d433a562SThomas Veerman }
224d433a562SThomas Veerman /* Set the uid/gid first, then set the mode. */
225d433a562SThomas Veerman if (s->flags & (F_UID | F_UNAME) && s->st_uid != p->fts_statp->st_uid) {
226d433a562SThomas Veerman LABEL;
22784d9c625SLionel Sambuc printf(flavor == F_FREEBSD9 ?
22884d9c625SLionel Sambuc "%suser expected %lu found %lu" : "%suser (%lu, %lu",
229d433a562SThomas Veerman tab, (u_long)s->st_uid, (u_long)p->fts_statp->st_uid);
230d433a562SThomas Veerman if (uflag) {
231d433a562SThomas Veerman if (lchown(p->fts_accpath, s->st_uid, -1))
23284d9c625SLionel Sambuc printf(", not modified: %s%s\n",
23384d9c625SLionel Sambuc strerror(errno),
23484d9c625SLionel Sambuc flavor == F_FREEBSD9 ? "" : ")");
235d433a562SThomas Veerman else
23684d9c625SLionel Sambuc printf(", modified%s\n",
23784d9c625SLionel Sambuc flavor == F_FREEBSD9 ? "" : ")");
238d433a562SThomas Veerman } else
239d433a562SThomas Veerman printf(")\n");
240d433a562SThomas Veerman tab = "\t";
241d433a562SThomas Veerman }
242d433a562SThomas Veerman if (s->flags & (F_GID | F_GNAME) && s->st_gid != p->fts_statp->st_gid) {
243d433a562SThomas Veerman LABEL;
24484d9c625SLionel Sambuc printf(flavor == F_FREEBSD9 ?
24584d9c625SLionel Sambuc "%sgid expected %lu found %lu" : "%sgid (%lu, %lu",
246d433a562SThomas Veerman tab, (u_long)s->st_gid, (u_long)p->fts_statp->st_gid);
247d433a562SThomas Veerman if (uflag) {
248d433a562SThomas Veerman if (lchown(p->fts_accpath, -1, s->st_gid))
24984d9c625SLionel Sambuc printf(", not modified: %s%s\n",
25084d9c625SLionel Sambuc strerror(errno),
25184d9c625SLionel Sambuc flavor == F_FREEBSD9 ? "" : ")");
252d433a562SThomas Veerman else
25384d9c625SLionel Sambuc printf(", modified%s\n",
25484d9c625SLionel Sambuc flavor == F_FREEBSD9 ? "" : ")");
255d433a562SThomas Veerman }
256d433a562SThomas Veerman else
257d433a562SThomas Veerman printf(")\n");
258d433a562SThomas Veerman tab = "\t";
259d433a562SThomas Veerman }
260d433a562SThomas Veerman if (s->flags & F_MODE &&
261d433a562SThomas Veerman s->st_mode != (p->fts_statp->st_mode & MBITS)) {
262d433a562SThomas Veerman if (lflag) {
263d433a562SThomas Veerman mode_t tmode, mode;
264d433a562SThomas Veerman
265d433a562SThomas Veerman tmode = s->st_mode;
266d433a562SThomas Veerman mode = p->fts_statp->st_mode & MBITS;
267d433a562SThomas Veerman /*
268d433a562SThomas Veerman * if none of the suid/sgid/etc bits are set,
269d433a562SThomas Veerman * then if the mode is a subset of the target,
270d433a562SThomas Veerman * skip.
271d433a562SThomas Veerman */
272d433a562SThomas Veerman if (!((tmode & ~(S_IRWXU|S_IRWXG|S_IRWXO)) ||
273d433a562SThomas Veerman (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO))))
274d433a562SThomas Veerman if ((mode | tmode) == tmode)
275d433a562SThomas Veerman goto skip;
276d433a562SThomas Veerman }
277d433a562SThomas Veerman
278d433a562SThomas Veerman LABEL;
27984d9c625SLionel Sambuc printf(flavor == F_FREEBSD9 ?
28084d9c625SLionel Sambuc "%spermissions expcted %#lo found %#lo" :
28184d9c625SLionel Sambuc "%spermissions (%#lo, %#lo",
282d433a562SThomas Veerman tab, (u_long)s->st_mode,
283d433a562SThomas Veerman (u_long)p->fts_statp->st_mode & MBITS);
284d433a562SThomas Veerman if (uflag) {
285d433a562SThomas Veerman if (lchmod(p->fts_accpath, s->st_mode))
28684d9c625SLionel Sambuc printf(", not modified: %s%s\n",
28784d9c625SLionel Sambuc strerror(errno),
28884d9c625SLionel Sambuc flavor == F_FREEBSD9 ? "" : ")");
289d433a562SThomas Veerman else
29084d9c625SLionel Sambuc printf(", modified%s\n",
29184d9c625SLionel Sambuc flavor == F_FREEBSD9 ? "" : ")");
292d433a562SThomas Veerman }
293d433a562SThomas Veerman else
294d433a562SThomas Veerman printf(")\n");
295d433a562SThomas Veerman tab = "\t";
296d433a562SThomas Veerman skip: ;
297d433a562SThomas Veerman }
298d433a562SThomas Veerman if (s->flags & F_NLINK && s->type != F_DIR &&
299d433a562SThomas Veerman s->st_nlink != p->fts_statp->st_nlink) {
300d433a562SThomas Veerman LABEL;
30184d9c625SLionel Sambuc printf(flavor == F_FREEBSD9 ?
30284d9c625SLionel Sambuc "%slink count expected %lu found %lu\n" :
30384d9c625SLionel Sambuc "%slink count (%lu, %lu)\n",
304d433a562SThomas Veerman tab, (u_long)s->st_nlink, (u_long)p->fts_statp->st_nlink);
305d433a562SThomas Veerman tab = "\t";
306d433a562SThomas Veerman }
307d433a562SThomas Veerman if (s->flags & F_SIZE && s->st_size != p->fts_statp->st_size) {
308d433a562SThomas Veerman LABEL;
30984d9c625SLionel Sambuc printf(flavor == F_FREEBSD9 ?
31084d9c625SLionel Sambuc "%ssize expected %ju found %ju\n" : "%ssize (%ju, %ju)\n",
31184d9c625SLionel Sambuc tab, (uintmax_t)s->st_size,
31284d9c625SLionel Sambuc (uintmax_t)p->fts_statp->st_size);
313d433a562SThomas Veerman tab = "\t";
314d433a562SThomas Veerman }
315d433a562SThomas Veerman /*
316d433a562SThomas Veerman * XXX
317d433a562SThomas Veerman * Since utimes(2) only takes a timeval, there's no point in
318d433a562SThomas Veerman * comparing the low bits of the timespec nanosecond field. This
319d433a562SThomas Veerman * will only result in mismatches that we can never fix.
320d433a562SThomas Veerman *
321d433a562SThomas Veerman * Doesn't display microsecond differences.
322d433a562SThomas Veerman */
323d433a562SThomas Veerman if (s->flags & F_TIME) {
324d433a562SThomas Veerman struct timeval tv[2];
325d433a562SThomas Veerman struct stat *ps = p->fts_statp;
326d433a562SThomas Veerman time_t smtime = s->st_mtimespec.tv_sec;
327d433a562SThomas Veerman
328d433a562SThomas Veerman #if defined(BSD4_4) && !defined(HAVE_NBTOOL_CONFIG_H)
329d433a562SThomas Veerman time_t pmtime = ps->st_mtimespec.tv_sec;
330d433a562SThomas Veerman
331d433a562SThomas Veerman TIMESPEC_TO_TIMEVAL(&tv[0], &s->st_mtimespec);
332d433a562SThomas Veerman TIMESPEC_TO_TIMEVAL(&tv[1], &ps->st_mtimespec);
333d433a562SThomas Veerman #else
334d433a562SThomas Veerman time_t pmtime = (time_t)ps->st_mtime;
335d433a562SThomas Veerman
336d433a562SThomas Veerman tv[0].tv_sec = smtime;
337d433a562SThomas Veerman tv[0].tv_usec = 0;
338d433a562SThomas Veerman tv[1].tv_sec = pmtime;
339d433a562SThomas Veerman tv[1].tv_usec = 0;
340d433a562SThomas Veerman #endif
341d433a562SThomas Veerman
342d433a562SThomas Veerman if (tv[0].tv_sec != tv[1].tv_sec ||
343d433a562SThomas Veerman tv[0].tv_usec != tv[1].tv_usec) {
344d433a562SThomas Veerman LABEL;
34584d9c625SLionel Sambuc printf(flavor == F_FREEBSD9 ?
34684d9c625SLionel Sambuc "%smodification time expected %.24s found " :
34784d9c625SLionel Sambuc "%smodification time (%.24s, ",
348d433a562SThomas Veerman tab, ctime(&smtime));
349d433a562SThomas Veerman printf("%.24s", ctime(&pmtime));
350d433a562SThomas Veerman if (tflag) {
351d433a562SThomas Veerman tv[1] = tv[0];
352d433a562SThomas Veerman if (utimes(p->fts_accpath, tv))
35384d9c625SLionel Sambuc printf(", not modified: %s%s\n",
35484d9c625SLionel Sambuc strerror(errno),
35584d9c625SLionel Sambuc flavor == F_FREEBSD9 ? "" : ")");
356d433a562SThomas Veerman else
35784d9c625SLionel Sambuc printf(", modified%s\n",
35884d9c625SLionel Sambuc flavor == F_FREEBSD9 ? "" : ")");
359d433a562SThomas Veerman } else
36084d9c625SLionel Sambuc printf("%s\n", flavor == F_FREEBSD9 ? "" : ")");
361d433a562SThomas Veerman tab = "\t";
362d433a562SThomas Veerman }
363d433a562SThomas Veerman }
364a8ef0910SBen Gras #if HAVE_STRUCT_STAT_ST_FLAGS
365d433a562SThomas Veerman /*
366d433a562SThomas Veerman * XXX
367d433a562SThomas Veerman * since lchflags(2) will reset file times, the utimes() above
368d433a562SThomas Veerman * may have been useless! oh well, we'd rather have correct
369d433a562SThomas Veerman * flags, rather than times?
370d433a562SThomas Veerman */
371d433a562SThomas Veerman if ((s->flags & F_FLAGS) && ((s->st_flags != p->fts_statp->st_flags)
372d433a562SThomas Veerman || mflag || iflag)) {
373d433a562SThomas Veerman if (s->st_flags != p->fts_statp->st_flags) {
374d433a562SThomas Veerman char *f_s;
375d433a562SThomas Veerman LABEL;
376d433a562SThomas Veerman f_s = flags_to_string(s->st_flags, "none");
37784d9c625SLionel Sambuc printf(flavor == F_FREEBSD9 ?
37884d9c625SLionel Sambuc "%sflags expected \"%s\" found " :
37984d9c625SLionel Sambuc "%sflags (\"%s\" is not ", tab, f_s);
380d433a562SThomas Veerman free(f_s);
381d433a562SThomas Veerman f_s = flags_to_string(p->fts_statp->st_flags, "none");
382d433a562SThomas Veerman printf("\"%s\"", f_s);
383d433a562SThomas Veerman free(f_s);
384d433a562SThomas Veerman }
385d433a562SThomas Veerman if (uflag) {
386d433a562SThomas Veerman if (iflag)
387d433a562SThomas Veerman SETFLAGS(0, CH_MASK);
388d433a562SThomas Veerman else if (mflag)
389d433a562SThomas Veerman CLEARFLAGS(0, SP_FLGS);
390d433a562SThomas Veerman else
391d433a562SThomas Veerman SETFLAGS(0, (~SP_FLGS & CH_MASK));
392d433a562SThomas Veerman } else
39384d9c625SLionel Sambuc printf("%s\n", flavor == F_FREEBSD9 ? "" : ")");
394d433a562SThomas Veerman tab = "\t";
395d433a562SThomas Veerman }
396d433a562SThomas Veerman #endif /* HAVE_STRUCT_STAT_ST_FLAGS */
397d433a562SThomas Veerman
398d433a562SThomas Veerman /*
399d433a562SThomas Veerman * from this point, no more permission checking or whacking
400d433a562SThomas Veerman * occurs, only checking of stuff like checksums and symlinks.
401d433a562SThomas Veerman */
402d433a562SThomas Veerman afterpermwhack:
403d433a562SThomas Veerman if (s->flags & F_CKSUM) {
404d433a562SThomas Veerman if ((fd = open(p->fts_accpath, O_RDONLY, 0)) < 0) {
405d433a562SThomas Veerman LABEL;
406d433a562SThomas Veerman printf("%scksum: %s: %s\n",
407d433a562SThomas Veerman tab, p->fts_accpath, strerror(errno));
408d433a562SThomas Veerman tab = "\t";
409d433a562SThomas Veerman } else if (crc(fd, &val, &len)) {
410d433a562SThomas Veerman close(fd);
411d433a562SThomas Veerman LABEL;
412d433a562SThomas Veerman printf("%scksum: %s: %s\n",
413d433a562SThomas Veerman tab, p->fts_accpath, strerror(errno));
414d433a562SThomas Veerman tab = "\t";
415d433a562SThomas Veerman } else {
416d433a562SThomas Veerman close(fd);
417d433a562SThomas Veerman if (s->cksum != val) {
418d433a562SThomas Veerman LABEL;
41984d9c625SLionel Sambuc printf(flavor == F_FREEBSD9 ?
42084d9c625SLionel Sambuc "%scksum expected %lu found %lu\n" :
42184d9c625SLionel Sambuc "%scksum (%lu, %lu)\n",
422d433a562SThomas Veerman tab, s->cksum, (unsigned long)val);
423d433a562SThomas Veerman }
424d433a562SThomas Veerman tab = "\t";
425d433a562SThomas Veerman }
426d433a562SThomas Veerman }
427d433a562SThomas Veerman #ifndef NO_MD5
428d433a562SThomas Veerman if (s->flags & F_MD5) {
429d433a562SThomas Veerman if ((digestbuf = MD5File(p->fts_accpath, NULL)) == NULL) {
430d433a562SThomas Veerman LABEL;
431a8ef0910SBen Gras printf("%s%s: %s: %s\n",
432a8ef0910SBen Gras tab, MD5KEY, p->fts_accpath, strerror(errno));
433d433a562SThomas Veerman tab = "\t";
434d433a562SThomas Veerman } else {
435d433a562SThomas Veerman if (strcmp(s->md5digest, digestbuf)) {
436d433a562SThomas Veerman LABEL;
43784d9c625SLionel Sambuc printf(flavor == F_FREEBSD9 ?
43884d9c625SLionel Sambuc "%s%s expected %s found %s\n" :
43984d9c625SLionel Sambuc "%s%s (0x%s, 0x%s)\n",
440a8ef0910SBen Gras tab, MD5KEY, s->md5digest, digestbuf);
441d433a562SThomas Veerman }
442d433a562SThomas Veerman tab = "\t";
443d433a562SThomas Veerman free(digestbuf);
444d433a562SThomas Veerman }
445d433a562SThomas Veerman }
446d433a562SThomas Veerman #endif /* ! NO_MD5 */
447d433a562SThomas Veerman #ifndef NO_RMD160
448d433a562SThomas Veerman if (s->flags & F_RMD160) {
449d433a562SThomas Veerman if ((digestbuf = RMD160File(p->fts_accpath, NULL)) == NULL) {
450d433a562SThomas Veerman LABEL;
451a8ef0910SBen Gras printf("%s%s: %s: %s\n",
452a8ef0910SBen Gras tab, RMD160KEY, p->fts_accpath, strerror(errno));
453d433a562SThomas Veerman tab = "\t";
454d433a562SThomas Veerman } else {
455d433a562SThomas Veerman if (strcmp(s->rmd160digest, digestbuf)) {
456d433a562SThomas Veerman LABEL;
45784d9c625SLionel Sambuc printf(flavor == F_FREEBSD9 ?
45884d9c625SLionel Sambuc "%s%s expected %s found %s\n" :
45984d9c625SLionel Sambuc "%s%s (0x%s, 0x%s)\n",
460a8ef0910SBen Gras tab, RMD160KEY, s->rmd160digest, digestbuf);
461d433a562SThomas Veerman }
462d433a562SThomas Veerman tab = "\t";
463d433a562SThomas Veerman free(digestbuf);
464d433a562SThomas Veerman }
465d433a562SThomas Veerman }
466d433a562SThomas Veerman #endif /* ! NO_RMD160 */
467d433a562SThomas Veerman #ifndef NO_SHA1
468d433a562SThomas Veerman if (s->flags & F_SHA1) {
469d433a562SThomas Veerman if ((digestbuf = SHA1File(p->fts_accpath, NULL)) == NULL) {
470d433a562SThomas Veerman LABEL;
471a8ef0910SBen Gras printf("%s%s: %s: %s\n",
472a8ef0910SBen Gras tab, SHA1KEY, p->fts_accpath, strerror(errno));
473d433a562SThomas Veerman tab = "\t";
474d433a562SThomas Veerman } else {
475d433a562SThomas Veerman if (strcmp(s->sha1digest, digestbuf)) {
476d433a562SThomas Veerman LABEL;
47784d9c625SLionel Sambuc printf(flavor == F_FREEBSD9 ?
47884d9c625SLionel Sambuc "%s%s expected %s found %s\n" :
47984d9c625SLionel Sambuc "%s%s (0x%s, 0x%s)\n",
480a8ef0910SBen Gras tab, SHA1KEY, s->sha1digest, digestbuf);
481d433a562SThomas Veerman }
482d433a562SThomas Veerman tab = "\t";
483d433a562SThomas Veerman free(digestbuf);
484d433a562SThomas Veerman }
485d433a562SThomas Veerman }
486d433a562SThomas Veerman #endif /* ! NO_SHA1 */
487d433a562SThomas Veerman #ifndef NO_SHA2
488d433a562SThomas Veerman if (s->flags & F_SHA256) {
489d433a562SThomas Veerman if ((digestbuf = SHA256_File(p->fts_accpath, NULL)) == NULL) {
490d433a562SThomas Veerman LABEL;
491a8ef0910SBen Gras printf("%s%s: %s: %s\n",
492a8ef0910SBen Gras tab, SHA256KEY, p->fts_accpath, strerror(errno));
493d433a562SThomas Veerman tab = "\t";
494d433a562SThomas Veerman } else {
495d433a562SThomas Veerman if (strcmp(s->sha256digest, digestbuf)) {
496d433a562SThomas Veerman LABEL;
49784d9c625SLionel Sambuc printf(flavor == F_FREEBSD9 ?
49884d9c625SLionel Sambuc "%s%s expected %s found %s\n" :
49984d9c625SLionel Sambuc "%s%s (0x%s, 0x%s)\n",
500a8ef0910SBen Gras tab, SHA256KEY, s->sha256digest, digestbuf);
501d433a562SThomas Veerman }
502d433a562SThomas Veerman tab = "\t";
503d433a562SThomas Veerman free(digestbuf);
504d433a562SThomas Veerman }
505d433a562SThomas Veerman }
506a8ef0910SBen Gras #ifdef SHA384_BLOCK_LENGTH
507d433a562SThomas Veerman if (s->flags & F_SHA384) {
508d433a562SThomas Veerman if ((digestbuf = SHA384_File(p->fts_accpath, NULL)) == NULL) {
509d433a562SThomas Veerman LABEL;
510a8ef0910SBen Gras printf("%s%s: %s: %s\n",
511a8ef0910SBen Gras tab, SHA384KEY, p->fts_accpath, strerror(errno));
512d433a562SThomas Veerman tab = "\t";
513d433a562SThomas Veerman } else {
514d433a562SThomas Veerman if (strcmp(s->sha384digest, digestbuf)) {
515d433a562SThomas Veerman LABEL;
51684d9c625SLionel Sambuc printf(flavor == F_FREEBSD9 ?
51784d9c625SLionel Sambuc "%s%s expected %s found %s\n" :
51884d9c625SLionel Sambuc "%s%s (0x%s, 0x%s)\n",
519a8ef0910SBen Gras tab, SHA384KEY, s->sha384digest, digestbuf);
520d433a562SThomas Veerman }
521d433a562SThomas Veerman tab = "\t";
522d433a562SThomas Veerman free(digestbuf);
523d433a562SThomas Veerman }
524d433a562SThomas Veerman }
525a8ef0910SBen Gras #endif
526d433a562SThomas Veerman if (s->flags & F_SHA512) {
527d433a562SThomas Veerman if ((digestbuf = SHA512_File(p->fts_accpath, NULL)) == NULL) {
528d433a562SThomas Veerman LABEL;
529a8ef0910SBen Gras printf("%s%s: %s: %s\n",
530a8ef0910SBen Gras tab, SHA512KEY, p->fts_accpath, strerror(errno));
531d433a562SThomas Veerman tab = "\t";
532d433a562SThomas Veerman } else {
533d433a562SThomas Veerman if (strcmp(s->sha512digest, digestbuf)) {
534d433a562SThomas Veerman LABEL;
53584d9c625SLionel Sambuc printf(flavor == F_FREEBSD9 ?
53684d9c625SLionel Sambuc "%s%s expected %s found %s\n" :
53784d9c625SLionel Sambuc "%s%s (0x%s, 0x%s)\n",
538a8ef0910SBen Gras tab, SHA512KEY, s->sha512digest, digestbuf);
539d433a562SThomas Veerman }
540d433a562SThomas Veerman tab = "\t";
541d433a562SThomas Veerman free(digestbuf);
542d433a562SThomas Veerman }
543d433a562SThomas Veerman }
544d433a562SThomas Veerman #endif /* ! NO_SHA2 */
545d433a562SThomas Veerman if (s->flags & F_SLINK &&
546d433a562SThomas Veerman strcmp(cp = rlink(p->fts_accpath), s->slink)) {
547d433a562SThomas Veerman LABEL;
54884d9c625SLionel Sambuc printf(flavor == F_FREEBSD9 ?
54984d9c625SLionel Sambuc "%slink ref expected %s found %s" :
55084d9c625SLionel Sambuc "%slink ref (%s, %s", tab, cp, s->slink);
551d433a562SThomas Veerman if (uflag) {
552d433a562SThomas Veerman if ((unlink(p->fts_accpath) == -1) ||
553d433a562SThomas Veerman (symlink(s->slink, p->fts_accpath) == -1) )
55484d9c625SLionel Sambuc printf(", not modified: %s%s\n",
55584d9c625SLionel Sambuc strerror(errno),
55684d9c625SLionel Sambuc flavor == F_FREEBSD9 ? "" : ")");
557d433a562SThomas Veerman else
55884d9c625SLionel Sambuc printf(", modified%s\n",
55984d9c625SLionel Sambuc flavor == F_FREEBSD9 ? "" : ")");
560d433a562SThomas Veerman } else
56184d9c625SLionel Sambuc printf("%s\n", flavor == F_FREEBSD9 ? "" : ")");
562d433a562SThomas Veerman }
563d433a562SThomas Veerman return (label);
564d433a562SThomas Veerman }
565d433a562SThomas Veerman
566d433a562SThomas Veerman const char *
rlink(const char * name)567d433a562SThomas Veerman rlink(const char *name)
568d433a562SThomas Veerman {
569d433a562SThomas Veerman static char lbuf[MAXPATHLEN];
570d433a562SThomas Veerman int len;
571d433a562SThomas Veerman
572d433a562SThomas Veerman if ((len = readlink(name, lbuf, sizeof(lbuf) - 1)) == -1)
573d433a562SThomas Veerman mtree_err("%s: %s", name, strerror(errno));
574d433a562SThomas Veerman lbuf[len] = '\0';
575d433a562SThomas Veerman return (lbuf);
576d433a562SThomas Veerman }
577