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