compare.c revision 44303
119304Speter/*-
219304Speter * Copyright (c) 1989, 1993
319304Speter *	The Regents of the University of California.  All rights reserved.
419304Speter *
519304Speter * Redistribution and use in source and binary forms, with or without
619304Speter * modification, are permitted provided that the following conditions
719304Speter * are met:
819304Speter * 1. Redistributions of source code must retain the above copyright
919304Speter *    notice, this list of conditions and the following disclaimer.
1019304Speter * 2. Redistributions in binary form must reproduce the above copyright
1119304Speter *    notice, this list of conditions and the following disclaimer in the
1219304Speter *    documentation and/or other materials provided with the distribution.
13254225Speter * 3. All advertising materials mentioning features or use of this software
1419304Speter *    must display the following acknowledgement:
1519304Speter *	This product includes software developed by the University of
1619304Speter *	California, Berkeley and its contributors.
1719304Speter * 4. Neither the name of the University nor the names of its contributors
1819304Speter *    may be used to endorse or promote products derived from this software
1919304Speter *    without specific prior written permission.
2019304Speter *
2119304Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2219304Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2319304Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2419304Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2519304Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2619304Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2719304Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2819304Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2919304Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3019304Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3119304Speter * SUCH DAMAGE.
3219304Speter */
3319304Speter
34254225Speter#ifndef lint
3519304Speter#if 0
3619304Speterstatic char sccsid[] = "@(#)compare.c	8.1 (Berkeley) 6/6/93";
3719304Speter#endif
3819304Speterstatic const char rcsid[] =
3919304Speter	"$Id: compare.c,v 1.10 1998/08/02 14:41:34 bde Exp $";
4019304Speter#endif /* not lint */
4119304Speter
4219304Speter#include <sys/param.h>
4319304Speter#include <sys/stat.h>
4419304Speter#include <err.h>
4519304Speter#include <errno.h>
4619304Speter#include <fcntl.h>
4719304Speter#include <fts.h>
4819304Speter#ifdef MD5
4919304Speter#include <md5.h>
5019304Speter#endif
5119304Speter#ifdef SHA1
5219304Speter#include <sha.h>
5319304Speter#endif
5419304Speter#ifdef RMD160
5519304Speter#include <ripemd.h>
5619304Speter#endif
5719304Speter#include <stdio.h>
5819304Speter#include <time.h>
5919304Speter#include <unistd.h>
6019304Speter#include "mtree.h"
6119304Speter#include "extern.h"
6219304Speter
6319304Speterextern int uflag;
6419304Speterextern int lineno;
6519304Speter
6619304Speterstatic char *ftype __P((u_int));
6719304Speter
6819304Speter#define	INDENTNAMELEN	8
6919304Speter#define	LABEL \
7019304Speter	if (!label++) { \
7119304Speter		len = printf("%s: ", RP(p)); \
72254225Speter		if (len > INDENTNAMELEN) { \
7319304Speter			tab = "\t"; \
7419304Speter			(void)printf("\n"); \
7519304Speter		} else { \
7619304Speter			tab = ""; \
7719304Speter			(void)printf("%*s", INDENTNAMELEN - (int)len, ""); \
7819304Speter		} \
7919304Speter	}
8019304Speter
8119304Speterint
8219304Spetercompare(name, s, p)
8319304Speter	char *name;
8419304Speter	register NODE *s;
8519304Speter	register FTSENT *p;
8619304Speter{
8719304Speter	extern int uflag;
8819304Speter	u_long len, val;
8919304Speter	int fd, label;
9019304Speter	char *cp, *tab = "";
9119304Speter
9219304Speter	label = 0;
9319304Speter	switch(s->type) {
9419304Speter	case F_BLOCK:
9519304Speter		if (!S_ISBLK(p->fts_statp->st_mode))
9619304Speter			goto typeerr;
9719304Speter		break;
9819304Speter	case F_CHAR:
9919304Speter		if (!S_ISCHR(p->fts_statp->st_mode))
10019304Speter			goto typeerr;
10119304Speter		break;
10219304Speter	case F_DIR:
10319304Speter		if (!S_ISDIR(p->fts_statp->st_mode))
10419304Speter			goto typeerr;
10519304Speter		break;
10619304Speter	case F_FIFO:
10719304Speter		if (!S_ISFIFO(p->fts_statp->st_mode))
10819304Speter			goto typeerr;
10919304Speter		break;
11019304Speter	case F_FILE:
11119304Speter		if (!S_ISREG(p->fts_statp->st_mode))
11219304Speter			goto typeerr;
11319304Speter		break;
11419304Speter	case F_LINK:
11519304Speter		if (!S_ISLNK(p->fts_statp->st_mode))
11619304Speter			goto typeerr;
11719304Speter		break;
11819304Speter	case F_SOCK:
11919304Speter		if (!S_ISSOCK(p->fts_statp->st_mode)) {
12019304Spetertypeerr:		LABEL;
12119304Speter			(void)printf("\ttype (%s, %s)\n",
12219304Speter			    ftype(s->type), inotype(p->fts_statp->st_mode));
12319304Speter		}
12419304Speter		break;
12519304Speter	}
12619304Speter	/* Set the uid/gid first, then set the mode. */
12719304Speter	if (s->flags & (F_UID | F_UNAME) && s->st_uid != p->fts_statp->st_uid) {
12819304Speter		LABEL;
12919304Speter		(void)printf("%suser (%lu, %lu",
13019304Speter		    tab, (u_long)s->st_uid, (u_long)p->fts_statp->st_uid);
13119304Speter		if (uflag)
13219304Speter			if (chown(p->fts_accpath, s->st_uid, -1))
13319304Speter				(void)printf(", not modified: %s)\n",
13419304Speter				    strerror(errno));
13519304Speter			else
13619304Speter				(void)printf(", modified)\n");
13719304Speter		else
13819304Speter			(void)printf(")\n");
139254225Speter		tab = "\t";
14019304Speter	}
14119304Speter	if (s->flags & (F_GID | F_GNAME) && s->st_gid != p->fts_statp->st_gid) {
14219304Speter		LABEL;
14319304Speter		(void)printf("%sgid (%lu, %lu",
14419304Speter		    tab, (u_long)s->st_gid, (u_long)p->fts_statp->st_gid);
14519304Speter		if (uflag)
14619304Speter			if (chown(p->fts_accpath, -1, s->st_gid))
14719304Speter				(void)printf(", not modified: %s)\n",
14819304Speter				    strerror(errno));
14919304Speter			else
15019304Speter				(void)printf(", modified)\n");
15119304Speter		else
15219304Speter			(void)printf(")\n");
15319304Speter		tab = "\t";
15419304Speter	}
15519304Speter	if (s->flags & F_MODE &&
15619304Speter	    s->st_mode != (p->fts_statp->st_mode & MBITS)) {
15719304Speter		LABEL;
15819304Speter		(void)printf("%spermissions (%#o, %#o",
15919304Speter		    tab, s->st_mode, p->fts_statp->st_mode & MBITS);
16019304Speter		if (uflag)
16119304Speter			if (chmod(p->fts_accpath, s->st_mode))
16219304Speter				(void)printf(", not modified: %s)\n",
16319304Speter				    strerror(errno));
16419304Speter			else
16519304Speter				(void)printf(", modified)\n");
16619304Speter		else
16719304Speter			(void)printf(")\n");
16819304Speter		tab = "\t";
16919304Speter	}
17019304Speter	if (s->flags & F_NLINK && s->type != F_DIR &&
17119304Speter	    s->st_nlink != p->fts_statp->st_nlink) {
17219304Speter		LABEL;
17319304Speter		(void)printf("%slink count (%u, %u)\n",
17419304Speter		    tab, s->st_nlink, p->fts_statp->st_nlink);
17519304Speter		tab = "\t";
17619304Speter	}
17719304Speter	if (s->flags & F_SIZE && s->st_size != p->fts_statp->st_size) {
17819304Speter		LABEL;
17919304Speter		(void)printf("%ssize (%qd, %qd)\n",
18019304Speter		    tab, s->st_size, p->fts_statp->st_size);
18119304Speter		tab = "\t";
18219304Speter	}
18319304Speter	/*
18419304Speter	 * XXX
18519304Speter	 * Catches nano-second differences, but doesn't display them.
18619304Speter	 */
18719304Speter	if ((s->flags & F_TIME) &&
18819304Speter	     ((s->st_mtimespec.tv_sec != p->fts_statp->st_mtimespec.tv_sec) ||
18919304Speter	     (s->st_mtimespec.tv_nsec != p->fts_statp->st_mtimespec.tv_nsec))) {
19019304Speter		LABEL;
19119304Speter		(void)printf("%smodification time (%.24s, ",
19219304Speter		    tab, ctime(&s->st_mtimespec.tv_sec));
19319304Speter		(void)printf("%.24s)\n",
19419304Speter		    ctime(&p->fts_statp->st_mtimespec.tv_sec));
19519304Speter		tab = "\t";
19619304Speter	}
19719304Speter	if (s->flags & F_CKSUM)
19819304Speter		if ((fd = open(p->fts_accpath, O_RDONLY, 0)) < 0) {
19919304Speter			LABEL;
20019304Speter			(void)printf("%scksum: %s: %s\n",
201254225Speter			    tab, p->fts_accpath, strerror(errno));
20219304Speter			tab = "\t";
20319304Speter		} else if (crc(fd, &val, &len)) {
20419304Speter			(void)close(fd);
20519304Speter			LABEL;
20619304Speter			(void)printf("%scksum: %s: %s\n",
20719304Speter			    tab, p->fts_accpath, strerror(errno));
20819304Speter			tab = "\t";
20919304Speter		} else {
21019304Speter			(void)close(fd);
21119304Speter			if (s->cksum != val) {
21219304Speter				LABEL;
21319304Speter				(void)printf("%scksum (%lu, %lu)\n",
21419304Speter				    tab, s->cksum, val);
21519304Speter			}
21619304Speter			tab = "\t";
21719304Speter		}
21819304Speter#ifdef MD5
21919304Speter	if (s->flags & F_MD5) {
22019304Speter		char *new_digest, buf[33];
22119304Speter
22219304Speter		new_digest = MD5File(p->fts_accpath, buf);
22319304Speter		if (!new_digest) {
22419304Speter			LABEL;
22519304Speter			printf("%sMD5File: %s: %s\n", tab, p->fts_accpath,
22619304Speter			       strerror(errno));
22719304Speter			tab = "\t";
22819304Speter		} else if (strcmp(new_digest, s->md5digest)) {
22919304Speter			LABEL;
23019304Speter			printf("%sMD5 (%s, %s)\n", tab, s->md5digest,
23119304Speter			       new_digest);
23219304Speter			tab = "\t";
23319304Speter		}
23419304Speter	}
23519304Speter#endif /* MD5 */
23619304Speter#ifdef SHA1
23719304Speter	if (s->flags & F_SHA1) {
23819304Speter		char *new_digest, buf[41];
23919304Speter
24019304Speter		new_digest = SHA1_File(p->fts_accpath, buf);
24119304Speter		if (!new_digest) {
24219304Speter			LABEL;
24319304Speter			printf("%sSHA1_File: %s: %s\n", tab, p->fts_accpath,
24419304Speter			       strerror(errno));
24519304Speter			tab = "\t";
24619304Speter		} else if (strcmp(new_digest, s->sha1digest)) {
24719304Speter			LABEL;
24819304Speter			printf("%sSHA-1 (%s, %s)\n", tab, s->sha1digest,
24919304Speter			       new_digest);
25019304Speter			tab = "\t";
25119304Speter		}
25219304Speter	}
25319304Speter#endif /* SHA1 */
25419304Speter#ifdef RMD160
25519304Speter	if (s->flags & F_RMD160) {
25619304Speter		char *new_digest, buf[41];
25719304Speter
25819304Speter		new_digest = RIPEMD160_File(p->fts_accpath, buf);
25919304Speter		if (!new_digest) {
26019304Speter			LABEL;
261254225Speter			printf("%sRIPEMD160_File: %s: %s\n", tab,
26219304Speter			       p->fts_accpath, strerror(errno));
26319304Speter			tab = "\t";
26419304Speter		} else if (strcmp(new_digest, s->rmd160digest)) {
26519304Speter			LABEL;
26619304Speter			printf("%sRIPEMD160 (%s, %s)\n", tab, s->rmd160digest,
26719304Speter			       new_digest);
26819304Speter			tab = "\t";
26919304Speter		}
27019304Speter	}
27119304Speter#endif /* RMD160 */
27219304Speter
27319304Speter	if (s->flags & F_SLINK && strcmp(cp = rlink(name), s->slink)) {
27419304Speter		LABEL;
27519304Speter		(void)printf("%slink ref (%s, %s)\n", tab, cp, s->slink);
27619304Speter	}
27719304Speter	return (label);
27819304Speter}
27919304Speter
28019304Speterchar *
28119304Speterinotype(type)
28219304Speter	u_int type;
28319304Speter{
284	switch(type & S_IFMT) {
285	case S_IFBLK:
286		return ("block");
287	case S_IFCHR:
288		return ("char");
289	case S_IFDIR:
290		return ("dir");
291	case S_IFIFO:
292		return ("fifo");
293	case S_IFREG:
294		return ("file");
295	case S_IFLNK:
296		return ("link");
297	case S_IFSOCK:
298		return ("socket");
299	default:
300		return ("unknown");
301	}
302	/* NOTREACHED */
303}
304
305static char *
306ftype(type)
307	u_int type;
308{
309	switch(type) {
310	case F_BLOCK:
311		return ("block");
312	case F_CHAR:
313		return ("char");
314	case F_DIR:
315		return ("dir");
316	case F_FIFO:
317		return ("fifo");
318	case F_FILE:
319		return ("file");
320	case F_LINK:
321		return ("link");
322	case F_SOCK:
323		return ("socket");
324	default:
325		return ("unknown");
326	}
327	/* NOTREACHED */
328}
329
330char *
331rlink(name)
332	char *name;
333{
334	static char lbuf[MAXPATHLEN];
335	register int len;
336
337	if ((len = readlink(name, lbuf, sizeof(lbuf) - 1)) == -1)
338		err(1, "line %d: %s", lineno, name);
339	lbuf[len] = '\0';
340	return (lbuf);
341}
342