xref: /original-bsd/usr.sbin/mtree/compare.c (revision caa496f3)
1 /*-
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)compare.c	5.7 (Berkeley) 05/25/90";
10 #endif /* not lint */
11 
12 #include <sys/param.h>
13 #include <sys/stat.h>
14 #include <fts.h>
15 #include <errno.h>
16 #include <stdio.h>
17 #include <time.h>
18 #include "mtree.h"
19 
20 #define	LABEL \
21 	if (!label++) \
22 		(void)printf("%s: ", RP(p)); \
23 
24 compare(name, s, p)
25 	char *name;
26 	register NODE *s;
27 	register FTSENT *p;
28 {
29 	extern int exitval, uflag;
30 	int label;
31 	char *ftype(), *inotype(), *rlink();
32 
33 	label = 0;
34 	switch(s->type) {
35 	case F_BLOCK:
36 		if (!S_ISBLK(p->fts_statb.st_mode))
37 			goto typeerr;
38 		break;
39 	case F_CHAR:
40 		if (!S_ISCHR(p->fts_statb.st_mode))
41 			goto typeerr;
42 		break;
43 	case F_DIR:
44 		if (!S_ISDIR(p->fts_statb.st_mode))
45 			goto typeerr;
46 		break;
47 	case F_FIFO:
48 		if (!S_ISFIFO(p->fts_statb.st_mode))
49 			goto typeerr;
50 		break;
51 	case F_FILE:
52 		if (!S_ISREG(p->fts_statb.st_mode))
53 			goto typeerr;
54 		break;
55 	case F_LINK:
56 		if (!S_ISLNK(p->fts_statb.st_mode))
57 			goto typeerr;
58 		break;
59 	case F_SOCK:
60 		if (!S_ISFIFO(p->fts_statb.st_mode)) {
61 typeerr:		LABEL;
62 			(void)printf("\n\ttype (%s, %s)",
63 			    ftype(s->type), inotype(p->fts_statb.st_mode));
64 		}
65 		break;
66 	}
67 	if (s->flags & F_MODE && s->st_mode != (p->fts_statb.st_mode & MBITS)) {
68 		LABEL;
69 		(void)printf("\n\tpermissions (%#o, %#o%s",
70 		    s->st_mode, p->fts_statb.st_mode & MBITS, uflag ? "" : ")");
71 		if (uflag)
72 			if (chmod(p->fts_accpath, s->st_mode))
73 				(void)printf(", not modified: %s)",
74 				    strerror(errno));
75 			else
76 				(void)printf(", modified)");
77 	}
78 	if (s->flags & F_OWNER && s->st_uid != p->fts_statb.st_uid) {
79 		LABEL;
80 		(void)printf("\n\towner (%u, %u%s",
81 		    s->st_uid, p->fts_statb.st_uid, uflag ? "" : ")");
82 		if (uflag)
83 			if (chown(p->fts_accpath, s->st_uid, -1))
84 				(void)printf(", not modified: %s)",
85 				    strerror(errno));
86 			else
87 				(void)printf(", modified)");
88 	}
89 	if (s->flags & F_GROUP && s->st_gid != p->fts_statb.st_gid) {
90 		LABEL;
91 		(void)printf("\n\tgroup (%u, %u%s",
92 		    s->st_gid, p->fts_statb.st_gid, uflag ? "" : ")");
93 		if (uflag)
94 			if (chown(p->fts_accpath, -1, s->st_gid))
95 				(void)printf(", not modified: %s)",
96 				    strerror(errno));
97 			else
98 				(void)printf(", modified)");
99 	}
100 	if (s->flags & F_NLINK && s->type != F_DIR &&
101 	    s->st_nlink != p->fts_statb.st_nlink) {
102 		LABEL;
103 		(void)printf("\n\tlink count (%u, %u)",
104 		    s->st_nlink, p->fts_statb.st_nlink);
105 	}
106 	if (s->flags & F_SIZE && s->st_size != p->fts_statb.st_size) {
107 		LABEL;
108 		(void)printf("\n\tsize (%ld, %ld)",
109 		    s->st_size, p->fts_statb.st_size);
110 	}
111 	if (s->flags & F_SLINK) {
112 		char *cp;
113 
114 		if (strcmp(cp = rlink(name), s->slink)) {
115 			LABEL;
116 			(void)printf("\n\tlink ref (%s, %s)", cp, s->slink);
117 		}
118 	}
119 	if (s->flags & F_TIME && s->st_mtime != p->fts_statb.st_mtime) {
120 		LABEL;
121 		(void)printf("\n\tmodification time (%.24s, ",
122 		    ctime(&s->st_mtime));
123 		(void)printf("%.24s)", ctime(&p->fts_statb.st_mtime));
124 	}
125 	if (label) {
126 		exitval = 2;
127 		putchar('\n');
128 	}
129 }
130 
131 char *
132 inotype(type)
133 	mode_t type;
134 {
135 	switch(type & S_IFMT) {
136 	case S_IFBLK:
137 		return("block");
138 	case S_IFCHR:
139 		return("char");
140 	case S_IFDIR:
141 		return("dir");
142 	case S_IFREG:
143 		return("file");
144 	case S_IFLNK:
145 		return("link");
146 	case S_IFSOCK:
147 		return("socket");
148 	default:
149 		return("unknown");
150 	}
151 	/* NOTREACHED */
152 }
153 
154 char *
155 ftype(type)
156 	u_int type;
157 {
158 	switch(type) {
159 	case F_BLOCK:
160 		return("block");
161 	case F_CHAR:
162 		return("char");
163 	case F_DIR:
164 		return("dir");
165 	case F_FIFO:
166 		return("fifo");
167 	case F_FILE:
168 		return("file");
169 	case F_LINK:
170 		return("link");
171 	case F_SOCK:
172 		return("socket");
173 	default:
174 		return("unknown");
175 	}
176 	/* NOTREACHED */
177 }
178 
179 char *
180 rlink(name)
181 	char *name;
182 {
183 	register int len;
184 	static char lbuf[MAXPATHLEN];
185 
186 	len = readlink(name, lbuf, sizeof(lbuf));
187 	if (len == -1) {
188 		(void)fprintf(stderr, "mtree: %s: %s.\n",
189 		    name, strerror(errno));
190 		exit(1);
191 	}
192 	lbuf[len] = '\0';
193 	return(lbuf);
194 }
195