1244541Sbrooks/* $NetBSD: specspec.c,v 1.2 2012/10/05 01:27:29 christos Exp $ */ 2244541Sbrooks 3244541Sbrooks/*- 4244541Sbrooks * Copyright (c) 2003 Poul-Henning Kamp 5244541Sbrooks * All rights reserved. 6244541Sbrooks * 7244541Sbrooks * Redistribution and use in source and binary forms, with or without 8244541Sbrooks * modification, are permitted provided that the following conditions 9244541Sbrooks * are met: 10244541Sbrooks * 1. Redistributions of source code must retain the above copyright 11244541Sbrooks * notice, this list of conditions and the following disclaimer. 12244541Sbrooks * 2. Redistributions in binary form must reproduce the above copyright 13244541Sbrooks * notice, this list of conditions and the following disclaimer in the 14244541Sbrooks * documentation and/or other materials provided with the distribution. 15244541Sbrooks * 16244541Sbrooks * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17244541Sbrooks * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18244541Sbrooks * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19244541Sbrooks * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20244541Sbrooks * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21244541Sbrooks * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22244541Sbrooks * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23244541Sbrooks * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24244541Sbrooks * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25244541Sbrooks * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26244541Sbrooks * SUCH DAMAGE. 27244541Sbrooks */ 28244541Sbrooks 29244541Sbrooks#if HAVE_NBTOOL_CONFIG_H 30244541Sbrooks#include "nbtool_config.h" 31244541Sbrooks#endif 32244541Sbrooks 33244541Sbrooks#include <sys/cdefs.h> 34244541Sbrooks__RCSID("$NetBSD: specspec.c,v 1.2 2012/10/05 01:27:29 christos Exp $"); 35244541Sbrooks 36244541Sbrooks#include <err.h> 37244541Sbrooks#include <grp.h> 38244541Sbrooks#include <pwd.h> 39244541Sbrooks#include <time.h> 40244541Sbrooks#include <stdio.h> 41244541Sbrooks#include <stdint.h> 42244541Sbrooks#include <stdlib.h> 43244541Sbrooks#include <string.h> 44244541Sbrooks#include <unistd.h> 45244541Sbrooks#include "mtree.h" 46244541Sbrooks#include "extern.h" 47244541Sbrooks 48244541Sbrooks#define FF(a, b, c, d) \ 49244541Sbrooks (((a)->flags & (c)) && ((b)->flags & (c)) && ((a)->d) != ((b)->d)) 50244541Sbrooks#define FS(a, b, c, d) \ 51244541Sbrooks (((a)->flags & (c)) && ((b)->flags & (c)) && strcmp((a)->d,(b)->d)) 52244541Sbrooks#define FM(a, b, c, d) \ 53244541Sbrooks (((a)->flags & (c)) && ((b)->flags & (c)) && memcmp(&(a)->d,&(b)->d, sizeof (a)->d)) 54244541Sbrooks 55244541Sbrooksstatic void 56244541Sbrooksshownode(NODE *n, int f, char const *path) 57244541Sbrooks{ 58244541Sbrooks struct group *gr; 59244541Sbrooks struct passwd *pw; 60244541Sbrooks 61244541Sbrooks printf("%s%s %s", path, n->name, inotype(nodetoino(n->type))); 62244541Sbrooks if (f & F_CKSUM) 63244541Sbrooks printf(" cksum=%lu", n->cksum); 64244541Sbrooks if (f & F_GID) 65244541Sbrooks printf(" gid=%d", n->st_gid); 66244541Sbrooks if (f & F_GNAME) { 67244541Sbrooks gr = getgrgid(n->st_gid); 68244541Sbrooks if (gr == NULL) 69244541Sbrooks printf(" gid=%d", n->st_gid); 70244541Sbrooks else 71244541Sbrooks printf(" gname=%s", gr->gr_name); 72244541Sbrooks } 73244541Sbrooks if (f & F_MODE) 74244541Sbrooks printf(" mode=%o", n->st_mode); 75244541Sbrooks if (f & F_NLINK) 76244541Sbrooks printf(" nlink=%d", n->st_nlink); 77244541Sbrooks if (f & F_SIZE) 78244541Sbrooks printf(" size=%jd", (intmax_t)n->st_size); 79244541Sbrooks if (f & F_UID) 80244541Sbrooks printf(" uid=%d", n->st_uid); 81244541Sbrooks if (f & F_UNAME) { 82244541Sbrooks pw = getpwuid(n->st_uid); 83244541Sbrooks if (pw == NULL) 84244541Sbrooks printf(" uid=%d", n->st_uid); 85244541Sbrooks else 86244541Sbrooks printf(" uname=%s", pw->pw_name); 87244541Sbrooks } 88244541Sbrooks if (f & F_MD5) 89244541Sbrooks printf(" %s=%s", MD5KEY, n->md5digest); 90244541Sbrooks if (f & F_SHA1) 91244541Sbrooks printf(" %s=%s", SHA1KEY, n->sha1digest); 92244541Sbrooks if (f & F_RMD160) 93244541Sbrooks printf(" %s=%s", RMD160KEY, n->rmd160digest); 94244541Sbrooks if (f & F_SHA256) 95244541Sbrooks printf(" %s=%s", SHA256KEY, n->sha256digest); 96244541Sbrooks if (f & F_SHA384) 97244541Sbrooks printf(" %s=%s", SHA384KEY, n->sha384digest); 98244541Sbrooks if (f & F_SHA512) 99244541Sbrooks printf(" %s=%s", SHA512KEY, n->sha512digest); 100244541Sbrooks if (f & F_FLAGS) 101244541Sbrooks printf(" flags=%s", flags_to_string(n->st_flags, "none")); 102244541Sbrooks printf("\n"); 103244541Sbrooks} 104244541Sbrooks 105244541Sbrooksstatic int 106244541Sbrooksmismatch(NODE *n1, NODE *n2, int differ, char const *path) 107244541Sbrooks{ 108244541Sbrooks 109244541Sbrooks if (n2 == NULL) { 110244541Sbrooks shownode(n1, differ, path); 111244541Sbrooks return (1); 112244541Sbrooks } 113244541Sbrooks if (n1 == NULL) { 114244541Sbrooks printf("\t"); 115244541Sbrooks shownode(n2, differ, path); 116244541Sbrooks return (1); 117244541Sbrooks } 118244541Sbrooks if (!(differ & keys)) 119244541Sbrooks return(0); 120244541Sbrooks printf("\t\t"); 121244541Sbrooks shownode(n1, differ, path); 122244541Sbrooks printf("\t\t"); 123244541Sbrooks shownode(n2, differ, path); 124244541Sbrooks return (1); 125244541Sbrooks} 126244541Sbrooks 127244541Sbrooksstatic int 128244541Sbrookscompare_nodes(NODE *n1, NODE *n2, char const *path) 129244541Sbrooks{ 130244541Sbrooks int differs; 131244541Sbrooks 132244541Sbrooks if (n1 != NULL && n1->type == F_LINK) 133244541Sbrooks n1->flags &= ~F_MODE; 134244541Sbrooks if (n2 != NULL && n2->type == F_LINK) 135244541Sbrooks n2->flags &= ~F_MODE; 136244541Sbrooks differs = 0; 137244541Sbrooks if (n1 == NULL && n2 != NULL) { 138244541Sbrooks differs = n2->flags; 139244541Sbrooks mismatch(n1, n2, differs, path); 140244541Sbrooks return (1); 141244541Sbrooks } 142244541Sbrooks if (n1 != NULL && n2 == NULL) { 143244541Sbrooks differs = n1->flags; 144244541Sbrooks mismatch(n1, n2, differs, path); 145244541Sbrooks return (1); 146244541Sbrooks } 147244541Sbrooks if (n1->type != n2->type) { 148244541Sbrooks differs = 0; 149244541Sbrooks mismatch(n1, n2, differs, path); 150244541Sbrooks return (1); 151244541Sbrooks } 152244541Sbrooks if (FF(n1, n2, F_CKSUM, cksum)) 153244541Sbrooks differs |= F_CKSUM; 154244541Sbrooks if (FF(n1, n2, F_GID, st_gid)) 155244541Sbrooks differs |= F_GID; 156244541Sbrooks if (FF(n1, n2, F_GNAME, st_gid)) 157244541Sbrooks differs |= F_GNAME; 158244541Sbrooks if (FF(n1, n2, F_MODE, st_mode)) 159244541Sbrooks differs |= F_MODE; 160244541Sbrooks if (FF(n1, n2, F_NLINK, st_nlink)) 161244541Sbrooks differs |= F_NLINK; 162244541Sbrooks if (FF(n1, n2, F_SIZE, st_size)) 163244541Sbrooks differs |= F_SIZE; 164244541Sbrooks if (FS(n1, n2, F_SLINK, slink)) 165244541Sbrooks differs |= F_SLINK; 166244541Sbrooks if (FM(n1, n2, F_TIME, st_mtimespec)) 167244541Sbrooks differs |= F_TIME; 168244541Sbrooks if (FF(n1, n2, F_UID, st_uid)) 169244541Sbrooks differs |= F_UID; 170244541Sbrooks if (FF(n1, n2, F_UNAME, st_uid)) 171244541Sbrooks differs |= F_UNAME; 172244541Sbrooks if (FS(n1, n2, F_MD5, md5digest)) 173244541Sbrooks differs |= F_MD5; 174244541Sbrooks if (FS(n1, n2, F_SHA1, sha1digest)) 175244541Sbrooks differs |= F_SHA1; 176244541Sbrooks if (FS(n1, n2, F_RMD160, rmd160digest)) 177244541Sbrooks differs |= F_RMD160; 178244541Sbrooks if (FS(n1, n2, F_SHA256, sha256digest)) 179244541Sbrooks differs |= F_SHA256; 180244541Sbrooks if (FS(n1, n2, F_SHA384, sha384digest)) 181244541Sbrooks differs |= F_SHA384; 182244541Sbrooks if (FS(n1, n2, F_SHA512, sha512digest)) 183244541Sbrooks differs |= F_SHA512; 184244541Sbrooks if (FF(n1, n2, F_FLAGS, st_flags)) 185244541Sbrooks differs |= F_FLAGS; 186244541Sbrooks if (differs) { 187244541Sbrooks mismatch(n1, n2, differs, path); 188244541Sbrooks return (1); 189244541Sbrooks } 190244541Sbrooks return (0); 191244541Sbrooks} 192244541Sbrooksstatic int 193244541Sbrookswalk_in_the_forest(NODE *t1, NODE *t2, char const *path) 194244541Sbrooks{ 195244541Sbrooks int r, i; 196244541Sbrooks NODE *c1, *c2, *n1, *n2; 197244541Sbrooks char *np; 198244541Sbrooks 199244541Sbrooks r = 0; 200244541Sbrooks 201244541Sbrooks if (t1 != NULL) 202244541Sbrooks c1 = t1->child; 203244541Sbrooks else 204244541Sbrooks c1 = NULL; 205244541Sbrooks if (t2 != NULL) 206244541Sbrooks c2 = t2->child; 207244541Sbrooks else 208244541Sbrooks c2 = NULL; 209244541Sbrooks while (c1 != NULL || c2 != NULL) { 210244541Sbrooks n1 = n2 = NULL; 211244541Sbrooks if (c1 != NULL) 212244541Sbrooks n1 = c1->next; 213244541Sbrooks if (c2 != NULL) 214244541Sbrooks n2 = c2->next; 215244541Sbrooks if (c1 != NULL && c2 != NULL) { 216244541Sbrooks if (c1->type != F_DIR && c2->type == F_DIR) { 217244541Sbrooks n2 = c2; 218244541Sbrooks c2 = NULL; 219244541Sbrooks } else if (c1->type == F_DIR && c2->type != F_DIR) { 220244541Sbrooks n1 = c1; 221244541Sbrooks c1 = NULL; 222244541Sbrooks } else { 223244541Sbrooks i = strcmp(c1->name, c2->name); 224244541Sbrooks if (i > 0) { 225244541Sbrooks n1 = c1; 226244541Sbrooks c1 = NULL; 227244541Sbrooks } else if (i < 0) { 228244541Sbrooks n2 = c2; 229244541Sbrooks c2 = NULL; 230244541Sbrooks } 231244541Sbrooks } 232244541Sbrooks } 233244541Sbrooks if (c1 == NULL && c2->type == F_DIR) { 234244541Sbrooks asprintf(&np, "%s%s/", path, c2->name); 235244541Sbrooks i = walk_in_the_forest(c1, c2, np); 236244541Sbrooks free(np); 237244541Sbrooks i += compare_nodes(c1, c2, path); 238244541Sbrooks } else if (c2 == NULL && c1->type == F_DIR) { 239244541Sbrooks asprintf(&np, "%s%s/", path, c1->name); 240244541Sbrooks i = walk_in_the_forest(c1, c2, np); 241244541Sbrooks free(np); 242244541Sbrooks i += compare_nodes(c1, c2, path); 243244541Sbrooks } else if (c1 == NULL || c2 == NULL) { 244244541Sbrooks i = compare_nodes(c1, c2, path); 245244541Sbrooks } else if (c1->type == F_DIR && c2->type == F_DIR) { 246244541Sbrooks asprintf(&np, "%s%s/", path, c1->name); 247244541Sbrooks i = walk_in_the_forest(c1, c2, np); 248244541Sbrooks free(np); 249244541Sbrooks i += compare_nodes(c1, c2, path); 250244541Sbrooks } else { 251244541Sbrooks i = compare_nodes(c1, c2, path); 252244541Sbrooks } 253244541Sbrooks r += i; 254244541Sbrooks c1 = n1; 255244541Sbrooks c2 = n2; 256244541Sbrooks } 257244541Sbrooks return (r); 258244541Sbrooks} 259244541Sbrooks 260244541Sbrooksint 261244541Sbrooksmtree_specspec(FILE *fi, FILE *fj) 262244541Sbrooks{ 263244541Sbrooks int rval; 264244541Sbrooks NODE *root1, *root2; 265244541Sbrooks 266244541Sbrooks root1 = spec(fi); 267244541Sbrooks root2 = spec(fj); 268244541Sbrooks rval = walk_in_the_forest(root1, root2, ""); 269244541Sbrooks rval += compare_nodes(root1, root2, ""); 270244541Sbrooks if (rval > 0) 271244541Sbrooks return (MISMATCHEXIT); 272244541Sbrooks return (0); 273244541Sbrooks} 274