2 * Copyright (c) 2003 Poul-Henning Kamp
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
39 #define FF(a, b, c, d) \
40 (((a)->flags & (c)) && ((b)->flags & (c)) && ((a)->d) != ((b)->d))
41 #define FS(a, b, c, d) \
42 (((a)->flags & (c)) && ((b)->flags & (c)) && strcmp((a)->d,(b)->d))
43 #define FM(a, b, c, d) \
44 (((a)->flags & (c)) && ((b)->flags & (c)) && memcmp(&(a)->d,&(b)->d, sizeof (a)->d))
47 shownode(NODE *n, int f, char const *path)
52 printf("%s%s %s", path, n->name, ftype(n->type));
54 printf(" cksum=%lu", n->cksum);
56 printf(" gid=%d", n->st_gid);
58 gr = getgrgid(n->st_gid);
60 printf(" gid=%d", n->st_gid);
62 printf(" gname=%s", gr->gr_name);
65 printf(" mode=%o", n->st_mode);
67 printf(" nlink=%d", n->st_nlink);
69 printf(" size=%jd", (intmax_t)n->st_size);
71 printf(" uid=%d", n->st_uid);
73 pw = getpwuid(n->st_uid);
75 printf(" uid=%d", n->st_uid);
77 printf(" uname=%s", pw->pw_name);
80 printf(" md5digest=%s", n->md5digest);
82 printf(" sha1digest=%s", n->sha1digest);
84 printf(" rmd160digest=%s", n->rmd160digest);
86 printf(" sha256digest=%s", n->sha256digest);
88 printf(" flags=%s", flags_to_string(n->st_flags));
93 mismatch(NODE *n1, NODE *n2, int differ, char const *path)
97 shownode(n1, differ, path);
102 shownode(n2, differ, path);
105 if (!(differ & keys))
108 shownode(n1, differ, path);
110 shownode(n2, differ, path);
115 compare_nodes(NODE *n1, NODE *n2, char const *path)
119 if (n1 != NULL && n1->type == F_LINK)
120 n1->flags &= ~F_MODE;
121 if (n2 != NULL && n2->type == F_LINK)
122 n2->flags &= ~F_MODE;
124 if (n1 == NULL && n2 != NULL) {
126 mismatch(n1, n2, differs, path);
129 if (n1 != NULL && n2 == NULL) {
131 mismatch(n1, n2, differs, path);
134 if (n1->type != n2->type) {
136 mismatch(n1, n2, differs, path);
139 if (FF(n1, n2, F_CKSUM, cksum))
141 if (FF(n1, n2, F_GID, st_gid))
143 if (FF(n1, n2, F_GNAME, st_gid))
145 if (FF(n1, n2, F_MODE, st_mode))
147 if (FF(n1, n2, F_NLINK, st_nlink))
149 if (FF(n1, n2, F_SIZE, st_size))
151 if (FS(n1, n2, F_SLINK, slink))
153 if (FM(n1, n2, F_TIME, st_mtimespec))
155 if (FF(n1, n2, F_UID, st_uid))
157 if (FF(n1, n2, F_UNAME, st_uid))
159 if (FS(n1, n2, F_MD5, md5digest))
161 if (FS(n1, n2, F_SHA1, sha1digest))
163 if (FS(n1, n2, F_RMD160, rmd160digest))
165 if (FS(n1, n2, F_SHA256, sha256digest))
167 if (FF(n1, n2, F_FLAGS, st_flags))
170 mismatch(n1, n2, differs, path);
176 walk_in_the_forest(NODE *t1, NODE *t2, char const *path)
179 NODE *c1, *c2, *n1, *n2;
192 while (c1 != NULL || c2 != NULL) {
198 if (c1 != NULL && c2 != NULL) {
199 if (c1->type != F_DIR && c2->type == F_DIR) {
202 } else if (c1->type == F_DIR && c2->type != F_DIR) {
206 i = strcmp(c1->name, c2->name);
216 if (c1 == NULL && c2->type == F_DIR) {
217 asprintf(&np, "%s%s/", path, c2->name);
218 i = walk_in_the_forest(c1, c2, np);
220 i += compare_nodes(c1, c2, path);
221 } else if (c2 == NULL && c1->type == F_DIR) {
222 asprintf(&np, "%s%s/", path, c1->name);
223 i = walk_in_the_forest(c1, c2, np);
225 i += compare_nodes(c1, c2, path);
226 } else if (c1 == NULL || c2 == NULL) {
227 i = compare_nodes(c1, c2, path);
228 } else if (c1->type == F_DIR && c2->type == F_DIR) {
229 asprintf(&np, "%s%s/", path, c1->name);
230 i = walk_in_the_forest(c1, c2, np);
232 i += compare_nodes(c1, c2, path);
234 i = compare_nodes(c1, c2, path);
244 mtree_specspec(FILE *fi, FILE *fj)
249 root1 = mtree_readspec(fi);
250 root2 = mtree_readspec(fj);
251 rval = walk_in_the_forest(root1, root2, "");
252 rval += compare_nodes(root1, root2, "");
254 return (MISMATCHEXIT);