<sys/poll.h>: Some namespace cleanup.
[dragonfly.git] / usr.sbin / mtree / compare.c
blobaf783fc36ff2ecf70b7c2311e2e944dc6d2c82ac
1 /*-
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
29 * @(#)compare.c 8.1 (Berkeley) 6/6/93
30 * $FreeBSD: src/usr.sbin/mtree/compare.c,v 1.15.2.4 2003/05/07 17:55:17 tobez Exp $
31 * $DragonFly: src/usr.sbin/mtree/compare.c,v 1.5 2004/03/15 16:24:22 dillon Exp $
34 #include <sys/param.h>
35 #include <sys/stat.h>
36 #include <err.h>
37 #include <errno.h>
38 #include <fcntl.h>
39 #include <fts.h>
40 #ifdef MD5
41 #include <md5.h>
42 #endif
43 #ifdef SHA1
44 #include <sha.h>
45 #endif
46 #ifdef RMD160
47 #include <ripemd.h>
48 #endif
49 #include <stdio.h>
50 #include <time.h>
51 #include <unistd.h>
52 #include "mtree.h"
53 #include "extern.h"
55 static const char *ftype(u_int);
57 #define INDENTNAMELEN 8
58 #define LABEL \
59 if (!label++) { \
60 len = printf("%s changed\n", RP(p)); \
61 tab = "\t"; \
64 int
65 compare(NODE *s, FTSENT *p)
67 u_long len, val;
68 int fd, label;
69 char *cp, *fflags;
70 const char *tab = "";
72 label = 0;
73 switch(s->type) {
74 case F_BLOCK:
75 if (!S_ISBLK(p->fts_statp->st_mode))
76 goto typeerr;
77 break;
78 case F_CHAR:
79 if (!S_ISCHR(p->fts_statp->st_mode))
80 goto typeerr;
81 break;
82 case F_DIR:
83 if (!S_ISDIR(p->fts_statp->st_mode))
84 goto typeerr;
85 break;
86 case F_FIFO:
87 if (!S_ISFIFO(p->fts_statp->st_mode))
88 goto typeerr;
89 break;
90 case F_FILE:
91 if (!S_ISREG(p->fts_statp->st_mode))
92 goto typeerr;
93 break;
94 case F_LINK:
95 if (!S_ISLNK(p->fts_statp->st_mode))
96 goto typeerr;
97 break;
98 case F_SOCK:
99 if (!S_ISSOCK(p->fts_statp->st_mode)) {
100 typeerr: LABEL;
101 printf("\ttype expected %s found %s\n",
102 ftype(s->type), inotype(p->fts_statp->st_mode));
103 return (label);
105 break;
107 /* Set the uid/gid first, then set the mode. */
108 if (s->flags & (F_UID | F_UNAME) && s->st_uid != p->fts_statp->st_uid) {
109 LABEL;
110 printf("%suser expected %lu found %lu",
111 tab, (u_long)s->st_uid, (u_long)p->fts_statp->st_uid);
112 if (uflag)
113 if (chown(p->fts_accpath, s->st_uid, -1))
114 printf(" not modified: %s\n",
115 strerror(errno));
116 else
117 printf(" modified\n");
118 else
119 printf("\n");
120 tab = "\t";
122 if (s->flags & (F_GID | F_GNAME) && s->st_gid != p->fts_statp->st_gid) {
123 LABEL;
124 printf("%sgid expected %lu found %lu",
125 tab, (u_long)s->st_gid, (u_long)p->fts_statp->st_gid);
126 if (uflag)
127 if (chown(p->fts_accpath, -1, s->st_gid))
128 printf(" not modified: %s\n",
129 strerror(errno));
130 else
131 printf(" modified\n");
132 else
133 printf("\n");
134 tab = "\t";
136 if (s->flags & F_MODE &&
137 !S_ISLNK(p->fts_statp->st_mode) &&
138 s->st_mode != (p->fts_statp->st_mode & MBITS)) {
139 LABEL;
140 printf("%spermissions expected %#o found %#o",
141 tab, s->st_mode, p->fts_statp->st_mode & MBITS);
142 if (uflag)
143 if (chmod(p->fts_accpath, s->st_mode))
144 printf(" not modified: %s\n",
145 strerror(errno));
146 else
147 printf(" modified\n");
148 else
149 printf("\n");
150 tab = "\t";
152 if (s->flags & F_NLINK && s->type != F_DIR &&
153 s->st_nlink != p->fts_statp->st_nlink) {
154 LABEL;
155 printf("%slink_count expected %u found %u\n",
156 tab, s->st_nlink, p->fts_statp->st_nlink);
157 tab = "\t";
159 if (s->flags & F_SIZE && s->st_size != p->fts_statp->st_size &&
160 !S_ISDIR(p->fts_statp->st_mode)) {
161 LABEL;
162 printf("%ssize expected %jd found %jd\n", tab,
163 (intmax_t)s->st_size, (intmax_t)p->fts_statp->st_size);
164 tab = "\t";
167 * XXX
168 * Catches nano-second differences, but doesn't display them.
170 if ((s->flags & F_TIME) &&
171 ((s->st_mtimespec.tv_sec != p->fts_statp->st_mtimespec.tv_sec) ||
172 (s->st_mtimespec.tv_nsec != p->fts_statp->st_mtimespec.tv_nsec))) {
173 LABEL;
174 printf("%smodification time expected %.24s ",
175 tab, ctime(&s->st_mtimespec.tv_sec));
176 printf("found %.24s\n",
177 ctime(&p->fts_statp->st_mtimespec.tv_sec));
178 tab = "\t";
180 if (s->flags & F_CKSUM) {
181 if ((fd = open(p->fts_accpath, O_RDONLY, 0)) < 0) {
182 LABEL;
183 printf("%scksum: %s: %s\n",
184 tab, p->fts_accpath, strerror(errno));
185 tab = "\t";
186 } else if (crc(fd, &val, &len)) {
187 close(fd);
188 LABEL;
189 printf("%scksum: %s: %s\n",
190 tab, p->fts_accpath, strerror(errno));
191 tab = "\t";
192 } else {
193 close(fd);
194 if (s->cksum != val) {
195 LABEL;
196 printf("%scksum expected %lu found %lu\n",
197 tab, s->cksum, val);
198 tab = "\t";
203 * XXX
204 * since chflags(2) will reset file times, the utimes() above
205 * may have been useless! oh well, we'd rather have correct
206 * flags, rather than times?
208 if ((s->flags & F_FLAGS) && s->st_flags != p->fts_statp->st_flags) {
209 LABEL;
210 fflags = flags_to_string(s->st_flags);
211 printf("%sflags expected \"%s\"", tab, fflags);
212 free(fflags);
214 fflags = flags_to_string(p->fts_statp->st_flags);
215 printf(" found \"%s\"", fflags);
216 free(fflags);
218 if (uflag)
219 if (chflags(p->fts_accpath, s->st_flags))
220 printf(" not modified: %s\n",
221 strerror(errno));
222 else
223 printf(" modified\n");
224 else
225 printf("\n");
226 tab = "\t";
228 #ifdef MD5
229 if (s->flags & F_MD5) {
230 char *new_digest, buf[33];
232 new_digest = MD5File(p->fts_accpath, buf);
233 if (!new_digest) {
234 LABEL;
235 printf("%sMD5: %s: %s\n", tab, p->fts_accpath,
236 strerror(errno));
237 tab = "\t";
238 } else if (strcmp(new_digest, s->md5digest)) {
239 LABEL;
240 printf("%sMD5 expected %s found %s\n", tab, s->md5digest,
241 new_digest);
242 tab = "\t";
245 #endif /* MD5 */
246 #ifdef SHA1
247 if (s->flags & F_SHA1) {
248 char *new_digest, buf[41];
250 new_digest = SHA1_File(p->fts_accpath, buf);
251 if (!new_digest) {
252 LABEL;
253 printf("%sSHA-1: %s: %s\n", tab, p->fts_accpath,
254 strerror(errno));
255 tab = "\t";
256 } else if (strcmp(new_digest, s->sha1digest)) {
257 LABEL;
258 printf("%sSHA-1 expected %s found %s\n",
259 tab, s->sha1digest, new_digest);
260 tab = "\t";
263 #endif /* SHA1 */
264 #ifdef RMD160
265 if (s->flags & F_RMD160) {
266 char *new_digest, buf[41];
268 new_digest = RIPEMD160_File(p->fts_accpath, buf);
269 if (!new_digest) {
270 LABEL;
271 printf("%sRIPEMD160: %s: %s\n", tab,
272 p->fts_accpath, strerror(errno));
273 tab = "\t";
274 } else if (strcmp(new_digest, s->rmd160digest)) {
275 LABEL;
276 printf("%sRIPEMD160 expected %s found %s\n",
277 tab, s->rmd160digest, new_digest);
278 tab = "\t";
281 #endif /* RMD160 */
283 if (s->flags & F_SLINK &&
284 strcmp(cp = rlink(p->fts_accpath), s->slink)) {
285 LABEL;
286 printf("%slink_ref expected %s found %s\n",
287 tab, s->slink, cp);
289 return (label);
292 const char *
293 inotype(u_int type)
295 switch(type & S_IFMT) {
296 case S_IFBLK:
297 return ("block");
298 case S_IFCHR:
299 return ("char");
300 case S_IFDIR:
301 return ("dir");
302 case S_IFIFO:
303 return ("fifo");
304 case S_IFREG:
305 return ("file");
306 case S_IFLNK:
307 return ("link");
308 case S_IFSOCK:
309 return ("socket");
310 default:
311 return ("unknown");
313 /* NOTREACHED */
316 static const char *
317 ftype(u_int type)
319 switch(type) {
320 case F_BLOCK:
321 return ("block");
322 case F_CHAR:
323 return ("char");
324 case F_DIR:
325 return ("dir");
326 case F_FIFO:
327 return ("fifo");
328 case F_FILE:
329 return ("file");
330 case F_LINK:
331 return ("link");
332 case F_SOCK:
333 return ("socket");
334 default:
335 return ("unknown");
337 /* NOTREACHED */
340 char *
341 rlink(char *name)
343 static char lbuf[MAXPATHLEN];
344 int len;
346 if ((len = readlink(name, lbuf, sizeof(lbuf) - 1)) == -1)
347 err(1, "line %d: %s", lineno, name);
348 lbuf[len] = '\0';
349 return (lbuf);