xref: /freebsd-src/contrib/mtree/specspec.c (revision c6ec7d31830ab1c80edae95ad5e4b9dba10c47ac)
1*c6ec7d31SBrooks Davis /*	$NetBSD: specspec.c,v 1.2 2012/10/05 01:27:29 christos Exp $	*/
2*c6ec7d31SBrooks Davis 
3*c6ec7d31SBrooks Davis /*-
4*c6ec7d31SBrooks Davis  * Copyright (c) 2003 Poul-Henning Kamp
5*c6ec7d31SBrooks Davis  * All rights reserved.
6*c6ec7d31SBrooks Davis  *
7*c6ec7d31SBrooks Davis  * Redistribution and use in source and binary forms, with or without
8*c6ec7d31SBrooks Davis  * modification, are permitted provided that the following conditions
9*c6ec7d31SBrooks Davis  * are met:
10*c6ec7d31SBrooks Davis  * 1. Redistributions of source code must retain the above copyright
11*c6ec7d31SBrooks Davis  *    notice, this list of conditions and the following disclaimer.
12*c6ec7d31SBrooks Davis  * 2. Redistributions in binary form must reproduce the above copyright
13*c6ec7d31SBrooks Davis  *    notice, this list of conditions and the following disclaimer in the
14*c6ec7d31SBrooks Davis  *    documentation and/or other materials provided with the distribution.
15*c6ec7d31SBrooks Davis  *
16*c6ec7d31SBrooks Davis  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17*c6ec7d31SBrooks Davis  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*c6ec7d31SBrooks Davis  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*c6ec7d31SBrooks Davis  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20*c6ec7d31SBrooks Davis  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21*c6ec7d31SBrooks Davis  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22*c6ec7d31SBrooks Davis  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23*c6ec7d31SBrooks Davis  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24*c6ec7d31SBrooks Davis  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25*c6ec7d31SBrooks Davis  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*c6ec7d31SBrooks Davis  * SUCH DAMAGE.
27*c6ec7d31SBrooks Davis  */
28*c6ec7d31SBrooks Davis 
29*c6ec7d31SBrooks Davis #if HAVE_NBTOOL_CONFIG_H
30*c6ec7d31SBrooks Davis #include "nbtool_config.h"
31*c6ec7d31SBrooks Davis #endif
32*c6ec7d31SBrooks Davis 
33*c6ec7d31SBrooks Davis #include <sys/cdefs.h>
34*c6ec7d31SBrooks Davis __RCSID("$NetBSD: specspec.c,v 1.2 2012/10/05 01:27:29 christos Exp $");
35*c6ec7d31SBrooks Davis 
36*c6ec7d31SBrooks Davis #include <err.h>
37*c6ec7d31SBrooks Davis #include <grp.h>
38*c6ec7d31SBrooks Davis #include <pwd.h>
39*c6ec7d31SBrooks Davis #include <time.h>
40*c6ec7d31SBrooks Davis #include <stdio.h>
41*c6ec7d31SBrooks Davis #include <stdint.h>
42*c6ec7d31SBrooks Davis #include <stdlib.h>
43*c6ec7d31SBrooks Davis #include <string.h>
44*c6ec7d31SBrooks Davis #include <unistd.h>
45*c6ec7d31SBrooks Davis #include "mtree.h"
46*c6ec7d31SBrooks Davis #include "extern.h"
47*c6ec7d31SBrooks Davis 
48*c6ec7d31SBrooks Davis #define FF(a, b, c, d) \
49*c6ec7d31SBrooks Davis 	(((a)->flags & (c)) && ((b)->flags & (c)) && ((a)->d) != ((b)->d))
50*c6ec7d31SBrooks Davis #define FS(a, b, c, d) \
51*c6ec7d31SBrooks Davis 	(((a)->flags & (c)) && ((b)->flags & (c)) && strcmp((a)->d,(b)->d))
52*c6ec7d31SBrooks Davis #define FM(a, b, c, d) \
53*c6ec7d31SBrooks Davis 	(((a)->flags & (c)) && ((b)->flags & (c)) && memcmp(&(a)->d,&(b)->d, sizeof (a)->d))
54*c6ec7d31SBrooks Davis 
55*c6ec7d31SBrooks Davis static void
56*c6ec7d31SBrooks Davis shownode(NODE *n, int f, char const *path)
57*c6ec7d31SBrooks Davis {
58*c6ec7d31SBrooks Davis 	struct group *gr;
59*c6ec7d31SBrooks Davis 	struct passwd *pw;
60*c6ec7d31SBrooks Davis 
61*c6ec7d31SBrooks Davis 	printf("%s%s %s", path, n->name, inotype(nodetoino(n->type)));
62*c6ec7d31SBrooks Davis 	if (f & F_CKSUM)
63*c6ec7d31SBrooks Davis 		printf(" cksum=%lu", n->cksum);
64*c6ec7d31SBrooks Davis 	if (f & F_GID)
65*c6ec7d31SBrooks Davis 		printf(" gid=%d", n->st_gid);
66*c6ec7d31SBrooks Davis 	if (f & F_GNAME) {
67*c6ec7d31SBrooks Davis 		gr = getgrgid(n->st_gid);
68*c6ec7d31SBrooks Davis 		if (gr == NULL)
69*c6ec7d31SBrooks Davis 			printf(" gid=%d", n->st_gid);
70*c6ec7d31SBrooks Davis 		else
71*c6ec7d31SBrooks Davis 			printf(" gname=%s", gr->gr_name);
72*c6ec7d31SBrooks Davis 	}
73*c6ec7d31SBrooks Davis 	if (f & F_MODE)
74*c6ec7d31SBrooks Davis 		printf(" mode=%o", n->st_mode);
75*c6ec7d31SBrooks Davis 	if (f & F_NLINK)
76*c6ec7d31SBrooks Davis 		printf(" nlink=%d", n->st_nlink);
77*c6ec7d31SBrooks Davis 	if (f & F_SIZE)
78*c6ec7d31SBrooks Davis 		printf(" size=%jd", (intmax_t)n->st_size);
79*c6ec7d31SBrooks Davis 	if (f & F_UID)
80*c6ec7d31SBrooks Davis 		printf(" uid=%d", n->st_uid);
81*c6ec7d31SBrooks Davis 	if (f & F_UNAME) {
82*c6ec7d31SBrooks Davis 		pw = getpwuid(n->st_uid);
83*c6ec7d31SBrooks Davis 		if (pw == NULL)
84*c6ec7d31SBrooks Davis 			printf(" uid=%d", n->st_uid);
85*c6ec7d31SBrooks Davis 		else
86*c6ec7d31SBrooks Davis 			printf(" uname=%s", pw->pw_name);
87*c6ec7d31SBrooks Davis 	}
88*c6ec7d31SBrooks Davis 	if (f & F_MD5)
89*c6ec7d31SBrooks Davis 		printf(" %s=%s", MD5KEY, n->md5digest);
90*c6ec7d31SBrooks Davis 	if (f & F_SHA1)
91*c6ec7d31SBrooks Davis 		printf(" %s=%s", SHA1KEY, n->sha1digest);
92*c6ec7d31SBrooks Davis 	if (f & F_RMD160)
93*c6ec7d31SBrooks Davis 		printf(" %s=%s", RMD160KEY, n->rmd160digest);
94*c6ec7d31SBrooks Davis 	if (f & F_SHA256)
95*c6ec7d31SBrooks Davis 		printf(" %s=%s", SHA256KEY, n->sha256digest);
96*c6ec7d31SBrooks Davis 	if (f & F_SHA384)
97*c6ec7d31SBrooks Davis 		printf(" %s=%s", SHA384KEY, n->sha384digest);
98*c6ec7d31SBrooks Davis 	if (f & F_SHA512)
99*c6ec7d31SBrooks Davis 		printf(" %s=%s", SHA512KEY, n->sha512digest);
100*c6ec7d31SBrooks Davis 	if (f & F_FLAGS)
101*c6ec7d31SBrooks Davis 		printf(" flags=%s", flags_to_string(n->st_flags, "none"));
102*c6ec7d31SBrooks Davis 	printf("\n");
103*c6ec7d31SBrooks Davis }
104*c6ec7d31SBrooks Davis 
105*c6ec7d31SBrooks Davis static int
106*c6ec7d31SBrooks Davis mismatch(NODE *n1, NODE *n2, int differ, char const *path)
107*c6ec7d31SBrooks Davis {
108*c6ec7d31SBrooks Davis 
109*c6ec7d31SBrooks Davis 	if (n2 == NULL) {
110*c6ec7d31SBrooks Davis 		shownode(n1, differ, path);
111*c6ec7d31SBrooks Davis 		return (1);
112*c6ec7d31SBrooks Davis 	}
113*c6ec7d31SBrooks Davis 	if (n1 == NULL) {
114*c6ec7d31SBrooks Davis 		printf("\t");
115*c6ec7d31SBrooks Davis 		shownode(n2, differ, path);
116*c6ec7d31SBrooks Davis 		return (1);
117*c6ec7d31SBrooks Davis 	}
118*c6ec7d31SBrooks Davis 	if (!(differ & keys))
119*c6ec7d31SBrooks Davis 		return(0);
120*c6ec7d31SBrooks Davis 	printf("\t\t");
121*c6ec7d31SBrooks Davis 	shownode(n1, differ, path);
122*c6ec7d31SBrooks Davis 	printf("\t\t");
123*c6ec7d31SBrooks Davis 	shownode(n2, differ, path);
124*c6ec7d31SBrooks Davis 	return (1);
125*c6ec7d31SBrooks Davis }
126*c6ec7d31SBrooks Davis 
127*c6ec7d31SBrooks Davis static int
128*c6ec7d31SBrooks Davis compare_nodes(NODE *n1, NODE *n2, char const *path)
129*c6ec7d31SBrooks Davis {
130*c6ec7d31SBrooks Davis 	int differs;
131*c6ec7d31SBrooks Davis 
132*c6ec7d31SBrooks Davis 	if (n1 != NULL && n1->type == F_LINK)
133*c6ec7d31SBrooks Davis 		n1->flags &= ~F_MODE;
134*c6ec7d31SBrooks Davis 	if (n2 != NULL && n2->type == F_LINK)
135*c6ec7d31SBrooks Davis 		n2->flags &= ~F_MODE;
136*c6ec7d31SBrooks Davis 	differs = 0;
137*c6ec7d31SBrooks Davis 	if (n1 == NULL && n2 != NULL) {
138*c6ec7d31SBrooks Davis 		differs = n2->flags;
139*c6ec7d31SBrooks Davis 		mismatch(n1, n2, differs, path);
140*c6ec7d31SBrooks Davis 		return (1);
141*c6ec7d31SBrooks Davis 	}
142*c6ec7d31SBrooks Davis 	if (n1 != NULL && n2 == NULL) {
143*c6ec7d31SBrooks Davis 		differs = n1->flags;
144*c6ec7d31SBrooks Davis 		mismatch(n1, n2, differs, path);
145*c6ec7d31SBrooks Davis 		return (1);
146*c6ec7d31SBrooks Davis 	}
147*c6ec7d31SBrooks Davis 	if (n1->type != n2->type) {
148*c6ec7d31SBrooks Davis 		differs = 0;
149*c6ec7d31SBrooks Davis 		mismatch(n1, n2, differs, path);
150*c6ec7d31SBrooks Davis 		return (1);
151*c6ec7d31SBrooks Davis 	}
152*c6ec7d31SBrooks Davis 	if (FF(n1, n2, F_CKSUM, cksum))
153*c6ec7d31SBrooks Davis 		differs |= F_CKSUM;
154*c6ec7d31SBrooks Davis 	if (FF(n1, n2, F_GID, st_gid))
155*c6ec7d31SBrooks Davis 		differs |= F_GID;
156*c6ec7d31SBrooks Davis 	if (FF(n1, n2, F_GNAME, st_gid))
157*c6ec7d31SBrooks Davis 		differs |= F_GNAME;
158*c6ec7d31SBrooks Davis 	if (FF(n1, n2, F_MODE, st_mode))
159*c6ec7d31SBrooks Davis 		differs |= F_MODE;
160*c6ec7d31SBrooks Davis 	if (FF(n1, n2, F_NLINK, st_nlink))
161*c6ec7d31SBrooks Davis 		differs |= F_NLINK;
162*c6ec7d31SBrooks Davis 	if (FF(n1, n2, F_SIZE, st_size))
163*c6ec7d31SBrooks Davis 		differs |= F_SIZE;
164*c6ec7d31SBrooks Davis 	if (FS(n1, n2, F_SLINK, slink))
165*c6ec7d31SBrooks Davis 		differs |= F_SLINK;
166*c6ec7d31SBrooks Davis 	if (FM(n1, n2, F_TIME, st_mtimespec))
167*c6ec7d31SBrooks Davis 		differs |= F_TIME;
168*c6ec7d31SBrooks Davis 	if (FF(n1, n2, F_UID, st_uid))
169*c6ec7d31SBrooks Davis 		differs |= F_UID;
170*c6ec7d31SBrooks Davis 	if (FF(n1, n2, F_UNAME, st_uid))
171*c6ec7d31SBrooks Davis 		differs |= F_UNAME;
172*c6ec7d31SBrooks Davis 	if (FS(n1, n2, F_MD5, md5digest))
173*c6ec7d31SBrooks Davis 		differs |= F_MD5;
174*c6ec7d31SBrooks Davis 	if (FS(n1, n2, F_SHA1, sha1digest))
175*c6ec7d31SBrooks Davis 		differs |= F_SHA1;
176*c6ec7d31SBrooks Davis 	if (FS(n1, n2, F_RMD160, rmd160digest))
177*c6ec7d31SBrooks Davis 		differs |= F_RMD160;
178*c6ec7d31SBrooks Davis 	if (FS(n1, n2, F_SHA256, sha256digest))
179*c6ec7d31SBrooks Davis 		differs |= F_SHA256;
180*c6ec7d31SBrooks Davis 	if (FS(n1, n2, F_SHA384, sha384digest))
181*c6ec7d31SBrooks Davis 		differs |= F_SHA384;
182*c6ec7d31SBrooks Davis 	if (FS(n1, n2, F_SHA512, sha512digest))
183*c6ec7d31SBrooks Davis 		differs |= F_SHA512;
184*c6ec7d31SBrooks Davis 	if (FF(n1, n2, F_FLAGS, st_flags))
185*c6ec7d31SBrooks Davis 		differs |= F_FLAGS;
186*c6ec7d31SBrooks Davis 	if (differs) {
187*c6ec7d31SBrooks Davis 		mismatch(n1, n2, differs, path);
188*c6ec7d31SBrooks Davis 		return (1);
189*c6ec7d31SBrooks Davis 	}
190*c6ec7d31SBrooks Davis 	return (0);
191*c6ec7d31SBrooks Davis }
192*c6ec7d31SBrooks Davis static int
193*c6ec7d31SBrooks Davis walk_in_the_forest(NODE *t1, NODE *t2, char const *path)
194*c6ec7d31SBrooks Davis {
195*c6ec7d31SBrooks Davis 	int r, i;
196*c6ec7d31SBrooks Davis 	NODE *c1, *c2, *n1, *n2;
197*c6ec7d31SBrooks Davis 	char *np;
198*c6ec7d31SBrooks Davis 
199*c6ec7d31SBrooks Davis 	r = 0;
200*c6ec7d31SBrooks Davis 
201*c6ec7d31SBrooks Davis 	if (t1 != NULL)
202*c6ec7d31SBrooks Davis 		c1 = t1->child;
203*c6ec7d31SBrooks Davis 	else
204*c6ec7d31SBrooks Davis 		c1 = NULL;
205*c6ec7d31SBrooks Davis 	if (t2 != NULL)
206*c6ec7d31SBrooks Davis 		c2 = t2->child;
207*c6ec7d31SBrooks Davis 	else
208*c6ec7d31SBrooks Davis 		c2 = NULL;
209*c6ec7d31SBrooks Davis 	while (c1 != NULL || c2 != NULL) {
210*c6ec7d31SBrooks Davis 		n1 = n2 = NULL;
211*c6ec7d31SBrooks Davis 		if (c1 != NULL)
212*c6ec7d31SBrooks Davis 			n1 = c1->next;
213*c6ec7d31SBrooks Davis 		if (c2 != NULL)
214*c6ec7d31SBrooks Davis 			n2 = c2->next;
215*c6ec7d31SBrooks Davis 		if (c1 != NULL && c2 != NULL) {
216*c6ec7d31SBrooks Davis 			if (c1->type != F_DIR && c2->type == F_DIR) {
217*c6ec7d31SBrooks Davis 				n2 = c2;
218*c6ec7d31SBrooks Davis 				c2 = NULL;
219*c6ec7d31SBrooks Davis 			} else if (c1->type == F_DIR && c2->type != F_DIR) {
220*c6ec7d31SBrooks Davis 				n1 = c1;
221*c6ec7d31SBrooks Davis 				c1 = NULL;
222*c6ec7d31SBrooks Davis 			} else {
223*c6ec7d31SBrooks Davis 				i = strcmp(c1->name, c2->name);
224*c6ec7d31SBrooks Davis 				if (i > 0) {
225*c6ec7d31SBrooks Davis 					n1 = c1;
226*c6ec7d31SBrooks Davis 					c1 = NULL;
227*c6ec7d31SBrooks Davis 				} else if (i < 0) {
228*c6ec7d31SBrooks Davis 					n2 = c2;
229*c6ec7d31SBrooks Davis 					c2 = NULL;
230*c6ec7d31SBrooks Davis 				}
231*c6ec7d31SBrooks Davis 			}
232*c6ec7d31SBrooks Davis 		}
233*c6ec7d31SBrooks Davis 		if (c1 == NULL && c2->type == F_DIR) {
234*c6ec7d31SBrooks Davis 			asprintf(&np, "%s%s/", path, c2->name);
235*c6ec7d31SBrooks Davis 			i = walk_in_the_forest(c1, c2, np);
236*c6ec7d31SBrooks Davis 			free(np);
237*c6ec7d31SBrooks Davis 			i += compare_nodes(c1, c2, path);
238*c6ec7d31SBrooks Davis 		} else if (c2 == NULL && c1->type == F_DIR) {
239*c6ec7d31SBrooks Davis 			asprintf(&np, "%s%s/", path, c1->name);
240*c6ec7d31SBrooks Davis 			i = walk_in_the_forest(c1, c2, np);
241*c6ec7d31SBrooks Davis 			free(np);
242*c6ec7d31SBrooks Davis 			i += compare_nodes(c1, c2, path);
243*c6ec7d31SBrooks Davis 		} else if (c1 == NULL || c2 == NULL) {
244*c6ec7d31SBrooks Davis 			i = compare_nodes(c1, c2, path);
245*c6ec7d31SBrooks Davis 		} else if (c1->type == F_DIR && c2->type == F_DIR) {
246*c6ec7d31SBrooks Davis 			asprintf(&np, "%s%s/", path, c1->name);
247*c6ec7d31SBrooks Davis 			i = walk_in_the_forest(c1, c2, np);
248*c6ec7d31SBrooks Davis 			free(np);
249*c6ec7d31SBrooks Davis 			i += compare_nodes(c1, c2, path);
250*c6ec7d31SBrooks Davis 		} else {
251*c6ec7d31SBrooks Davis 			i = compare_nodes(c1, c2, path);
252*c6ec7d31SBrooks Davis 		}
253*c6ec7d31SBrooks Davis 		r += i;
254*c6ec7d31SBrooks Davis 		c1 = n1;
255*c6ec7d31SBrooks Davis 		c2 = n2;
256*c6ec7d31SBrooks Davis 	}
257*c6ec7d31SBrooks Davis 	return (r);
258*c6ec7d31SBrooks Davis }
259*c6ec7d31SBrooks Davis 
260*c6ec7d31SBrooks Davis int
261*c6ec7d31SBrooks Davis mtree_specspec(FILE *fi, FILE *fj)
262*c6ec7d31SBrooks Davis {
263*c6ec7d31SBrooks Davis 	int rval;
264*c6ec7d31SBrooks Davis 	NODE *root1, *root2;
265*c6ec7d31SBrooks Davis 
266*c6ec7d31SBrooks Davis 	root1 = spec(fi);
267*c6ec7d31SBrooks Davis 	root2 = spec(fj);
268*c6ec7d31SBrooks Davis 	rval = walk_in_the_forest(root1, root2, "");
269*c6ec7d31SBrooks Davis 	rval += compare_nodes(root1, root2, "");
270*c6ec7d31SBrooks Davis 	if (rval > 0)
271*c6ec7d31SBrooks Davis 		return (MISMATCHEXIT);
272*c6ec7d31SBrooks Davis 	return (0);
273*c6ec7d31SBrooks Davis }
274