compare.c revision 1553
1/*-
2 * Copyright (c) 1989, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
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. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35static char sccsid[] = "@(#)compare.c	8.1 (Berkeley) 6/6/93";
36#endif /* not lint */
37
38#include <sys/param.h>
39#include <sys/stat.h>
40#include <fcntl.h>
41#include <fts.h>
42#include <errno.h>
43#include <stdio.h>
44#include <time.h>
45#include <unistd.h>
46#include "mtree.h"
47#include "extern.h"
48
49extern int uflag;
50
51static char *ftype __P((u_int));
52
53#define	INDENTNAMELEN	8
54#define	LABEL \
55	if (!label++) { \
56		len = printf("%s: ", RP(p)); \
57		if (len > INDENTNAMELEN) { \
58			tab = "\t"; \
59			(void)printf("\n"); \
60		} else { \
61			tab = ""; \
62			(void)printf("%*s", INDENTNAMELEN - len, ""); \
63		} \
64	}
65
66int
67compare(name, s, p)
68	char *name;
69	register NODE *s;
70	register FTSENT *p;
71{
72	extern int uflag;
73	u_long len, val;
74	int fd, label;
75	char *cp, *tab;
76
77	label = 0;
78	switch(s->type) {
79	case F_BLOCK:
80		if (!S_ISBLK(p->fts_statp->st_mode))
81			goto typeerr;
82		break;
83	case F_CHAR:
84		if (!S_ISCHR(p->fts_statp->st_mode))
85			goto typeerr;
86		break;
87	case F_DIR:
88		if (!S_ISDIR(p->fts_statp->st_mode))
89			goto typeerr;
90		break;
91	case F_FIFO:
92		if (!S_ISFIFO(p->fts_statp->st_mode))
93			goto typeerr;
94		break;
95	case F_FILE:
96		if (!S_ISREG(p->fts_statp->st_mode))
97			goto typeerr;
98		break;
99	case F_LINK:
100		if (!S_ISLNK(p->fts_statp->st_mode))
101			goto typeerr;
102		break;
103	case F_SOCK:
104		if (!S_ISSOCK(p->fts_statp->st_mode)) {
105typeerr:		LABEL;
106			(void)printf("\ttype (%s, %s)\n",
107			    ftype(s->type), inotype(p->fts_statp->st_mode));
108		}
109		break;
110	}
111	/* Set the uid/gid first, then set the mode. */
112	if (s->flags & (F_UID | F_UNAME) && s->st_uid != p->fts_statp->st_uid) {
113		LABEL;
114		(void)printf("%suser (%u, %u",
115		    tab, s->st_uid, p->fts_statp->st_uid);
116		if (uflag)
117			if (chown(p->fts_accpath, s->st_uid, -1))
118				(void)printf(", not modified: %s)\n",
119				    strerror(errno));
120			else
121				(void)printf(", modified)\n");
122		else
123			(void)printf(")\n");
124		tab = "\t";
125	}
126	if (s->flags & (F_GID | F_GNAME) && s->st_gid != p->fts_statp->st_gid) {
127		LABEL;
128		(void)printf("%sgid (%u, %u",
129		    tab, s->st_gid, p->fts_statp->st_gid);
130		if (uflag)
131			if (chown(p->fts_accpath, -1, s->st_gid))
132				(void)printf(", not modified: %s)\n",
133				    strerror(errno));
134			else
135				(void)printf(", modified)\n");
136		else
137			(void)printf(")\n");
138		tab = "\t";
139	}
140	if (s->flags & F_MODE &&
141	    s->st_mode != (p->fts_statp->st_mode & MBITS)) {
142		LABEL;
143		(void)printf("%spermissions (%#o, %#o",
144		    tab, s->st_mode, p->fts_statp->st_mode & MBITS);
145		if (uflag)
146			if (chmod(p->fts_accpath, s->st_mode))
147				(void)printf(", not modified: %s)\n",
148				    strerror(errno));
149			else
150				(void)printf(", modified)\n");
151		else
152			(void)printf(")\n");
153		tab = "\t";
154	}
155	if (s->flags & F_NLINK && s->type != F_DIR &&
156	    s->st_nlink != p->fts_statp->st_nlink) {
157		LABEL;
158		(void)printf("%slink count (%u, %u)\n",
159		    tab, s->st_nlink, p->fts_statp->st_nlink);
160		tab = "\t";
161	}
162	if (s->flags & F_SIZE && s->st_size != p->fts_statp->st_size) {
163		LABEL;
164		(void)printf("%ssize (%qd, %qd)\n",
165		    tab, s->st_size, p->fts_statp->st_size);
166		tab = "\t";
167	}
168	/*
169	 * XXX
170	 * Catches nano-second differences, but doesn't display them.
171	 */
172	if (s->flags & F_TIME &&
173	    s->st_mtimespec.ts_sec != p->fts_statp->st_mtimespec.ts_sec ||
174	    s->st_mtimespec.ts_nsec != p->fts_statp->st_mtimespec.ts_nsec) {
175		LABEL;
176		(void)printf("%smodification time (%.24s, ",
177		    tab, ctime(&s->st_mtimespec.ts_sec));
178		(void)printf("%.24s)\n",
179		    ctime(&p->fts_statp->st_mtimespec.ts_sec));
180		tab = "\t";
181	}
182	if (s->flags & F_CKSUM)
183		if ((fd = open(p->fts_accpath, O_RDONLY, 0)) < 0) {
184			LABEL;
185			(void)printf("%scksum: %s: %s\n",
186			    tab, p->fts_accpath, strerror(errno));
187			tab = "\t";
188		} else if (crc(fd, &val, &len)) {
189			(void)close(fd);
190			LABEL;
191			(void)printf("%scksum: %s: %s\n",
192			    tab, p->fts_accpath, strerror(errno));
193			tab = "\t";
194		} else {
195			(void)close(fd);
196			if (s->cksum != val) {
197				LABEL;
198				(void)printf("%scksum (%lu, %lu)\n",
199				    tab, s->cksum, val);
200			}
201			tab = "\t";
202		}
203	if (s->flags & F_SLINK && strcmp(cp = rlink(name), s->slink)) {
204		LABEL;
205		(void)printf("%slink ref (%s, %s)\n", tab, cp, s->slink);
206	}
207	return (label);
208}
209
210char *
211inotype(type)
212	u_int type;
213{
214	switch(type & S_IFMT) {
215	case S_IFBLK:
216		return ("block");
217	case S_IFCHR:
218		return ("char");
219	case S_IFDIR:
220		return ("dir");
221	case S_IFIFO:
222		return ("fifo");
223	case S_IFREG:
224		return ("file");
225	case S_IFLNK:
226		return ("link");
227	case S_IFSOCK:
228		return ("socket");
229	default:
230		return ("unknown");
231	}
232	/* NOTREACHED */
233}
234
235static char *
236ftype(type)
237	u_int type;
238{
239	switch(type) {
240	case F_BLOCK:
241		return ("block");
242	case F_CHAR:
243		return ("char");
244	case F_DIR:
245		return ("dir");
246	case F_FIFO:
247		return ("fifo");
248	case F_FILE:
249		return ("file");
250	case F_LINK:
251		return ("link");
252	case F_SOCK:
253		return ("socket");
254	default:
255		return ("unknown");
256	}
257	/* NOTREACHED */
258}
259
260char *
261rlink(name)
262	char *name;
263{
264	static char lbuf[MAXPATHLEN];
265	register int len;
266
267	if ((len = readlink(name, lbuf, sizeof(lbuf))) == -1)
268		err("%s: %s", name, strerror(errno));
269	lbuf[len] = '\0';
270	return (lbuf);
271}
272