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