1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <stdio.h> 30*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 31*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 32*7c478bd9Sstevel@tonic-gate #include <string.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 35*7c478bd9Sstevel@tonic-gate #include <dirent.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 37*7c478bd9Sstevel@tonic-gate #include <errno.h> 38*7c478bd9Sstevel@tonic-gate #include <unistd.h> 39*7c478bd9Sstevel@tonic-gate #include <ftw.h> 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate #include "list.h" 42*7c478bd9Sstevel@tonic-gate #include "protocmp.h" 43*7c478bd9Sstevel@tonic-gate #include "proto_list.h" 44*7c478bd9Sstevel@tonic-gate #include "protodir.h" 45*7c478bd9Sstevel@tonic-gate #include "exception_list.h" 46*7c478bd9Sstevel@tonic-gate #include "stdusers.h" 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate #define MAX_PROTO_REFS 5 49*7c478bd9Sstevel@tonic-gate #define MAX_EXCEPTION_FILES 5 50*7c478bd9Sstevel@tonic-gate #define MAX_DEPTH 50 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate /* 53*7c478bd9Sstevel@tonic-gate * default flag values 54*7c478bd9Sstevel@tonic-gate */ 55*7c478bd9Sstevel@tonic-gate static int check_group = 1; 56*7c478bd9Sstevel@tonic-gate static int set_group = 0; 57*7c478bd9Sstevel@tonic-gate static int check_user = 1; 58*7c478bd9Sstevel@tonic-gate static int set_user = 0; 59*7c478bd9Sstevel@tonic-gate static int check_perm = 1; 60*7c478bd9Sstevel@tonic-gate static int set_perm = 0; 61*7c478bd9Sstevel@tonic-gate static int check_link = 1; 62*7c478bd9Sstevel@tonic-gate static int check_sym = 1; 63*7c478bd9Sstevel@tonic-gate static int check_majmin = 1; 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate static elem_list first_list; 66*7c478bd9Sstevel@tonic-gate static char *first_file_name; 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate static elem_list second_list; 69*7c478bd9Sstevel@tonic-gate static char *second_file_name; 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate static FILE *need_add_fp; 72*7c478bd9Sstevel@tonic-gate static char *need_add_file; 73*7c478bd9Sstevel@tonic-gate static FILE *need_rm_fp; 74*7c478bd9Sstevel@tonic-gate static char *need_rm_file; 75*7c478bd9Sstevel@tonic-gate static FILE *differ_fp; 76*7c478bd9Sstevel@tonic-gate static char *differ_file; 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate static char *myname; 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate /* 81*7c478bd9Sstevel@tonic-gate * default flag values 82*7c478bd9Sstevel@tonic-gate */ 83*7c478bd9Sstevel@tonic-gate static int verbose = 0; 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate static void 86*7c478bd9Sstevel@tonic-gate usage(void) 87*7c478bd9Sstevel@tonic-gate { 88*7c478bd9Sstevel@tonic-gate (void) fputs("usage: protocmp [-gupGUPlmsLv] " 89*7c478bd9Sstevel@tonic-gate "[-e <exception-list> ...] " 90*7c478bd9Sstevel@tonic-gate "-d <protolist|pkg dir>\n\t[-d <protolist|pkg dir> ...] " 91*7c478bd9Sstevel@tonic-gate "[<protolist|pkg dir>...]|<root>]\n", 92*7c478bd9Sstevel@tonic-gate stderr); 93*7c478bd9Sstevel@tonic-gate (void) fputs(" where:\n", stderr); 94*7c478bd9Sstevel@tonic-gate (void) fputs("\t-g : don't compare group\n", stderr); 95*7c478bd9Sstevel@tonic-gate (void) fputs("\t-u : don't compare owner\n", stderr); 96*7c478bd9Sstevel@tonic-gate (void) fputs("\t-p : don't compare permissions\n", stderr); 97*7c478bd9Sstevel@tonic-gate (void) fputs("\t-G : set group\n", stderr); 98*7c478bd9Sstevel@tonic-gate (void) fputs("\t-U : set owner\n", stderr); 99*7c478bd9Sstevel@tonic-gate (void) fputs("\t-P : set permissions\n", stderr); 100*7c478bd9Sstevel@tonic-gate (void) fputs("\t-l : don't compare link counts\n", stderr); 101*7c478bd9Sstevel@tonic-gate (void) fputs("\t-m : don't compare major/minor numbers\n", 102*7c478bd9Sstevel@tonic-gate stderr); 103*7c478bd9Sstevel@tonic-gate (void) fputs("\t-s : don't compare symlink values\n", stderr); 104*7c478bd9Sstevel@tonic-gate (void) fputs("\t-d <protolist|pkg dir>:\n", stderr); 105*7c478bd9Sstevel@tonic-gate (void) fputs("\t proto list or packaging to check\n", stderr); 106*7c478bd9Sstevel@tonic-gate (void) fputs("\t-e <file>: exceptions file\n", stderr); 107*7c478bd9Sstevel@tonic-gate (void) fputs("\t-L : list filtered exceptions\n", stderr); 108*7c478bd9Sstevel@tonic-gate (void) fputs("\t-v : verbose output\n", stderr); 109*7c478bd9Sstevel@tonic-gate (void) fputs("\n" 110*7c478bd9Sstevel@tonic-gate "If any of the -[GUP] flags are given, then the final argument must be the\n" 111*7c478bd9Sstevel@tonic-gate "proto root directory itself on which to set permissions according to the\n" 112*7c478bd9Sstevel@tonic-gate "packaging data specified via -d options.\n", stderr); 113*7c478bd9Sstevel@tonic-gate } 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate static void 117*7c478bd9Sstevel@tonic-gate open_output_files(void) 118*7c478bd9Sstevel@tonic-gate { 119*7c478bd9Sstevel@tonic-gate if ((need_add_fp = 120*7c478bd9Sstevel@tonic-gate fopen((need_add_file = tempnam(NULL, "add")), "w")) == NULL) { 121*7c478bd9Sstevel@tonic-gate perror(need_add_file); 122*7c478bd9Sstevel@tonic-gate exit(1); 123*7c478bd9Sstevel@tonic-gate } 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate if ((need_rm_fp = 126*7c478bd9Sstevel@tonic-gate fopen((need_rm_file = tempnam(NULL, "rm")), "w")) == NULL) { 127*7c478bd9Sstevel@tonic-gate perror(need_rm_file); 128*7c478bd9Sstevel@tonic-gate exit(1); 129*7c478bd9Sstevel@tonic-gate } 130*7c478bd9Sstevel@tonic-gate 131*7c478bd9Sstevel@tonic-gate if ((differ_fp = 132*7c478bd9Sstevel@tonic-gate fopen((differ_file = tempnam(NULL, "diff")), "w")) == NULL) { 133*7c478bd9Sstevel@tonic-gate perror(differ_file); 134*7c478bd9Sstevel@tonic-gate exit(1); 135*7c478bd9Sstevel@tonic-gate } 136*7c478bd9Sstevel@tonic-gate } 137*7c478bd9Sstevel@tonic-gate 138*7c478bd9Sstevel@tonic-gate static void 139*7c478bd9Sstevel@tonic-gate close_output_files(void) 140*7c478bd9Sstevel@tonic-gate { 141*7c478bd9Sstevel@tonic-gate (void) fclose(need_add_fp); 142*7c478bd9Sstevel@tonic-gate (void) fclose(need_rm_fp); 143*7c478bd9Sstevel@tonic-gate (void) fclose(differ_fp); 144*7c478bd9Sstevel@tonic-gate } 145*7c478bd9Sstevel@tonic-gate 146*7c478bd9Sstevel@tonic-gate static void 147*7c478bd9Sstevel@tonic-gate print_file(char *file) 148*7c478bd9Sstevel@tonic-gate { 149*7c478bd9Sstevel@tonic-gate FILE *fp; 150*7c478bd9Sstevel@tonic-gate int count; 151*7c478bd9Sstevel@tonic-gate char buff[BUF_SIZE]; 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate if ((fp = fopen(file, "r")) == NULL) { 154*7c478bd9Sstevel@tonic-gate perror(need_add_file); 155*7c478bd9Sstevel@tonic-gate } 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate while (count = fread(buff, sizeof (char), BUF_SIZE, fp)) 158*7c478bd9Sstevel@tonic-gate (void) fwrite(buff, sizeof (char), count, stdout); 159*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 160*7c478bd9Sstevel@tonic-gate } 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate static void 163*7c478bd9Sstevel@tonic-gate print_header(void) 164*7c478bd9Sstevel@tonic-gate { 165*7c478bd9Sstevel@tonic-gate (void) printf("%c %-30s %-20s %-4s %-5s %-5s %-5s %-2s %2s %2s %-9s\n", 166*7c478bd9Sstevel@tonic-gate 'T', "File Name", "Reloc/Sym name", "perm", "owner", "group", 167*7c478bd9Sstevel@tonic-gate "inode", "lnk", "maj", "min", "package(s)"); 168*7c478bd9Sstevel@tonic-gate (void) puts("-------------------------------------------------------" 169*7c478bd9Sstevel@tonic-gate "-----------------------------------------------------"); 170*7c478bd9Sstevel@tonic-gate } 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate static void 173*7c478bd9Sstevel@tonic-gate print_results(void) 174*7c478bd9Sstevel@tonic-gate { 175*7c478bd9Sstevel@tonic-gate (void) puts("*******************************************************"); 176*7c478bd9Sstevel@tonic-gate (void) puts("*"); 177*7c478bd9Sstevel@tonic-gate (void) printf("* Entries found in %s, but not found in %s\n", 178*7c478bd9Sstevel@tonic-gate first_file_name, second_file_name); 179*7c478bd9Sstevel@tonic-gate (void) puts("*"); 180*7c478bd9Sstevel@tonic-gate (void) puts("*******************************************************"); 181*7c478bd9Sstevel@tonic-gate print_header(); 182*7c478bd9Sstevel@tonic-gate print_file(need_add_file); 183*7c478bd9Sstevel@tonic-gate (void) puts("*******************************************************"); 184*7c478bd9Sstevel@tonic-gate (void) puts("*"); 185*7c478bd9Sstevel@tonic-gate (void) printf("* Entries found in %s, but not found in %s\n", 186*7c478bd9Sstevel@tonic-gate second_file_name, first_file_name); 187*7c478bd9Sstevel@tonic-gate (void) puts("*"); 188*7c478bd9Sstevel@tonic-gate (void) puts("*******************************************************"); 189*7c478bd9Sstevel@tonic-gate print_header(); 190*7c478bd9Sstevel@tonic-gate print_file(need_rm_file); 191*7c478bd9Sstevel@tonic-gate (void) puts("*******************************************************"); 192*7c478bd9Sstevel@tonic-gate (void) puts("*"); 193*7c478bd9Sstevel@tonic-gate (void) printf("* Entries that differ between %s and %s\n", 194*7c478bd9Sstevel@tonic-gate first_file_name, second_file_name); 195*7c478bd9Sstevel@tonic-gate (void) puts("*"); 196*7c478bd9Sstevel@tonic-gate (void) printf("* filea == %s\n", first_file_name); 197*7c478bd9Sstevel@tonic-gate (void) printf("* fileb == %s\n", second_file_name); 198*7c478bd9Sstevel@tonic-gate (void) puts("*"); 199*7c478bd9Sstevel@tonic-gate (void) puts("*******************************************************"); 200*7c478bd9Sstevel@tonic-gate (void) fputs("Unit ", stdout); 201*7c478bd9Sstevel@tonic-gate print_header(); 202*7c478bd9Sstevel@tonic-gate print_file(differ_file); 203*7c478bd9Sstevel@tonic-gate } 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate static void 206*7c478bd9Sstevel@tonic-gate clean_up(void) 207*7c478bd9Sstevel@tonic-gate { 208*7c478bd9Sstevel@tonic-gate (void) unlink(need_add_file); 209*7c478bd9Sstevel@tonic-gate (void) unlink(need_rm_file); 210*7c478bd9Sstevel@tonic-gate (void) unlink(differ_file); 211*7c478bd9Sstevel@tonic-gate } 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate /* 214*7c478bd9Sstevel@tonic-gate * elem_compare(a,b) 215*7c478bd9Sstevel@tonic-gate * 216*7c478bd9Sstevel@tonic-gate * Args: 217*7c478bd9Sstevel@tonic-gate * a - element a 218*7c478bd9Sstevel@tonic-gate * b - element b 219*7c478bd9Sstevel@tonic-gate * different_types - 220*7c478bd9Sstevel@tonic-gate * value = 0 -> comparing two elements of same 221*7c478bd9Sstevel@tonic-gate * type (eg: protodir elem vs. protodir elem). 222*7c478bd9Sstevel@tonic-gate * value != 0 -> comparing two elements of different type 223*7c478bd9Sstevel@tonic-gate * (eg: protodir elem vs. protolist elem). 224*7c478bd9Sstevel@tonic-gate * 225*7c478bd9Sstevel@tonic-gate * Returns: 226*7c478bd9Sstevel@tonic-gate * 0 - elements are identical 227*7c478bd9Sstevel@tonic-gate * >0 - elements differ 228*7c478bd9Sstevel@tonic-gate * check flags to see which fields differ. 229*7c478bd9Sstevel@tonic-gate */ 230*7c478bd9Sstevel@tonic-gate static int 231*7c478bd9Sstevel@tonic-gate elem_compare(elem *a, elem *b, int different_types) 232*7c478bd9Sstevel@tonic-gate { 233*7c478bd9Sstevel@tonic-gate int res = 0; 234*7c478bd9Sstevel@tonic-gate elem *i, *j; 235*7c478bd9Sstevel@tonic-gate 236*7c478bd9Sstevel@tonic-gate /* 237*7c478bd9Sstevel@tonic-gate * if these are hard links to other files - those are the 238*7c478bd9Sstevel@tonic-gate * files that should be compared. 239*7c478bd9Sstevel@tonic-gate */ 240*7c478bd9Sstevel@tonic-gate i = a->link_parent ? a->link_parent : a; 241*7c478bd9Sstevel@tonic-gate j = b->link_parent ? b->link_parent : b; 242*7c478bd9Sstevel@tonic-gate 243*7c478bd9Sstevel@tonic-gate /* 244*7c478bd9Sstevel@tonic-gate * We do not compare inodes - they always differ. 245*7c478bd9Sstevel@tonic-gate * We do not compare names because we assume that was 246*7c478bd9Sstevel@tonic-gate * checked before. 247*7c478bd9Sstevel@tonic-gate */ 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate /* 250*7c478bd9Sstevel@tonic-gate * Special rules for comparison: 251*7c478bd9Sstevel@tonic-gate * 252*7c478bd9Sstevel@tonic-gate * 1) if directory - ignore ref_cnt. 253*7c478bd9Sstevel@tonic-gate * 2) if sym_link - only check file_type & symlink 254*7c478bd9Sstevel@tonic-gate * 3) elem type of FILE_T, EDIT_T, & VOLATILE_T are equivilant when 255*7c478bd9Sstevel@tonic-gate * comparing a protodir entry to a protolist entry. 256*7c478bd9Sstevel@tonic-gate */ 257*7c478bd9Sstevel@tonic-gate if (i->file_type != j->file_type) { 258*7c478bd9Sstevel@tonic-gate if (different_types) { 259*7c478bd9Sstevel@tonic-gate /* 260*7c478bd9Sstevel@tonic-gate * Check to see if filetypes are FILE_T vs. 261*7c478bd9Sstevel@tonic-gate * EDIT_T/VOLATILE_T/LINK_T comparisons. 262*7c478bd9Sstevel@tonic-gate */ 263*7c478bd9Sstevel@tonic-gate if ((i->file_type == FILE_T) && 264*7c478bd9Sstevel@tonic-gate ((j->file_type == EDIT_T) || 265*7c478bd9Sstevel@tonic-gate (j->file_type == VOLATILE_T) || 266*7c478bd9Sstevel@tonic-gate (j->file_type == LINK_T))) { 267*7c478bd9Sstevel@tonic-gate /*EMPTY*/ 268*7c478bd9Sstevel@tonic-gate } else if ((j->file_type == FILE_T) && 269*7c478bd9Sstevel@tonic-gate ((i->file_type == EDIT_T) || 270*7c478bd9Sstevel@tonic-gate (i->file_type == VOLATILE_T) || 271*7c478bd9Sstevel@tonic-gate (i->file_type == LINK_T))) { 272*7c478bd9Sstevel@tonic-gate /*EMPTY*/ 273*7c478bd9Sstevel@tonic-gate } else 274*7c478bd9Sstevel@tonic-gate res |= TYPE_F; 275*7c478bd9Sstevel@tonic-gate } else 276*7c478bd9Sstevel@tonic-gate res |= TYPE_F; 277*7c478bd9Sstevel@tonic-gate } 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate /* 280*7c478bd9Sstevel@tonic-gate * if symlink - check the symlink value and then 281*7c478bd9Sstevel@tonic-gate * return. symlink is the only field of concern 282*7c478bd9Sstevel@tonic-gate * in SYMLINKS. 283*7c478bd9Sstevel@tonic-gate */ 284*7c478bd9Sstevel@tonic-gate if (check_sym && ((res == 0) && (i->file_type == SYM_LINK_T))) { 285*7c478bd9Sstevel@tonic-gate if ((!i->symsrc) || (!j->symsrc)) 286*7c478bd9Sstevel@tonic-gate res |= SYM_F; 287*7c478bd9Sstevel@tonic-gate else { 288*7c478bd9Sstevel@tonic-gate /* 289*7c478bd9Sstevel@tonic-gate * if either symlink starts with a './' strip it off, 290*7c478bd9Sstevel@tonic-gate * its irrelavant. 291*7c478bd9Sstevel@tonic-gate */ 292*7c478bd9Sstevel@tonic-gate if ((i->symsrc[0] == '.') && (i->symsrc[1] == '/')) 293*7c478bd9Sstevel@tonic-gate i->symsrc += 2; 294*7c478bd9Sstevel@tonic-gate if ((j->symsrc[0] == '.') && (j->symsrc[1] == '/')) 295*7c478bd9Sstevel@tonic-gate j->symsrc += 2; 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate if (strncmp(i->symsrc, j->symsrc, MAXNAME) != 0) 298*7c478bd9Sstevel@tonic-gate res |= SYM_F; 299*7c478bd9Sstevel@tonic-gate } 300*7c478bd9Sstevel@tonic-gate return (res); 301*7c478bd9Sstevel@tonic-gate } 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate if ((i->file_type != DIR_T) && check_link && 304*7c478bd9Sstevel@tonic-gate (i->ref_cnt != j->ref_cnt)) 305*7c478bd9Sstevel@tonic-gate res |= REF_F; 306*7c478bd9Sstevel@tonic-gate if (check_user && (strncmp(i->owner, j->owner, TYPESIZE) != 0)) 307*7c478bd9Sstevel@tonic-gate res |= OWNER_F; 308*7c478bd9Sstevel@tonic-gate if (check_group && (strncmp(i->group, j->group, TYPESIZE) != 0)) 309*7c478bd9Sstevel@tonic-gate res |= GROUP_F; 310*7c478bd9Sstevel@tonic-gate if (check_perm && (i->perm != j->perm)) 311*7c478bd9Sstevel@tonic-gate res |= PERM_F; 312*7c478bd9Sstevel@tonic-gate if (check_majmin && ((i->major != j->major) || (i->minor != j->minor))) 313*7c478bd9Sstevel@tonic-gate res |= MAJMIN_F; 314*7c478bd9Sstevel@tonic-gate 315*7c478bd9Sstevel@tonic-gate return (res); 316*7c478bd9Sstevel@tonic-gate } 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate static void 319*7c478bd9Sstevel@tonic-gate print_elem(FILE *fp, elem *e) 320*7c478bd9Sstevel@tonic-gate { 321*7c478bd9Sstevel@tonic-gate elem p; 322*7c478bd9Sstevel@tonic-gate pkg_list *l; 323*7c478bd9Sstevel@tonic-gate char maj[TYPESIZE], min[TYPESIZE]; 324*7c478bd9Sstevel@tonic-gate char perm[12], ref_cnt[12]; 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate /* 327*7c478bd9Sstevel@tonic-gate * If this is a LINK to another file, then adopt 328*7c478bd9Sstevel@tonic-gate * the permissions of that file. 329*7c478bd9Sstevel@tonic-gate */ 330*7c478bd9Sstevel@tonic-gate if (e->link_parent) { 331*7c478bd9Sstevel@tonic-gate p = *((elem *)e->link_parent); 332*7c478bd9Sstevel@tonic-gate (void) strcpy(p.name, e->name); 333*7c478bd9Sstevel@tonic-gate p.symsrc = e->symsrc; 334*7c478bd9Sstevel@tonic-gate p.file_type = e->file_type; 335*7c478bd9Sstevel@tonic-gate e = &p; 336*7c478bd9Sstevel@tonic-gate } 337*7c478bd9Sstevel@tonic-gate 338*7c478bd9Sstevel@tonic-gate if (!check_majmin || e->major == -1) { 339*7c478bd9Sstevel@tonic-gate maj[0] = '-'; 340*7c478bd9Sstevel@tonic-gate maj[1] = '\0'; 341*7c478bd9Sstevel@tonic-gate } else { 342*7c478bd9Sstevel@tonic-gate (void) sprintf(maj, "%d", e->major); 343*7c478bd9Sstevel@tonic-gate } 344*7c478bd9Sstevel@tonic-gate 345*7c478bd9Sstevel@tonic-gate if (!check_majmin || e->minor == -1) { 346*7c478bd9Sstevel@tonic-gate min[0] = '-'; 347*7c478bd9Sstevel@tonic-gate min[1] = '\0'; 348*7c478bd9Sstevel@tonic-gate } else { 349*7c478bd9Sstevel@tonic-gate (void) sprintf(min, "%d", e->minor); 350*7c478bd9Sstevel@tonic-gate } 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate if (!check_perm) { 353*7c478bd9Sstevel@tonic-gate perm[0] = '-'; 354*7c478bd9Sstevel@tonic-gate perm[1] = '\0'; 355*7c478bd9Sstevel@tonic-gate } else { 356*7c478bd9Sstevel@tonic-gate (void) snprintf(perm, sizeof (perm), "%o", e->perm); 357*7c478bd9Sstevel@tonic-gate } 358*7c478bd9Sstevel@tonic-gate 359*7c478bd9Sstevel@tonic-gate if (!check_link) { 360*7c478bd9Sstevel@tonic-gate ref_cnt[0] = '-'; 361*7c478bd9Sstevel@tonic-gate ref_cnt[1] = '\0'; 362*7c478bd9Sstevel@tonic-gate } else { 363*7c478bd9Sstevel@tonic-gate (void) snprintf(ref_cnt, sizeof (ref_cnt), "%d", e->ref_cnt); 364*7c478bd9Sstevel@tonic-gate } 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%c %-30s %-20s %4s %-5s %-5s %6d %2s %2s %2s ", 367*7c478bd9Sstevel@tonic-gate e->file_type, e->name, 368*7c478bd9Sstevel@tonic-gate check_sym && e->symsrc != NULL ? e->symsrc : "-", perm, 369*7c478bd9Sstevel@tonic-gate check_user ? e->owner : "-", 370*7c478bd9Sstevel@tonic-gate check_group ? e->group : "-", 371*7c478bd9Sstevel@tonic-gate e->inode, ref_cnt, maj, min); 372*7c478bd9Sstevel@tonic-gate /* 373*7c478bd9Sstevel@tonic-gate * dump package list - if any. 374*7c478bd9Sstevel@tonic-gate */ 375*7c478bd9Sstevel@tonic-gate if (!e->pkgs) 376*7c478bd9Sstevel@tonic-gate (void) fputs(" proto", fp); 377*7c478bd9Sstevel@tonic-gate 378*7c478bd9Sstevel@tonic-gate for (l = e->pkgs; l; l = l->next) { 379*7c478bd9Sstevel@tonic-gate (void) fputc(' ', fp); 380*7c478bd9Sstevel@tonic-gate (void) fputs(l->pkg_name, fp); 381*7c478bd9Sstevel@tonic-gate } 382*7c478bd9Sstevel@tonic-gate (void) fputc('\n', fp); 383*7c478bd9Sstevel@tonic-gate } 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate /* 386*7c478bd9Sstevel@tonic-gate * do_compare(a,b) 387*7c478bd9Sstevel@tonic-gate * 388*7c478bd9Sstevel@tonic-gate * Args: 389*7c478bd9Sstevel@tonic-gate * different_types - see elem_compare() for explanation. 390*7c478bd9Sstevel@tonic-gate */ 391*7c478bd9Sstevel@tonic-gate static void 392*7c478bd9Sstevel@tonic-gate do_compare(elem *a, elem *b, int different_types) 393*7c478bd9Sstevel@tonic-gate { 394*7c478bd9Sstevel@tonic-gate int rc; 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate if ((rc = elem_compare(a, b, different_types)) != 0) { 397*7c478bd9Sstevel@tonic-gate (void) fputs("filea: ", differ_fp); 398*7c478bd9Sstevel@tonic-gate print_elem(differ_fp, a); 399*7c478bd9Sstevel@tonic-gate (void) fputs("fileb: ", differ_fp); 400*7c478bd9Sstevel@tonic-gate print_elem(differ_fp, b); 401*7c478bd9Sstevel@tonic-gate (void) fputs(" differ: ", differ_fp); 402*7c478bd9Sstevel@tonic-gate 403*7c478bd9Sstevel@tonic-gate if (rc & SYM_F) 404*7c478bd9Sstevel@tonic-gate (void) fputs("symlink", differ_fp); 405*7c478bd9Sstevel@tonic-gate if (rc & PERM_F) 406*7c478bd9Sstevel@tonic-gate (void) fputs("perm ", differ_fp); 407*7c478bd9Sstevel@tonic-gate if (rc & REF_F) 408*7c478bd9Sstevel@tonic-gate (void) fputs("ref_cnt ", differ_fp); 409*7c478bd9Sstevel@tonic-gate if (rc & TYPE_F) 410*7c478bd9Sstevel@tonic-gate (void) fputs("file_type ", differ_fp); 411*7c478bd9Sstevel@tonic-gate if (rc & OWNER_F) 412*7c478bd9Sstevel@tonic-gate (void) fputs("owner ", differ_fp); 413*7c478bd9Sstevel@tonic-gate if (rc & GROUP_F) 414*7c478bd9Sstevel@tonic-gate (void) fputs("group ", differ_fp); 415*7c478bd9Sstevel@tonic-gate if (rc & MAJMIN_F) 416*7c478bd9Sstevel@tonic-gate (void) fputs("major/minor ", differ_fp); 417*7c478bd9Sstevel@tonic-gate (void) putc('\n', differ_fp); 418*7c478bd9Sstevel@tonic-gate (void) putc('\n', differ_fp); 419*7c478bd9Sstevel@tonic-gate } 420*7c478bd9Sstevel@tonic-gate } 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate static void 423*7c478bd9Sstevel@tonic-gate check_second_vs_first(int verbose) 424*7c478bd9Sstevel@tonic-gate { 425*7c478bd9Sstevel@tonic-gate int i; 426*7c478bd9Sstevel@tonic-gate elem *cur; 427*7c478bd9Sstevel@tonic-gate 428*7c478bd9Sstevel@tonic-gate for (i = 0; i < second_list.num_of_buckets; i++) { 429*7c478bd9Sstevel@tonic-gate for (cur = second_list.list[i]; cur; cur = cur->next) { 430*7c478bd9Sstevel@tonic-gate if (!(cur->flag & VISITED_F)) { 431*7c478bd9Sstevel@tonic-gate if ((first_list.type != second_list.type) && 432*7c478bd9Sstevel@tonic-gate find_elem(&exception_list, cur, 433*7c478bd9Sstevel@tonic-gate FOLLOW_LINK)) { 434*7c478bd9Sstevel@tonic-gate /* 435*7c478bd9Sstevel@tonic-gate * this entry is filtered, we don't 436*7c478bd9Sstevel@tonic-gate * need to do any more processing. 437*7c478bd9Sstevel@tonic-gate */ 438*7c478bd9Sstevel@tonic-gate if (verbose) { 439*7c478bd9Sstevel@tonic-gate (void) printf( 440*7c478bd9Sstevel@tonic-gate "Filtered: Need Deletion " 441*7c478bd9Sstevel@tonic-gate "of:\n\t"); 442*7c478bd9Sstevel@tonic-gate print_elem(stdout, cur); 443*7c478bd9Sstevel@tonic-gate } 444*7c478bd9Sstevel@tonic-gate continue; 445*7c478bd9Sstevel@tonic-gate } 446*7c478bd9Sstevel@tonic-gate /* 447*7c478bd9Sstevel@tonic-gate * It is possible for arch specific files to be 448*7c478bd9Sstevel@tonic-gate * found in a protodir but listed as arch 449*7c478bd9Sstevel@tonic-gate * independent in a protolist file. If this is 450*7c478bd9Sstevel@tonic-gate * a protodir vs. a protolist we will make 451*7c478bd9Sstevel@tonic-gate * that check. 452*7c478bd9Sstevel@tonic-gate */ 453*7c478bd9Sstevel@tonic-gate if ((second_list.type == PROTODIR_LIST) && 454*7c478bd9Sstevel@tonic-gate (cur->arch != P_ISA) && 455*7c478bd9Sstevel@tonic-gate (first_list.type != PROTODIR_LIST)) { 456*7c478bd9Sstevel@tonic-gate /* 457*7c478bd9Sstevel@tonic-gate * do a lookup for same file, but as 458*7c478bd9Sstevel@tonic-gate * type ISA. 459*7c478bd9Sstevel@tonic-gate */ 460*7c478bd9Sstevel@tonic-gate elem *e; 461*7c478bd9Sstevel@tonic-gate 462*7c478bd9Sstevel@tonic-gate e = find_elem_isa(&first_list, cur, 463*7c478bd9Sstevel@tonic-gate NO_FOLLOW_LINK); 464*7c478bd9Sstevel@tonic-gate if (e) { 465*7c478bd9Sstevel@tonic-gate do_compare(e, cur, 466*7c478bd9Sstevel@tonic-gate first_list.type - 467*7c478bd9Sstevel@tonic-gate second_list.type); 468*7c478bd9Sstevel@tonic-gate continue; 469*7c478bd9Sstevel@tonic-gate } 470*7c478bd9Sstevel@tonic-gate } 471*7c478bd9Sstevel@tonic-gate 472*7c478bd9Sstevel@tonic-gate print_elem(need_rm_fp, cur); 473*7c478bd9Sstevel@tonic-gate } 474*7c478bd9Sstevel@tonic-gate } 475*7c478bd9Sstevel@tonic-gate } 476*7c478bd9Sstevel@tonic-gate } 477*7c478bd9Sstevel@tonic-gate 478*7c478bd9Sstevel@tonic-gate static void 479*7c478bd9Sstevel@tonic-gate check_first_vs_second(int verbose) 480*7c478bd9Sstevel@tonic-gate { 481*7c478bd9Sstevel@tonic-gate int i; 482*7c478bd9Sstevel@tonic-gate elem *e; 483*7c478bd9Sstevel@tonic-gate elem *cur; 484*7c478bd9Sstevel@tonic-gate 485*7c478bd9Sstevel@tonic-gate for (i = 0; i < first_list.num_of_buckets; i++) { 486*7c478bd9Sstevel@tonic-gate for (cur = first_list.list[i]; cur; cur = cur->next) { 487*7c478bd9Sstevel@tonic-gate if ((first_list.type != second_list.type) && 488*7c478bd9Sstevel@tonic-gate find_elem(&exception_list, cur, FOLLOW_LINK)) { 489*7c478bd9Sstevel@tonic-gate /* 490*7c478bd9Sstevel@tonic-gate * this entry is filtered, we don't need to do 491*7c478bd9Sstevel@tonic-gate * any more processing. 492*7c478bd9Sstevel@tonic-gate */ 493*7c478bd9Sstevel@tonic-gate if (verbose) { 494*7c478bd9Sstevel@tonic-gate (void) printf("Filtered: Need " 495*7c478bd9Sstevel@tonic-gate "Addition of:\n\t"); 496*7c478bd9Sstevel@tonic-gate print_elem(stdout, cur); 497*7c478bd9Sstevel@tonic-gate } 498*7c478bd9Sstevel@tonic-gate continue; 499*7c478bd9Sstevel@tonic-gate } 500*7c478bd9Sstevel@tonic-gate 501*7c478bd9Sstevel@tonic-gate /* 502*7c478bd9Sstevel@tonic-gate * Search package database for file. 503*7c478bd9Sstevel@tonic-gate */ 504*7c478bd9Sstevel@tonic-gate e = find_elem(&second_list, cur, NO_FOLLOW_LINK); 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate /* 507*7c478bd9Sstevel@tonic-gate * It is possible for arch specific files to be found 508*7c478bd9Sstevel@tonic-gate * in a protodir but listed as arch independent in a 509*7c478bd9Sstevel@tonic-gate * protolist file. If this is a protodir vs. a 510*7c478bd9Sstevel@tonic-gate * protolist we will make that check. 511*7c478bd9Sstevel@tonic-gate */ 512*7c478bd9Sstevel@tonic-gate if (!e && (first_list.type == PROTODIR_LIST) && 513*7c478bd9Sstevel@tonic-gate (cur->arch != P_ISA) && 514*7c478bd9Sstevel@tonic-gate (second_list.type != PROTODIR_LIST)) { 515*7c478bd9Sstevel@tonic-gate /* 516*7c478bd9Sstevel@tonic-gate * do a lookup for same file, but as type ISA. 517*7c478bd9Sstevel@tonic-gate */ 518*7c478bd9Sstevel@tonic-gate e = find_elem_isa(&second_list, cur, 519*7c478bd9Sstevel@tonic-gate NO_FOLLOW_LINK); 520*7c478bd9Sstevel@tonic-gate } 521*7c478bd9Sstevel@tonic-gate 522*7c478bd9Sstevel@tonic-gate if (!e && (first_list.type != PROTODIR_LIST) && 523*7c478bd9Sstevel@tonic-gate (cur->arch == P_ISA) && 524*7c478bd9Sstevel@tonic-gate (second_list.type == PROTODIR_LIST)) { 525*7c478bd9Sstevel@tonic-gate /* 526*7c478bd9Sstevel@tonic-gate * do a lookup for same file, but as any 527*7c478bd9Sstevel@tonic-gate * type but ISA 528*7c478bd9Sstevel@tonic-gate */ 529*7c478bd9Sstevel@tonic-gate e = find_elem_mach(&second_list, cur, 530*7c478bd9Sstevel@tonic-gate NO_FOLLOW_LINK); 531*7c478bd9Sstevel@tonic-gate } 532*7c478bd9Sstevel@tonic-gate 533*7c478bd9Sstevel@tonic-gate if (e == NULL) 534*7c478bd9Sstevel@tonic-gate print_elem(need_add_fp, cur); 535*7c478bd9Sstevel@tonic-gate else { 536*7c478bd9Sstevel@tonic-gate do_compare(cur, e, 537*7c478bd9Sstevel@tonic-gate first_list.type - second_list.type); 538*7c478bd9Sstevel@tonic-gate e->flag |= VISITED_F; 539*7c478bd9Sstevel@tonic-gate } 540*7c478bd9Sstevel@tonic-gate } 541*7c478bd9Sstevel@tonic-gate } 542*7c478bd9Sstevel@tonic-gate } 543*7c478bd9Sstevel@tonic-gate 544*7c478bd9Sstevel@tonic-gate static int 545*7c478bd9Sstevel@tonic-gate read_in_file(const char *file_name, elem_list *list) 546*7c478bd9Sstevel@tonic-gate { 547*7c478bd9Sstevel@tonic-gate struct stat st_buf; 548*7c478bd9Sstevel@tonic-gate int count = 0; 549*7c478bd9Sstevel@tonic-gate 550*7c478bd9Sstevel@tonic-gate if (stat(file_name, &st_buf) == 0) { 551*7c478bd9Sstevel@tonic-gate if (S_ISREG(st_buf.st_mode)) { 552*7c478bd9Sstevel@tonic-gate if (verbose) { 553*7c478bd9Sstevel@tonic-gate (void) printf("file(%s): trying to process " 554*7c478bd9Sstevel@tonic-gate "as protolist...\n", file_name); 555*7c478bd9Sstevel@tonic-gate } 556*7c478bd9Sstevel@tonic-gate count = read_in_protolist(file_name, list, verbose); 557*7c478bd9Sstevel@tonic-gate } else if (S_ISDIR(st_buf.st_mode)) { 558*7c478bd9Sstevel@tonic-gate if (verbose) 559*7c478bd9Sstevel@tonic-gate (void) printf("directory(%s): trying to " 560*7c478bd9Sstevel@tonic-gate "process as protodir...\n", file_name); 561*7c478bd9Sstevel@tonic-gate count = read_in_protodir(file_name, list, verbose); 562*7c478bd9Sstevel@tonic-gate } else { 563*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 564*7c478bd9Sstevel@tonic-gate "%s not a file or a directory.\n", file_name); 565*7c478bd9Sstevel@tonic-gate usage(); 566*7c478bd9Sstevel@tonic-gate exit(1); 567*7c478bd9Sstevel@tonic-gate } 568*7c478bd9Sstevel@tonic-gate } else { 569*7c478bd9Sstevel@tonic-gate perror(file_name); 570*7c478bd9Sstevel@tonic-gate usage(); 571*7c478bd9Sstevel@tonic-gate exit(1); 572*7c478bd9Sstevel@tonic-gate } 573*7c478bd9Sstevel@tonic-gate 574*7c478bd9Sstevel@tonic-gate return (count); 575*7c478bd9Sstevel@tonic-gate } 576*7c478bd9Sstevel@tonic-gate 577*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 578*7c478bd9Sstevel@tonic-gate static int 579*7c478bd9Sstevel@tonic-gate set_values(const char *fname, const struct stat *sbp, int otype, 580*7c478bd9Sstevel@tonic-gate struct FTW *ftw) 581*7c478bd9Sstevel@tonic-gate { 582*7c478bd9Sstevel@tonic-gate elem *ep; 583*7c478bd9Sstevel@tonic-gate uid_t uid; 584*7c478bd9Sstevel@tonic-gate gid_t gid; 585*7c478bd9Sstevel@tonic-gate elem keyelem; 586*7c478bd9Sstevel@tonic-gate mode_t perm; 587*7c478bd9Sstevel@tonic-gate 588*7c478bd9Sstevel@tonic-gate if (fname[0] == '\0' || fname[1] == '\0' || fname[2] == '\0') 589*7c478bd9Sstevel@tonic-gate return (0); 590*7c478bd9Sstevel@tonic-gate /* skip leading "./" */ 591*7c478bd9Sstevel@tonic-gate fname += 2; 592*7c478bd9Sstevel@tonic-gate switch (otype) { 593*7c478bd9Sstevel@tonic-gate case FTW_F: 594*7c478bd9Sstevel@tonic-gate case FTW_D: 595*7c478bd9Sstevel@tonic-gate case FTW_DP: 596*7c478bd9Sstevel@tonic-gate if (strlcpy(keyelem.name, fname, sizeof (keyelem.name)) >= 597*7c478bd9Sstevel@tonic-gate sizeof (keyelem.name)) { 598*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s: name too long\n", 599*7c478bd9Sstevel@tonic-gate myname, fname); 600*7c478bd9Sstevel@tonic-gate return (1); 601*7c478bd9Sstevel@tonic-gate } 602*7c478bd9Sstevel@tonic-gate keyelem.arch = P_ISA; 603*7c478bd9Sstevel@tonic-gate ep = find_elem(&first_list, &keyelem, NO_FOLLOW_LINK); 604*7c478bd9Sstevel@tonic-gate if (ep == NULL) { 605*7c478bd9Sstevel@tonic-gate ep = find_elem_mach(&first_list, &keyelem, 606*7c478bd9Sstevel@tonic-gate NO_FOLLOW_LINK); 607*7c478bd9Sstevel@tonic-gate } 608*7c478bd9Sstevel@tonic-gate /* 609*7c478bd9Sstevel@tonic-gate * Do nothing if this is a hard or symbolic link, 610*7c478bd9Sstevel@tonic-gate * since links don't have this information. 611*7c478bd9Sstevel@tonic-gate * 612*7c478bd9Sstevel@tonic-gate * Assume it's a file on the exception list if it's 613*7c478bd9Sstevel@tonic-gate * not found in the packaging. Those are root:bin 755. 614*7c478bd9Sstevel@tonic-gate */ 615*7c478bd9Sstevel@tonic-gate if (ep != NULL && 616*7c478bd9Sstevel@tonic-gate (ep->file_type == SYM_LINK_T || ep->file_type == LINK_T)) { 617*7c478bd9Sstevel@tonic-gate return (0); 618*7c478bd9Sstevel@tonic-gate } 619*7c478bd9Sstevel@tonic-gate if (!set_group) { 620*7c478bd9Sstevel@tonic-gate gid = -1; 621*7c478bd9Sstevel@tonic-gate } else if (ep == NULL) { 622*7c478bd9Sstevel@tonic-gate gid = 0; 623*7c478bd9Sstevel@tonic-gate } else if ((gid = stdfind(ep->group, groupnames)) == -1) { 624*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s: group '%s' unknown\n", 625*7c478bd9Sstevel@tonic-gate myname, fname, ep->group); 626*7c478bd9Sstevel@tonic-gate return (1); 627*7c478bd9Sstevel@tonic-gate } 628*7c478bd9Sstevel@tonic-gate if (!set_user) { 629*7c478bd9Sstevel@tonic-gate uid = -1; 630*7c478bd9Sstevel@tonic-gate } else if (ep == NULL) { 631*7c478bd9Sstevel@tonic-gate uid = 2; 632*7c478bd9Sstevel@tonic-gate } else if ((uid = stdfind(ep->owner, usernames)) == -1) { 633*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s: user '%s' unknown\n", 634*7c478bd9Sstevel@tonic-gate myname, fname, ep->owner); 635*7c478bd9Sstevel@tonic-gate return (1); 636*7c478bd9Sstevel@tonic-gate } 637*7c478bd9Sstevel@tonic-gate if ((set_group && gid != -1 && gid != sbp->st_gid) || 638*7c478bd9Sstevel@tonic-gate (set_user && uid != -1 && uid != sbp->st_uid)) { 639*7c478bd9Sstevel@tonic-gate if (verbose) { 640*7c478bd9Sstevel@tonic-gate const char *owner, *group; 641*7c478bd9Sstevel@tonic-gate 642*7c478bd9Sstevel@tonic-gate owner = ep == NULL ? "root" : ep->owner; 643*7c478bd9Sstevel@tonic-gate group = ep == NULL ? "bin" : ep->group; 644*7c478bd9Sstevel@tonic-gate if (set_group && set_user) { 645*7c478bd9Sstevel@tonic-gate (void) printf("chown %s:%s %s\n", 646*7c478bd9Sstevel@tonic-gate owner, group, fname); 647*7c478bd9Sstevel@tonic-gate } else if (set_user) { 648*7c478bd9Sstevel@tonic-gate (void) printf("chown %s %s\n", owner, 649*7c478bd9Sstevel@tonic-gate fname); 650*7c478bd9Sstevel@tonic-gate } else { 651*7c478bd9Sstevel@tonic-gate (void) printf("chgrp %s %s\n", group, 652*7c478bd9Sstevel@tonic-gate fname); 653*7c478bd9Sstevel@tonic-gate } 654*7c478bd9Sstevel@tonic-gate } 655*7c478bd9Sstevel@tonic-gate if (lchown(fname, uid, gid) == -1) { 656*7c478bd9Sstevel@tonic-gate perror(fname); 657*7c478bd9Sstevel@tonic-gate return (1); 658*7c478bd9Sstevel@tonic-gate } 659*7c478bd9Sstevel@tonic-gate } 660*7c478bd9Sstevel@tonic-gate perm = ep == NULL ? 0755 : ep->perm; 661*7c478bd9Sstevel@tonic-gate if (set_perm && ((perm ^ sbp->st_mode) & ~S_IFMT) != 0) { 662*7c478bd9Sstevel@tonic-gate if (verbose) 663*7c478bd9Sstevel@tonic-gate (void) printf("chmod %lo %s\n", perm, fname); 664*7c478bd9Sstevel@tonic-gate if (chmod(fname, perm) == -1) { 665*7c478bd9Sstevel@tonic-gate perror(fname); 666*7c478bd9Sstevel@tonic-gate return (1); 667*7c478bd9Sstevel@tonic-gate } 668*7c478bd9Sstevel@tonic-gate } 669*7c478bd9Sstevel@tonic-gate return (0); 670*7c478bd9Sstevel@tonic-gate case FTW_DNR: 671*7c478bd9Sstevel@tonic-gate case FTW_NS: 672*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s: permission denied\n", 673*7c478bd9Sstevel@tonic-gate myname, fname); 674*7c478bd9Sstevel@tonic-gate return (1); 675*7c478bd9Sstevel@tonic-gate case FTW_SL: 676*7c478bd9Sstevel@tonic-gate case FTW_SLN: 677*7c478bd9Sstevel@tonic-gate return (0); 678*7c478bd9Sstevel@tonic-gate default: 679*7c478bd9Sstevel@tonic-gate return (1); 680*7c478bd9Sstevel@tonic-gate } 681*7c478bd9Sstevel@tonic-gate } 682*7c478bd9Sstevel@tonic-gate 683*7c478bd9Sstevel@tonic-gate int 684*7c478bd9Sstevel@tonic-gate main(int argc, char **argv) 685*7c478bd9Sstevel@tonic-gate { 686*7c478bd9Sstevel@tonic-gate int errflg = 0; 687*7c478bd9Sstevel@tonic-gate int i, c; 688*7c478bd9Sstevel@tonic-gate int list_filtered_exceptions = NULL; 689*7c478bd9Sstevel@tonic-gate int n_proto_refs = 0; 690*7c478bd9Sstevel@tonic-gate int n_exception_files = 0; 691*7c478bd9Sstevel@tonic-gate char *proto_refs[MAX_PROTO_REFS]; 692*7c478bd9Sstevel@tonic-gate char *exception_files[MAX_EXCEPTION_FILES]; 693*7c478bd9Sstevel@tonic-gate struct stat st_buf; 694*7c478bd9Sstevel@tonic-gate 695*7c478bd9Sstevel@tonic-gate if ((myname = argv[0]) == NULL) 696*7c478bd9Sstevel@tonic-gate myname = "protocmp"; 697*7c478bd9Sstevel@tonic-gate 698*7c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "gupGUPlmsLe:vd:")) != EOF) { 699*7c478bd9Sstevel@tonic-gate switch (c) { 700*7c478bd9Sstevel@tonic-gate case 's': 701*7c478bd9Sstevel@tonic-gate check_sym = 0; 702*7c478bd9Sstevel@tonic-gate break; 703*7c478bd9Sstevel@tonic-gate case 'm': 704*7c478bd9Sstevel@tonic-gate check_majmin = 0; 705*7c478bd9Sstevel@tonic-gate break; 706*7c478bd9Sstevel@tonic-gate case 'g': 707*7c478bd9Sstevel@tonic-gate check_group = 0; 708*7c478bd9Sstevel@tonic-gate break; 709*7c478bd9Sstevel@tonic-gate case 'G': 710*7c478bd9Sstevel@tonic-gate set_group = 1; 711*7c478bd9Sstevel@tonic-gate break; 712*7c478bd9Sstevel@tonic-gate case 'u': 713*7c478bd9Sstevel@tonic-gate check_user = 0; 714*7c478bd9Sstevel@tonic-gate break; 715*7c478bd9Sstevel@tonic-gate case 'U': 716*7c478bd9Sstevel@tonic-gate set_user = 1; 717*7c478bd9Sstevel@tonic-gate break; 718*7c478bd9Sstevel@tonic-gate case 'l': 719*7c478bd9Sstevel@tonic-gate check_link = 0; 720*7c478bd9Sstevel@tonic-gate break; 721*7c478bd9Sstevel@tonic-gate case 'p': 722*7c478bd9Sstevel@tonic-gate check_perm = 0; 723*7c478bd9Sstevel@tonic-gate break; 724*7c478bd9Sstevel@tonic-gate case 'P': 725*7c478bd9Sstevel@tonic-gate set_perm = 1; 726*7c478bd9Sstevel@tonic-gate break; 727*7c478bd9Sstevel@tonic-gate case 'e': 728*7c478bd9Sstevel@tonic-gate if (n_exception_files >= MAX_EXCEPTION_FILES) { 729*7c478bd9Sstevel@tonic-gate errflg++; 730*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 731*7c478bd9Sstevel@tonic-gate "Only %d exception files supported\n", 732*7c478bd9Sstevel@tonic-gate MAX_EXCEPTION_FILES); 733*7c478bd9Sstevel@tonic-gate } else { 734*7c478bd9Sstevel@tonic-gate exception_files[n_exception_files++] = optarg; 735*7c478bd9Sstevel@tonic-gate } 736*7c478bd9Sstevel@tonic-gate break; 737*7c478bd9Sstevel@tonic-gate case 'L': 738*7c478bd9Sstevel@tonic-gate list_filtered_exceptions++; 739*7c478bd9Sstevel@tonic-gate break; 740*7c478bd9Sstevel@tonic-gate case 'v': 741*7c478bd9Sstevel@tonic-gate verbose++; 742*7c478bd9Sstevel@tonic-gate break; 743*7c478bd9Sstevel@tonic-gate case 'd': 744*7c478bd9Sstevel@tonic-gate if (n_proto_refs >= MAX_PROTO_REFS) { 745*7c478bd9Sstevel@tonic-gate errflg++; 746*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 747*7c478bd9Sstevel@tonic-gate "Only %d proto references supported\n", 748*7c478bd9Sstevel@tonic-gate MAX_PROTO_REFS); 749*7c478bd9Sstevel@tonic-gate } else { 750*7c478bd9Sstevel@tonic-gate proto_refs[n_proto_refs++] = optarg; 751*7c478bd9Sstevel@tonic-gate } 752*7c478bd9Sstevel@tonic-gate break; 753*7c478bd9Sstevel@tonic-gate case '?': 754*7c478bd9Sstevel@tonic-gate default: 755*7c478bd9Sstevel@tonic-gate errflg++; 756*7c478bd9Sstevel@tonic-gate break; 757*7c478bd9Sstevel@tonic-gate } 758*7c478bd9Sstevel@tonic-gate } 759*7c478bd9Sstevel@tonic-gate 760*7c478bd9Sstevel@tonic-gate if (argc == optind || n_proto_refs == 0) { 761*7c478bd9Sstevel@tonic-gate usage(); 762*7c478bd9Sstevel@tonic-gate exit(1); 763*7c478bd9Sstevel@tonic-gate } 764*7c478bd9Sstevel@tonic-gate 765*7c478bd9Sstevel@tonic-gate if (set_group || set_user || set_perm) { 766*7c478bd9Sstevel@tonic-gate if (optind != argc - 1) { 767*7c478bd9Sstevel@tonic-gate usage(); 768*7c478bd9Sstevel@tonic-gate exit(1); 769*7c478bd9Sstevel@tonic-gate } 770*7c478bd9Sstevel@tonic-gate if (stat(argv[optind], &st_buf) == -1) { 771*7c478bd9Sstevel@tonic-gate perror(argv[optind]); 772*7c478bd9Sstevel@tonic-gate exit(1); 773*7c478bd9Sstevel@tonic-gate } 774*7c478bd9Sstevel@tonic-gate if (!S_ISDIR(st_buf.st_mode)) { 775*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s: not a directory\n", 776*7c478bd9Sstevel@tonic-gate myname, argv[optind]); 777*7c478bd9Sstevel@tonic-gate exit(1); 778*7c478bd9Sstevel@tonic-gate } 779*7c478bd9Sstevel@tonic-gate } 780*7c478bd9Sstevel@tonic-gate 781*7c478bd9Sstevel@tonic-gate init_list(&first_list, HASH_SIZE); 782*7c478bd9Sstevel@tonic-gate init_list(&second_list, HASH_SIZE); 783*7c478bd9Sstevel@tonic-gate init_list(&exception_list, HASH_SIZE); 784*7c478bd9Sstevel@tonic-gate 785*7c478bd9Sstevel@tonic-gate for (i = 0; i < n_exception_files; i++) { 786*7c478bd9Sstevel@tonic-gate (void) read_in_exceptions(exception_files[i], verbose); 787*7c478bd9Sstevel@tonic-gate } 788*7c478bd9Sstevel@tonic-gate 789*7c478bd9Sstevel@tonic-gate for (i = 0; i < n_proto_refs; i++) { 790*7c478bd9Sstevel@tonic-gate first_file_name = proto_refs[i]; 791*7c478bd9Sstevel@tonic-gate (void) read_in_file(first_file_name, &first_list); 792*7c478bd9Sstevel@tonic-gate } 793*7c478bd9Sstevel@tonic-gate 794*7c478bd9Sstevel@tonic-gate if (set_group || set_user || set_perm) { 795*7c478bd9Sstevel@tonic-gate if (chdir(argv[optind]) == -1) { 796*7c478bd9Sstevel@tonic-gate perror(argv[optind]); 797*7c478bd9Sstevel@tonic-gate exit(1); 798*7c478bd9Sstevel@tonic-gate } 799*7c478bd9Sstevel@tonic-gate i = nftw(".", set_values, MAX_DEPTH, FTW_PHYS|FTW_DEPTH); 800*7c478bd9Sstevel@tonic-gate if (i == -1) { 801*7c478bd9Sstevel@tonic-gate perror("nftw"); 802*7c478bd9Sstevel@tonic-gate i = 1; 803*7c478bd9Sstevel@tonic-gate } 804*7c478bd9Sstevel@tonic-gate exit(i); 805*7c478bd9Sstevel@tonic-gate } 806*7c478bd9Sstevel@tonic-gate 807*7c478bd9Sstevel@tonic-gate for (i = optind; i < argc; i++) { 808*7c478bd9Sstevel@tonic-gate second_file_name = argv[i]; 809*7c478bd9Sstevel@tonic-gate (void) read_in_file(second_file_name, &second_list); 810*7c478bd9Sstevel@tonic-gate } 811*7c478bd9Sstevel@tonic-gate 812*7c478bd9Sstevel@tonic-gate open_output_files(); 813*7c478bd9Sstevel@tonic-gate 814*7c478bd9Sstevel@tonic-gate if (verbose) 815*7c478bd9Sstevel@tonic-gate (void) puts("comparing build to packages..."); 816*7c478bd9Sstevel@tonic-gate 817*7c478bd9Sstevel@tonic-gate check_first_vs_second(list_filtered_exceptions); 818*7c478bd9Sstevel@tonic-gate 819*7c478bd9Sstevel@tonic-gate if (verbose) 820*7c478bd9Sstevel@tonic-gate (void) puts("checking over packages..."); 821*7c478bd9Sstevel@tonic-gate check_second_vs_first(list_filtered_exceptions); 822*7c478bd9Sstevel@tonic-gate 823*7c478bd9Sstevel@tonic-gate close_output_files(); 824*7c478bd9Sstevel@tonic-gate 825*7c478bd9Sstevel@tonic-gate print_results(); 826*7c478bd9Sstevel@tonic-gate 827*7c478bd9Sstevel@tonic-gate clean_up(); 828*7c478bd9Sstevel@tonic-gate 829*7c478bd9Sstevel@tonic-gate return (0); 830*7c478bd9Sstevel@tonic-gate } 831