17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #include <stdio.h> 287c478bd9Sstevel@tonic-gate #include <fcntl.h> 297c478bd9Sstevel@tonic-gate #include <stdlib.h> 307c478bd9Sstevel@tonic-gate #include <string.h> 317c478bd9Sstevel@tonic-gate #include <sys/types.h> 327c478bd9Sstevel@tonic-gate #include <sys/stat.h> 337c478bd9Sstevel@tonic-gate #include <dirent.h> 347c478bd9Sstevel@tonic-gate #include <sys/param.h> 357c478bd9Sstevel@tonic-gate #include <errno.h> 367c478bd9Sstevel@tonic-gate #include <unistd.h> 377c478bd9Sstevel@tonic-gate #include <ftw.h> 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate #include "list.h" 407c478bd9Sstevel@tonic-gate #include "protocmp.h" 417c478bd9Sstevel@tonic-gate #include "proto_list.h" 427c478bd9Sstevel@tonic-gate #include "protodir.h" 437c478bd9Sstevel@tonic-gate #include "exception_list.h" 447c478bd9Sstevel@tonic-gate #include "stdusers.h" 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate #define MAX_PROTO_REFS 5 477c478bd9Sstevel@tonic-gate #define MAX_EXCEPTION_FILES 5 487c478bd9Sstevel@tonic-gate #define MAX_DEPTH 50 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate /* 517c478bd9Sstevel@tonic-gate * default flag values 527c478bd9Sstevel@tonic-gate */ 537c478bd9Sstevel@tonic-gate static int check_group = 1; 547c478bd9Sstevel@tonic-gate static int set_group = 0; 557c478bd9Sstevel@tonic-gate static int check_user = 1; 567c478bd9Sstevel@tonic-gate static int set_user = 0; 577c478bd9Sstevel@tonic-gate static int check_perm = 1; 587c478bd9Sstevel@tonic-gate static int set_perm = 0; 597c478bd9Sstevel@tonic-gate static int check_link = 1; 607c478bd9Sstevel@tonic-gate static int check_sym = 1; 617c478bd9Sstevel@tonic-gate static int check_majmin = 1; 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate static elem_list first_list; 647c478bd9Sstevel@tonic-gate static char *first_file_name; 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate static elem_list second_list; 677c478bd9Sstevel@tonic-gate static char *second_file_name; 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate static FILE *need_add_fp; 707c478bd9Sstevel@tonic-gate static char *need_add_file; 717c478bd9Sstevel@tonic-gate static FILE *need_rm_fp; 727c478bd9Sstevel@tonic-gate static char *need_rm_file; 737c478bd9Sstevel@tonic-gate static FILE *differ_fp; 747c478bd9Sstevel@tonic-gate static char *differ_file; 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate static char *myname; 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate /* 797c478bd9Sstevel@tonic-gate * default flag values 807c478bd9Sstevel@tonic-gate */ 817c478bd9Sstevel@tonic-gate static int verbose = 0; 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate static void 847c478bd9Sstevel@tonic-gate usage(void) 857c478bd9Sstevel@tonic-gate { 867c478bd9Sstevel@tonic-gate (void) fputs("usage: protocmp [-gupGUPlmsLv] " 877c478bd9Sstevel@tonic-gate "[-e <exception-list> ...] " 887c478bd9Sstevel@tonic-gate "-d <protolist|pkg dir>\n\t[-d <protolist|pkg dir> ...] " 897c478bd9Sstevel@tonic-gate "[<protolist|pkg dir>...]|<root>]\n", 907c478bd9Sstevel@tonic-gate stderr); 917c478bd9Sstevel@tonic-gate (void) fputs(" where:\n", stderr); 927c478bd9Sstevel@tonic-gate (void) fputs("\t-g : don't compare group\n", stderr); 937c478bd9Sstevel@tonic-gate (void) fputs("\t-u : don't compare owner\n", stderr); 947c478bd9Sstevel@tonic-gate (void) fputs("\t-p : don't compare permissions\n", stderr); 957c478bd9Sstevel@tonic-gate (void) fputs("\t-G : set group\n", stderr); 967c478bd9Sstevel@tonic-gate (void) fputs("\t-U : set owner\n", stderr); 977c478bd9Sstevel@tonic-gate (void) fputs("\t-P : set permissions\n", stderr); 987c478bd9Sstevel@tonic-gate (void) fputs("\t-l : don't compare link counts\n", stderr); 997c478bd9Sstevel@tonic-gate (void) fputs("\t-m : don't compare major/minor numbers\n", 1007c478bd9Sstevel@tonic-gate stderr); 1017c478bd9Sstevel@tonic-gate (void) fputs("\t-s : don't compare symlink values\n", stderr); 1027c478bd9Sstevel@tonic-gate (void) fputs("\t-d <protolist|pkg dir>:\n", stderr); 1037c478bd9Sstevel@tonic-gate (void) fputs("\t proto list or packaging to check\n", stderr); 1047c478bd9Sstevel@tonic-gate (void) fputs("\t-e <file>: exceptions file\n", stderr); 1057c478bd9Sstevel@tonic-gate (void) fputs("\t-L : list filtered exceptions\n", stderr); 1067c478bd9Sstevel@tonic-gate (void) fputs("\t-v : verbose output\n", stderr); 1077c478bd9Sstevel@tonic-gate (void) fputs("\n" 1087c478bd9Sstevel@tonic-gate "If any of the -[GUP] flags are given, then the final argument must be the\n" 1097c478bd9Sstevel@tonic-gate "proto root directory itself on which to set permissions according to the\n" 1107c478bd9Sstevel@tonic-gate "packaging data specified via -d options.\n", stderr); 1117c478bd9Sstevel@tonic-gate } 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate static void 1157c478bd9Sstevel@tonic-gate open_output_files(void) 1167c478bd9Sstevel@tonic-gate { 1177c478bd9Sstevel@tonic-gate if ((need_add_fp = 1187c478bd9Sstevel@tonic-gate fopen((need_add_file = tempnam(NULL, "add")), "w")) == NULL) { 1197c478bd9Sstevel@tonic-gate perror(need_add_file); 1207c478bd9Sstevel@tonic-gate exit(1); 1217c478bd9Sstevel@tonic-gate } 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate if ((need_rm_fp = 1247c478bd9Sstevel@tonic-gate fopen((need_rm_file = tempnam(NULL, "rm")), "w")) == NULL) { 1257c478bd9Sstevel@tonic-gate perror(need_rm_file); 1267c478bd9Sstevel@tonic-gate exit(1); 1277c478bd9Sstevel@tonic-gate } 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate if ((differ_fp = 1307c478bd9Sstevel@tonic-gate fopen((differ_file = tempnam(NULL, "diff")), "w")) == NULL) { 1317c478bd9Sstevel@tonic-gate perror(differ_file); 1327c478bd9Sstevel@tonic-gate exit(1); 1337c478bd9Sstevel@tonic-gate } 1347c478bd9Sstevel@tonic-gate } 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate static void 1377c478bd9Sstevel@tonic-gate close_output_files(void) 1387c478bd9Sstevel@tonic-gate { 1397c478bd9Sstevel@tonic-gate (void) fclose(need_add_fp); 1407c478bd9Sstevel@tonic-gate (void) fclose(need_rm_fp); 1417c478bd9Sstevel@tonic-gate (void) fclose(differ_fp); 1427c478bd9Sstevel@tonic-gate } 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate static void 1457c478bd9Sstevel@tonic-gate print_file(char *file) 1467c478bd9Sstevel@tonic-gate { 1477c478bd9Sstevel@tonic-gate FILE *fp; 1487c478bd9Sstevel@tonic-gate int count; 1497c478bd9Sstevel@tonic-gate char buff[BUF_SIZE]; 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate if ((fp = fopen(file, "r")) == NULL) { 1527c478bd9Sstevel@tonic-gate perror(need_add_file); 1537c478bd9Sstevel@tonic-gate } 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate while (count = fread(buff, sizeof (char), BUF_SIZE, fp)) 1567c478bd9Sstevel@tonic-gate (void) fwrite(buff, sizeof (char), count, stdout); 1577c478bd9Sstevel@tonic-gate (void) fclose(fp); 1587c478bd9Sstevel@tonic-gate } 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate static void 1617c478bd9Sstevel@tonic-gate print_header(void) 1627c478bd9Sstevel@tonic-gate { 1637c478bd9Sstevel@tonic-gate (void) printf("%c %-30s %-20s %-4s %-5s %-5s %-5s %-2s %2s %2s %-9s\n", 1647c478bd9Sstevel@tonic-gate 'T', "File Name", "Reloc/Sym name", "perm", "owner", "group", 1657c478bd9Sstevel@tonic-gate "inode", "lnk", "maj", "min", "package(s)"); 1667c478bd9Sstevel@tonic-gate (void) puts("-------------------------------------------------------" 1677c478bd9Sstevel@tonic-gate "-----------------------------------------------------"); 1687c478bd9Sstevel@tonic-gate } 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate static void 1717c478bd9Sstevel@tonic-gate print_results(void) 1727c478bd9Sstevel@tonic-gate { 1737c478bd9Sstevel@tonic-gate (void) puts("*******************************************************"); 1747c478bd9Sstevel@tonic-gate (void) puts("*"); 1757c478bd9Sstevel@tonic-gate (void) printf("* Entries found in %s, but not found in %s\n", 1767c478bd9Sstevel@tonic-gate first_file_name, second_file_name); 1777c478bd9Sstevel@tonic-gate (void) puts("*"); 1787c478bd9Sstevel@tonic-gate (void) puts("*******************************************************"); 1797c478bd9Sstevel@tonic-gate print_header(); 1807c478bd9Sstevel@tonic-gate print_file(need_add_file); 1817c478bd9Sstevel@tonic-gate (void) puts("*******************************************************"); 1827c478bd9Sstevel@tonic-gate (void) puts("*"); 1837c478bd9Sstevel@tonic-gate (void) printf("* Entries found in %s, but not found in %s\n", 1847c478bd9Sstevel@tonic-gate second_file_name, first_file_name); 1857c478bd9Sstevel@tonic-gate (void) puts("*"); 1867c478bd9Sstevel@tonic-gate (void) puts("*******************************************************"); 1877c478bd9Sstevel@tonic-gate print_header(); 1887c478bd9Sstevel@tonic-gate print_file(need_rm_file); 1897c478bd9Sstevel@tonic-gate (void) puts("*******************************************************"); 1907c478bd9Sstevel@tonic-gate (void) puts("*"); 1917c478bd9Sstevel@tonic-gate (void) printf("* Entries that differ between %s and %s\n", 1927c478bd9Sstevel@tonic-gate first_file_name, second_file_name); 1937c478bd9Sstevel@tonic-gate (void) puts("*"); 1947c478bd9Sstevel@tonic-gate (void) printf("* filea == %s\n", first_file_name); 1957c478bd9Sstevel@tonic-gate (void) printf("* fileb == %s\n", second_file_name); 1967c478bd9Sstevel@tonic-gate (void) puts("*"); 1977c478bd9Sstevel@tonic-gate (void) puts("*******************************************************"); 1987c478bd9Sstevel@tonic-gate (void) fputs("Unit ", stdout); 1997c478bd9Sstevel@tonic-gate print_header(); 2007c478bd9Sstevel@tonic-gate print_file(differ_file); 2017c478bd9Sstevel@tonic-gate } 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate static void 2047c478bd9Sstevel@tonic-gate clean_up(void) 2057c478bd9Sstevel@tonic-gate { 2067c478bd9Sstevel@tonic-gate (void) unlink(need_add_file); 2077c478bd9Sstevel@tonic-gate (void) unlink(need_rm_file); 2087c478bd9Sstevel@tonic-gate (void) unlink(differ_file); 2097c478bd9Sstevel@tonic-gate } 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate /* 2127c478bd9Sstevel@tonic-gate * elem_compare(a,b) 2137c478bd9Sstevel@tonic-gate * 2147c478bd9Sstevel@tonic-gate * Args: 2157c478bd9Sstevel@tonic-gate * a - element a 2167c478bd9Sstevel@tonic-gate * b - element b 2177c478bd9Sstevel@tonic-gate * different_types - 2187c478bd9Sstevel@tonic-gate * value = 0 -> comparing two elements of same 2197c478bd9Sstevel@tonic-gate * type (eg: protodir elem vs. protodir elem). 2207c478bd9Sstevel@tonic-gate * value != 0 -> comparing two elements of different type 2217c478bd9Sstevel@tonic-gate * (eg: protodir elem vs. protolist elem). 2227c478bd9Sstevel@tonic-gate * 2237c478bd9Sstevel@tonic-gate * Returns: 2247c478bd9Sstevel@tonic-gate * 0 - elements are identical 2257c478bd9Sstevel@tonic-gate * >0 - elements differ 2267c478bd9Sstevel@tonic-gate * check flags to see which fields differ. 2277c478bd9Sstevel@tonic-gate */ 2287c478bd9Sstevel@tonic-gate static int 2297c478bd9Sstevel@tonic-gate elem_compare(elem *a, elem *b, int different_types) 2307c478bd9Sstevel@tonic-gate { 2317c478bd9Sstevel@tonic-gate int res = 0; 2327c478bd9Sstevel@tonic-gate elem *i, *j; 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate /* 2357c478bd9Sstevel@tonic-gate * if these are hard links to other files - those are the 2367c478bd9Sstevel@tonic-gate * files that should be compared. 2377c478bd9Sstevel@tonic-gate */ 2387c478bd9Sstevel@tonic-gate i = a->link_parent ? a->link_parent : a; 2397c478bd9Sstevel@tonic-gate j = b->link_parent ? b->link_parent : b; 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate /* 2427c478bd9Sstevel@tonic-gate * We do not compare inodes - they always differ. 2437c478bd9Sstevel@tonic-gate * We do not compare names because we assume that was 2447c478bd9Sstevel@tonic-gate * checked before. 2457c478bd9Sstevel@tonic-gate */ 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate /* 2487c478bd9Sstevel@tonic-gate * Special rules for comparison: 2497c478bd9Sstevel@tonic-gate * 2507c478bd9Sstevel@tonic-gate * 1) if directory - ignore ref_cnt. 2517c478bd9Sstevel@tonic-gate * 2) if sym_link - only check file_type & symlink 2527c478bd9Sstevel@tonic-gate * 3) elem type of FILE_T, EDIT_T, & VOLATILE_T are equivilant when 2537c478bd9Sstevel@tonic-gate * comparing a protodir entry to a protolist entry. 2547c478bd9Sstevel@tonic-gate */ 2557c478bd9Sstevel@tonic-gate if (i->file_type != j->file_type) { 2567c478bd9Sstevel@tonic-gate if (different_types) { 2577c478bd9Sstevel@tonic-gate /* 2587c478bd9Sstevel@tonic-gate * Check to see if filetypes are FILE_T vs. 2597c478bd9Sstevel@tonic-gate * EDIT_T/VOLATILE_T/LINK_T comparisons. 2607c478bd9Sstevel@tonic-gate */ 2617c478bd9Sstevel@tonic-gate if ((i->file_type == FILE_T) && 2627c478bd9Sstevel@tonic-gate ((j->file_type == EDIT_T) || 2637c478bd9Sstevel@tonic-gate (j->file_type == VOLATILE_T) || 2647c478bd9Sstevel@tonic-gate (j->file_type == LINK_T))) { 2657c478bd9Sstevel@tonic-gate /*EMPTY*/ 2667c478bd9Sstevel@tonic-gate } else if ((j->file_type == FILE_T) && 2677c478bd9Sstevel@tonic-gate ((i->file_type == EDIT_T) || 2687c478bd9Sstevel@tonic-gate (i->file_type == VOLATILE_T) || 2697c478bd9Sstevel@tonic-gate (i->file_type == LINK_T))) { 2707c478bd9Sstevel@tonic-gate /*EMPTY*/ 2717c478bd9Sstevel@tonic-gate } else 2727c478bd9Sstevel@tonic-gate res |= TYPE_F; 2737c478bd9Sstevel@tonic-gate } else 2747c478bd9Sstevel@tonic-gate res |= TYPE_F; 2757c478bd9Sstevel@tonic-gate } 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate /* 2787c478bd9Sstevel@tonic-gate * if symlink - check the symlink value and then 2797c478bd9Sstevel@tonic-gate * return. symlink is the only field of concern 2807c478bd9Sstevel@tonic-gate * in SYMLINKS. 2817c478bd9Sstevel@tonic-gate */ 2827c478bd9Sstevel@tonic-gate if (check_sym && ((res == 0) && (i->file_type == SYM_LINK_T))) { 2837c478bd9Sstevel@tonic-gate if ((!i->symsrc) || (!j->symsrc)) 2847c478bd9Sstevel@tonic-gate res |= SYM_F; 2857c478bd9Sstevel@tonic-gate else { 2867c478bd9Sstevel@tonic-gate /* 2877c478bd9Sstevel@tonic-gate * if either symlink starts with a './' strip it off, 28863360950Smp204432 * its irrelevant. 2897c478bd9Sstevel@tonic-gate */ 2907c478bd9Sstevel@tonic-gate if ((i->symsrc[0] == '.') && (i->symsrc[1] == '/')) 2917c478bd9Sstevel@tonic-gate i->symsrc += 2; 2927c478bd9Sstevel@tonic-gate if ((j->symsrc[0] == '.') && (j->symsrc[1] == '/')) 2937c478bd9Sstevel@tonic-gate j->symsrc += 2; 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate if (strncmp(i->symsrc, j->symsrc, MAXNAME) != 0) 2967c478bd9Sstevel@tonic-gate res |= SYM_F; 2977c478bd9Sstevel@tonic-gate } 2987c478bd9Sstevel@tonic-gate return (res); 2997c478bd9Sstevel@tonic-gate } 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate if ((i->file_type != DIR_T) && check_link && 3027c478bd9Sstevel@tonic-gate (i->ref_cnt != j->ref_cnt)) 3037c478bd9Sstevel@tonic-gate res |= REF_F; 3047c478bd9Sstevel@tonic-gate if (check_user && (strncmp(i->owner, j->owner, TYPESIZE) != 0)) 3057c478bd9Sstevel@tonic-gate res |= OWNER_F; 3067c478bd9Sstevel@tonic-gate if (check_group && (strncmp(i->group, j->group, TYPESIZE) != 0)) 3077c478bd9Sstevel@tonic-gate res |= GROUP_F; 3087c478bd9Sstevel@tonic-gate if (check_perm && (i->perm != j->perm)) 3097c478bd9Sstevel@tonic-gate res |= PERM_F; 3107c478bd9Sstevel@tonic-gate if (check_majmin && ((i->major != j->major) || (i->minor != j->minor))) 3117c478bd9Sstevel@tonic-gate res |= MAJMIN_F; 3127c478bd9Sstevel@tonic-gate 3137c478bd9Sstevel@tonic-gate return (res); 3147c478bd9Sstevel@tonic-gate } 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate static void 3177c478bd9Sstevel@tonic-gate print_elem(FILE *fp, elem *e) 3187c478bd9Sstevel@tonic-gate { 3197c478bd9Sstevel@tonic-gate elem p; 3207c478bd9Sstevel@tonic-gate pkg_list *l; 3217c478bd9Sstevel@tonic-gate char maj[TYPESIZE], min[TYPESIZE]; 3227c478bd9Sstevel@tonic-gate char perm[12], ref_cnt[12]; 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate /* 3257c478bd9Sstevel@tonic-gate * If this is a LINK to another file, then adopt 3267c478bd9Sstevel@tonic-gate * the permissions of that file. 3277c478bd9Sstevel@tonic-gate */ 3287c478bd9Sstevel@tonic-gate if (e->link_parent) { 3297c478bd9Sstevel@tonic-gate p = *((elem *)e->link_parent); 3307c478bd9Sstevel@tonic-gate (void) strcpy(p.name, e->name); 3317c478bd9Sstevel@tonic-gate p.symsrc = e->symsrc; 3327c478bd9Sstevel@tonic-gate p.file_type = e->file_type; 3337c478bd9Sstevel@tonic-gate e = &p; 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate if (!check_majmin || e->major == -1) { 3377c478bd9Sstevel@tonic-gate maj[0] = '-'; 3387c478bd9Sstevel@tonic-gate maj[1] = '\0'; 3397c478bd9Sstevel@tonic-gate } else { 3407c478bd9Sstevel@tonic-gate (void) sprintf(maj, "%d", e->major); 3417c478bd9Sstevel@tonic-gate } 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate if (!check_majmin || e->minor == -1) { 3447c478bd9Sstevel@tonic-gate min[0] = '-'; 3457c478bd9Sstevel@tonic-gate min[1] = '\0'; 3467c478bd9Sstevel@tonic-gate } else { 3477c478bd9Sstevel@tonic-gate (void) sprintf(min, "%d", e->minor); 3487c478bd9Sstevel@tonic-gate } 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate if (!check_perm) { 3517c478bd9Sstevel@tonic-gate perm[0] = '-'; 3527c478bd9Sstevel@tonic-gate perm[1] = '\0'; 3537c478bd9Sstevel@tonic-gate } else { 3547c478bd9Sstevel@tonic-gate (void) snprintf(perm, sizeof (perm), "%o", e->perm); 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate if (!check_link) { 3587c478bd9Sstevel@tonic-gate ref_cnt[0] = '-'; 3597c478bd9Sstevel@tonic-gate ref_cnt[1] = '\0'; 3607c478bd9Sstevel@tonic-gate } else { 3617c478bd9Sstevel@tonic-gate (void) snprintf(ref_cnt, sizeof (ref_cnt), "%d", e->ref_cnt); 3627c478bd9Sstevel@tonic-gate } 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%c %-30s %-20s %4s %-5s %-5s %6d %2s %2s %2s ", 3657c478bd9Sstevel@tonic-gate e->file_type, e->name, 3667c478bd9Sstevel@tonic-gate check_sym && e->symsrc != NULL ? e->symsrc : "-", perm, 3677c478bd9Sstevel@tonic-gate check_user ? e->owner : "-", 3687c478bd9Sstevel@tonic-gate check_group ? e->group : "-", 3697c478bd9Sstevel@tonic-gate e->inode, ref_cnt, maj, min); 3707c478bd9Sstevel@tonic-gate /* 3717c478bd9Sstevel@tonic-gate * dump package list - if any. 3727c478bd9Sstevel@tonic-gate */ 3737c478bd9Sstevel@tonic-gate if (!e->pkgs) 3747c478bd9Sstevel@tonic-gate (void) fputs(" proto", fp); 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate for (l = e->pkgs; l; l = l->next) { 3777c478bd9Sstevel@tonic-gate (void) fputc(' ', fp); 3787c478bd9Sstevel@tonic-gate (void) fputs(l->pkg_name, fp); 3797c478bd9Sstevel@tonic-gate } 3807c478bd9Sstevel@tonic-gate (void) fputc('\n', fp); 3817c478bd9Sstevel@tonic-gate } 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate /* 3847c478bd9Sstevel@tonic-gate * do_compare(a,b) 3857c478bd9Sstevel@tonic-gate * 3867c478bd9Sstevel@tonic-gate * Args: 3877c478bd9Sstevel@tonic-gate * different_types - see elem_compare() for explanation. 3887c478bd9Sstevel@tonic-gate */ 3897c478bd9Sstevel@tonic-gate static void 3907c478bd9Sstevel@tonic-gate do_compare(elem *a, elem *b, int different_types) 3917c478bd9Sstevel@tonic-gate { 3927c478bd9Sstevel@tonic-gate int rc; 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate if ((rc = elem_compare(a, b, different_types)) != 0) { 3957c478bd9Sstevel@tonic-gate (void) fputs("filea: ", differ_fp); 3967c478bd9Sstevel@tonic-gate print_elem(differ_fp, a); 3977c478bd9Sstevel@tonic-gate (void) fputs("fileb: ", differ_fp); 3987c478bd9Sstevel@tonic-gate print_elem(differ_fp, b); 3997c478bd9Sstevel@tonic-gate (void) fputs(" differ: ", differ_fp); 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate if (rc & SYM_F) 4027c478bd9Sstevel@tonic-gate (void) fputs("symlink", differ_fp); 4037c478bd9Sstevel@tonic-gate if (rc & PERM_F) 4047c478bd9Sstevel@tonic-gate (void) fputs("perm ", differ_fp); 4057c478bd9Sstevel@tonic-gate if (rc & REF_F) 4067c478bd9Sstevel@tonic-gate (void) fputs("ref_cnt ", differ_fp); 4077c478bd9Sstevel@tonic-gate if (rc & TYPE_F) 4087c478bd9Sstevel@tonic-gate (void) fputs("file_type ", differ_fp); 4097c478bd9Sstevel@tonic-gate if (rc & OWNER_F) 4107c478bd9Sstevel@tonic-gate (void) fputs("owner ", differ_fp); 4117c478bd9Sstevel@tonic-gate if (rc & GROUP_F) 4127c478bd9Sstevel@tonic-gate (void) fputs("group ", differ_fp); 4137c478bd9Sstevel@tonic-gate if (rc & MAJMIN_F) 4147c478bd9Sstevel@tonic-gate (void) fputs("major/minor ", differ_fp); 4157c478bd9Sstevel@tonic-gate (void) putc('\n', differ_fp); 4167c478bd9Sstevel@tonic-gate (void) putc('\n', differ_fp); 4177c478bd9Sstevel@tonic-gate } 4187c478bd9Sstevel@tonic-gate } 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate static void 4217c478bd9Sstevel@tonic-gate check_second_vs_first(int verbose) 4227c478bd9Sstevel@tonic-gate { 4237c478bd9Sstevel@tonic-gate int i; 4247c478bd9Sstevel@tonic-gate elem *cur; 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate for (i = 0; i < second_list.num_of_buckets; i++) { 4277c478bd9Sstevel@tonic-gate for (cur = second_list.list[i]; cur; cur = cur->next) { 4287c478bd9Sstevel@tonic-gate if (!(cur->flag & VISITED_F)) { 4297c478bd9Sstevel@tonic-gate if ((first_list.type != second_list.type) && 4307c478bd9Sstevel@tonic-gate find_elem(&exception_list, cur, 4317c478bd9Sstevel@tonic-gate FOLLOW_LINK)) { 4327c478bd9Sstevel@tonic-gate /* 4337c478bd9Sstevel@tonic-gate * this entry is filtered, we don't 4347c478bd9Sstevel@tonic-gate * need to do any more processing. 4357c478bd9Sstevel@tonic-gate */ 4367c478bd9Sstevel@tonic-gate if (verbose) { 4377c478bd9Sstevel@tonic-gate (void) printf( 4387c478bd9Sstevel@tonic-gate "Filtered: Need Deletion " 4397c478bd9Sstevel@tonic-gate "of:\n\t"); 4407c478bd9Sstevel@tonic-gate print_elem(stdout, cur); 4417c478bd9Sstevel@tonic-gate } 4427c478bd9Sstevel@tonic-gate continue; 4437c478bd9Sstevel@tonic-gate } 4447c478bd9Sstevel@tonic-gate /* 4457c478bd9Sstevel@tonic-gate * It is possible for arch specific files to be 4467c478bd9Sstevel@tonic-gate * found in a protodir but listed as arch 4477c478bd9Sstevel@tonic-gate * independent in a protolist file. If this is 4487c478bd9Sstevel@tonic-gate * a protodir vs. a protolist we will make 4497c478bd9Sstevel@tonic-gate * that check. 4507c478bd9Sstevel@tonic-gate */ 4517c478bd9Sstevel@tonic-gate if ((second_list.type == PROTODIR_LIST) && 4527c478bd9Sstevel@tonic-gate (cur->arch != P_ISA) && 4537c478bd9Sstevel@tonic-gate (first_list.type != PROTODIR_LIST)) { 4547c478bd9Sstevel@tonic-gate /* 4557c478bd9Sstevel@tonic-gate * do a lookup for same file, but as 4567c478bd9Sstevel@tonic-gate * type ISA. 4577c478bd9Sstevel@tonic-gate */ 4587c478bd9Sstevel@tonic-gate elem *e; 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate e = find_elem_isa(&first_list, cur, 4617c478bd9Sstevel@tonic-gate NO_FOLLOW_LINK); 4627c478bd9Sstevel@tonic-gate if (e) { 4637c478bd9Sstevel@tonic-gate do_compare(e, cur, 4647c478bd9Sstevel@tonic-gate first_list.type - 4657c478bd9Sstevel@tonic-gate second_list.type); 4667c478bd9Sstevel@tonic-gate continue; 4677c478bd9Sstevel@tonic-gate } 4687c478bd9Sstevel@tonic-gate } 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate print_elem(need_rm_fp, cur); 4717c478bd9Sstevel@tonic-gate } 4727c478bd9Sstevel@tonic-gate } 4737c478bd9Sstevel@tonic-gate } 4747c478bd9Sstevel@tonic-gate } 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate static void 4777c478bd9Sstevel@tonic-gate check_first_vs_second(int verbose) 4787c478bd9Sstevel@tonic-gate { 4797c478bd9Sstevel@tonic-gate int i; 4807c478bd9Sstevel@tonic-gate elem *e; 4817c478bd9Sstevel@tonic-gate elem *cur; 4827c478bd9Sstevel@tonic-gate 4837c478bd9Sstevel@tonic-gate for (i = 0; i < first_list.num_of_buckets; i++) { 4847c478bd9Sstevel@tonic-gate for (cur = first_list.list[i]; cur; cur = cur->next) { 4857c478bd9Sstevel@tonic-gate if ((first_list.type != second_list.type) && 4867c478bd9Sstevel@tonic-gate find_elem(&exception_list, cur, FOLLOW_LINK)) { 4877c478bd9Sstevel@tonic-gate /* 4887c478bd9Sstevel@tonic-gate * this entry is filtered, we don't need to do 4897c478bd9Sstevel@tonic-gate * any more processing. 4907c478bd9Sstevel@tonic-gate */ 4917c478bd9Sstevel@tonic-gate if (verbose) { 4927c478bd9Sstevel@tonic-gate (void) printf("Filtered: Need " 4937c478bd9Sstevel@tonic-gate "Addition of:\n\t"); 4947c478bd9Sstevel@tonic-gate print_elem(stdout, cur); 4957c478bd9Sstevel@tonic-gate } 4967c478bd9Sstevel@tonic-gate continue; 4977c478bd9Sstevel@tonic-gate } 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate /* 5007c478bd9Sstevel@tonic-gate * Search package database for file. 5017c478bd9Sstevel@tonic-gate */ 5027c478bd9Sstevel@tonic-gate e = find_elem(&second_list, cur, NO_FOLLOW_LINK); 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate /* 5057c478bd9Sstevel@tonic-gate * It is possible for arch specific files to be found 5067c478bd9Sstevel@tonic-gate * in a protodir but listed as arch independent in a 5077c478bd9Sstevel@tonic-gate * protolist file. If this is a protodir vs. a 5087c478bd9Sstevel@tonic-gate * protolist we will make that check. 5097c478bd9Sstevel@tonic-gate */ 5107c478bd9Sstevel@tonic-gate if (!e && (first_list.type == PROTODIR_LIST) && 5117c478bd9Sstevel@tonic-gate (cur->arch != P_ISA) && 5127c478bd9Sstevel@tonic-gate (second_list.type != PROTODIR_LIST)) { 5137c478bd9Sstevel@tonic-gate /* 5147c478bd9Sstevel@tonic-gate * do a lookup for same file, but as type ISA. 5157c478bd9Sstevel@tonic-gate */ 5167c478bd9Sstevel@tonic-gate e = find_elem_isa(&second_list, cur, 5177c478bd9Sstevel@tonic-gate NO_FOLLOW_LINK); 5187c478bd9Sstevel@tonic-gate } 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate if (!e && (first_list.type != PROTODIR_LIST) && 5217c478bd9Sstevel@tonic-gate (cur->arch == P_ISA) && 5227c478bd9Sstevel@tonic-gate (second_list.type == PROTODIR_LIST)) { 5237c478bd9Sstevel@tonic-gate /* 5247c478bd9Sstevel@tonic-gate * do a lookup for same file, but as any 5257c478bd9Sstevel@tonic-gate * type but ISA 5267c478bd9Sstevel@tonic-gate */ 5277c478bd9Sstevel@tonic-gate e = find_elem_mach(&second_list, cur, 5287c478bd9Sstevel@tonic-gate NO_FOLLOW_LINK); 5297c478bd9Sstevel@tonic-gate } 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate if (e == NULL) 5327c478bd9Sstevel@tonic-gate print_elem(need_add_fp, cur); 5337c478bd9Sstevel@tonic-gate else { 5347c478bd9Sstevel@tonic-gate do_compare(cur, e, 5357c478bd9Sstevel@tonic-gate first_list.type - second_list.type); 5367c478bd9Sstevel@tonic-gate e->flag |= VISITED_F; 5377c478bd9Sstevel@tonic-gate } 5387c478bd9Sstevel@tonic-gate } 5397c478bd9Sstevel@tonic-gate } 5407c478bd9Sstevel@tonic-gate } 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate static int 5437c478bd9Sstevel@tonic-gate read_in_file(const char *file_name, elem_list *list) 5447c478bd9Sstevel@tonic-gate { 5457c478bd9Sstevel@tonic-gate struct stat st_buf; 5467c478bd9Sstevel@tonic-gate int count = 0; 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate if (stat(file_name, &st_buf) == 0) { 5497c478bd9Sstevel@tonic-gate if (S_ISREG(st_buf.st_mode)) { 5507c478bd9Sstevel@tonic-gate if (verbose) { 5517c478bd9Sstevel@tonic-gate (void) printf("file(%s): trying to process " 5527c478bd9Sstevel@tonic-gate "as protolist...\n", file_name); 5537c478bd9Sstevel@tonic-gate } 5547c478bd9Sstevel@tonic-gate count = read_in_protolist(file_name, list, verbose); 5557c478bd9Sstevel@tonic-gate } else if (S_ISDIR(st_buf.st_mode)) { 5567c478bd9Sstevel@tonic-gate if (verbose) 5577c478bd9Sstevel@tonic-gate (void) printf("directory(%s): trying to " 5587c478bd9Sstevel@tonic-gate "process as protodir...\n", file_name); 5597c478bd9Sstevel@tonic-gate count = read_in_protodir(file_name, list, verbose); 5607c478bd9Sstevel@tonic-gate } else { 5617c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5627c478bd9Sstevel@tonic-gate "%s not a file or a directory.\n", file_name); 5637c478bd9Sstevel@tonic-gate usage(); 5647c478bd9Sstevel@tonic-gate exit(1); 5657c478bd9Sstevel@tonic-gate } 5667c478bd9Sstevel@tonic-gate } else { 5677c478bd9Sstevel@tonic-gate perror(file_name); 5687c478bd9Sstevel@tonic-gate usage(); 5697c478bd9Sstevel@tonic-gate exit(1); 5707c478bd9Sstevel@tonic-gate } 5717c478bd9Sstevel@tonic-gate 5727c478bd9Sstevel@tonic-gate return (count); 5737c478bd9Sstevel@tonic-gate } 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate /* ARGSUSED */ 5767c478bd9Sstevel@tonic-gate static int 5777c478bd9Sstevel@tonic-gate set_values(const char *fname, const struct stat *sbp, int otype, 5787c478bd9Sstevel@tonic-gate struct FTW *ftw) 5797c478bd9Sstevel@tonic-gate { 5807c478bd9Sstevel@tonic-gate elem *ep; 5817c478bd9Sstevel@tonic-gate uid_t uid; 5827c478bd9Sstevel@tonic-gate gid_t gid; 5837c478bd9Sstevel@tonic-gate elem keyelem; 5847c478bd9Sstevel@tonic-gate mode_t perm; 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate if (fname[0] == '\0' || fname[1] == '\0' || fname[2] == '\0') 5877c478bd9Sstevel@tonic-gate return (0); 5887c478bd9Sstevel@tonic-gate /* skip leading "./" */ 5897c478bd9Sstevel@tonic-gate fname += 2; 5907c478bd9Sstevel@tonic-gate switch (otype) { 5917c478bd9Sstevel@tonic-gate case FTW_F: 5927c478bd9Sstevel@tonic-gate case FTW_D: 5937c478bd9Sstevel@tonic-gate case FTW_DP: 5947c478bd9Sstevel@tonic-gate if (strlcpy(keyelem.name, fname, sizeof (keyelem.name)) >= 5957c478bd9Sstevel@tonic-gate sizeof (keyelem.name)) { 5967c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s: name too long\n", 5977c478bd9Sstevel@tonic-gate myname, fname); 5987c478bd9Sstevel@tonic-gate return (1); 5997c478bd9Sstevel@tonic-gate } 6007c478bd9Sstevel@tonic-gate keyelem.arch = P_ISA; 6017c478bd9Sstevel@tonic-gate ep = find_elem(&first_list, &keyelem, NO_FOLLOW_LINK); 6027c478bd9Sstevel@tonic-gate if (ep == NULL) { 6037c478bd9Sstevel@tonic-gate ep = find_elem_mach(&first_list, &keyelem, 6047c478bd9Sstevel@tonic-gate NO_FOLLOW_LINK); 6057c478bd9Sstevel@tonic-gate } 6067c478bd9Sstevel@tonic-gate /* 6077c478bd9Sstevel@tonic-gate * Do nothing if this is a hard or symbolic link, 6087c478bd9Sstevel@tonic-gate * since links don't have this information. 6097c478bd9Sstevel@tonic-gate * 6107c478bd9Sstevel@tonic-gate * Assume it's a file on the exception list if it's 6117c478bd9Sstevel@tonic-gate * not found in the packaging. Those are root:bin 755. 6127c478bd9Sstevel@tonic-gate */ 6137c478bd9Sstevel@tonic-gate if (ep != NULL && 6147c478bd9Sstevel@tonic-gate (ep->file_type == SYM_LINK_T || ep->file_type == LINK_T)) { 6157c478bd9Sstevel@tonic-gate return (0); 6167c478bd9Sstevel@tonic-gate } 6177c478bd9Sstevel@tonic-gate if (!set_group) { 6187c478bd9Sstevel@tonic-gate gid = -1; 6197c478bd9Sstevel@tonic-gate } else if (ep == NULL) { 6207c478bd9Sstevel@tonic-gate gid = 0; 6217c478bd9Sstevel@tonic-gate } else if ((gid = stdfind(ep->group, groupnames)) == -1) { 6227c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s: group '%s' unknown\n", 6237c478bd9Sstevel@tonic-gate myname, fname, ep->group); 6247c478bd9Sstevel@tonic-gate return (1); 6257c478bd9Sstevel@tonic-gate } 6267c478bd9Sstevel@tonic-gate if (!set_user) { 6277c478bd9Sstevel@tonic-gate uid = -1; 6287c478bd9Sstevel@tonic-gate } else if (ep == NULL) { 6297c478bd9Sstevel@tonic-gate uid = 2; 6307c478bd9Sstevel@tonic-gate } else if ((uid = stdfind(ep->owner, usernames)) == -1) { 6317c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s: user '%s' unknown\n", 6327c478bd9Sstevel@tonic-gate myname, fname, ep->owner); 6337c478bd9Sstevel@tonic-gate return (1); 6347c478bd9Sstevel@tonic-gate } 6357c478bd9Sstevel@tonic-gate if ((set_group && gid != -1 && gid != sbp->st_gid) || 6367c478bd9Sstevel@tonic-gate (set_user && uid != -1 && uid != sbp->st_uid)) { 6377c478bd9Sstevel@tonic-gate if (verbose) { 6387c478bd9Sstevel@tonic-gate const char *owner, *group; 6397c478bd9Sstevel@tonic-gate 6407c478bd9Sstevel@tonic-gate owner = ep == NULL ? "root" : ep->owner; 6417c478bd9Sstevel@tonic-gate group = ep == NULL ? "bin" : ep->group; 6427c478bd9Sstevel@tonic-gate if (set_group && set_user) { 6437c478bd9Sstevel@tonic-gate (void) printf("chown %s:%s %s\n", 6447c478bd9Sstevel@tonic-gate owner, group, fname); 6457c478bd9Sstevel@tonic-gate } else if (set_user) { 6467c478bd9Sstevel@tonic-gate (void) printf("chown %s %s\n", owner, 6477c478bd9Sstevel@tonic-gate fname); 6487c478bd9Sstevel@tonic-gate } else { 6497c478bd9Sstevel@tonic-gate (void) printf("chgrp %s %s\n", group, 6507c478bd9Sstevel@tonic-gate fname); 6517c478bd9Sstevel@tonic-gate } 6527c478bd9Sstevel@tonic-gate } 6537c478bd9Sstevel@tonic-gate if (lchown(fname, uid, gid) == -1) { 6547c478bd9Sstevel@tonic-gate perror(fname); 6557c478bd9Sstevel@tonic-gate return (1); 6567c478bd9Sstevel@tonic-gate } 6577c478bd9Sstevel@tonic-gate } 6587c478bd9Sstevel@tonic-gate perm = ep == NULL ? 0755 : ep->perm; 6597c478bd9Sstevel@tonic-gate if (set_perm && ((perm ^ sbp->st_mode) & ~S_IFMT) != 0) { 6607c478bd9Sstevel@tonic-gate if (verbose) 6617c478bd9Sstevel@tonic-gate (void) printf("chmod %lo %s\n", perm, fname); 6627c478bd9Sstevel@tonic-gate if (chmod(fname, perm) == -1) { 6637c478bd9Sstevel@tonic-gate perror(fname); 6647c478bd9Sstevel@tonic-gate return (1); 6657c478bd9Sstevel@tonic-gate } 6667c478bd9Sstevel@tonic-gate } 6677c478bd9Sstevel@tonic-gate return (0); 6687c478bd9Sstevel@tonic-gate case FTW_DNR: 6697c478bd9Sstevel@tonic-gate case FTW_NS: 6707c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s: permission denied\n", 6717c478bd9Sstevel@tonic-gate myname, fname); 6727c478bd9Sstevel@tonic-gate return (1); 6737c478bd9Sstevel@tonic-gate case FTW_SL: 6747c478bd9Sstevel@tonic-gate case FTW_SLN: 6757c478bd9Sstevel@tonic-gate return (0); 6767c478bd9Sstevel@tonic-gate default: 6777c478bd9Sstevel@tonic-gate return (1); 6787c478bd9Sstevel@tonic-gate } 6797c478bd9Sstevel@tonic-gate } 6807c478bd9Sstevel@tonic-gate 6817c478bd9Sstevel@tonic-gate int 6827c478bd9Sstevel@tonic-gate main(int argc, char **argv) 6837c478bd9Sstevel@tonic-gate { 6847c478bd9Sstevel@tonic-gate int errflg = 0; 6857c478bd9Sstevel@tonic-gate int i, c; 686*ed159168SRichard PALO int list_filtered_exceptions = 0; 6877c478bd9Sstevel@tonic-gate int n_proto_refs = 0; 6887c478bd9Sstevel@tonic-gate int n_exception_files = 0; 6897c478bd9Sstevel@tonic-gate char *proto_refs[MAX_PROTO_REFS]; 6907c478bd9Sstevel@tonic-gate char *exception_files[MAX_EXCEPTION_FILES]; 6917c478bd9Sstevel@tonic-gate struct stat st_buf; 6927c478bd9Sstevel@tonic-gate 6937c478bd9Sstevel@tonic-gate if ((myname = argv[0]) == NULL) 6947c478bd9Sstevel@tonic-gate myname = "protocmp"; 6957c478bd9Sstevel@tonic-gate 6967c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "gupGUPlmsLe:vd:")) != EOF) { 6977c478bd9Sstevel@tonic-gate switch (c) { 6987c478bd9Sstevel@tonic-gate case 's': 6997c478bd9Sstevel@tonic-gate check_sym = 0; 7007c478bd9Sstevel@tonic-gate break; 7017c478bd9Sstevel@tonic-gate case 'm': 7027c478bd9Sstevel@tonic-gate check_majmin = 0; 7037c478bd9Sstevel@tonic-gate break; 7047c478bd9Sstevel@tonic-gate case 'g': 7057c478bd9Sstevel@tonic-gate check_group = 0; 7067c478bd9Sstevel@tonic-gate break; 7077c478bd9Sstevel@tonic-gate case 'G': 7087c478bd9Sstevel@tonic-gate set_group = 1; 7097c478bd9Sstevel@tonic-gate break; 7107c478bd9Sstevel@tonic-gate case 'u': 7117c478bd9Sstevel@tonic-gate check_user = 0; 7127c478bd9Sstevel@tonic-gate break; 7137c478bd9Sstevel@tonic-gate case 'U': 7147c478bd9Sstevel@tonic-gate set_user = 1; 7157c478bd9Sstevel@tonic-gate break; 7167c478bd9Sstevel@tonic-gate case 'l': 7177c478bd9Sstevel@tonic-gate check_link = 0; 7187c478bd9Sstevel@tonic-gate break; 7197c478bd9Sstevel@tonic-gate case 'p': 7207c478bd9Sstevel@tonic-gate check_perm = 0; 7217c478bd9Sstevel@tonic-gate break; 7227c478bd9Sstevel@tonic-gate case 'P': 7237c478bd9Sstevel@tonic-gate set_perm = 1; 7247c478bd9Sstevel@tonic-gate break; 7257c478bd9Sstevel@tonic-gate case 'e': 7267c478bd9Sstevel@tonic-gate if (n_exception_files >= MAX_EXCEPTION_FILES) { 7277c478bd9Sstevel@tonic-gate errflg++; 7287c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7297c478bd9Sstevel@tonic-gate "Only %d exception files supported\n", 7307c478bd9Sstevel@tonic-gate MAX_EXCEPTION_FILES); 7317c478bd9Sstevel@tonic-gate } else { 7327c478bd9Sstevel@tonic-gate exception_files[n_exception_files++] = optarg; 7337c478bd9Sstevel@tonic-gate } 7347c478bd9Sstevel@tonic-gate break; 7357c478bd9Sstevel@tonic-gate case 'L': 7367c478bd9Sstevel@tonic-gate list_filtered_exceptions++; 7377c478bd9Sstevel@tonic-gate break; 7387c478bd9Sstevel@tonic-gate case 'v': 7397c478bd9Sstevel@tonic-gate verbose++; 7407c478bd9Sstevel@tonic-gate break; 7417c478bd9Sstevel@tonic-gate case 'd': 7427c478bd9Sstevel@tonic-gate if (n_proto_refs >= MAX_PROTO_REFS) { 7437c478bd9Sstevel@tonic-gate errflg++; 7447c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7457c478bd9Sstevel@tonic-gate "Only %d proto references supported\n", 7467c478bd9Sstevel@tonic-gate MAX_PROTO_REFS); 7477c478bd9Sstevel@tonic-gate } else { 7487c478bd9Sstevel@tonic-gate proto_refs[n_proto_refs++] = optarg; 7497c478bd9Sstevel@tonic-gate } 7507c478bd9Sstevel@tonic-gate break; 7517c478bd9Sstevel@tonic-gate case '?': 7527c478bd9Sstevel@tonic-gate default: 7537c478bd9Sstevel@tonic-gate errflg++; 7547c478bd9Sstevel@tonic-gate break; 7557c478bd9Sstevel@tonic-gate } 7567c478bd9Sstevel@tonic-gate } 7577c478bd9Sstevel@tonic-gate 7587c478bd9Sstevel@tonic-gate if (argc == optind || n_proto_refs == 0) { 7597c478bd9Sstevel@tonic-gate usage(); 7607c478bd9Sstevel@tonic-gate exit(1); 7617c478bd9Sstevel@tonic-gate } 7627c478bd9Sstevel@tonic-gate 7637c478bd9Sstevel@tonic-gate if (set_group || set_user || set_perm) { 7647c478bd9Sstevel@tonic-gate if (optind != argc - 1) { 7657c478bd9Sstevel@tonic-gate usage(); 7667c478bd9Sstevel@tonic-gate exit(1); 7677c478bd9Sstevel@tonic-gate } 7687c478bd9Sstevel@tonic-gate if (stat(argv[optind], &st_buf) == -1) { 7697c478bd9Sstevel@tonic-gate perror(argv[optind]); 7707c478bd9Sstevel@tonic-gate exit(1); 7717c478bd9Sstevel@tonic-gate } 7727c478bd9Sstevel@tonic-gate if (!S_ISDIR(st_buf.st_mode)) { 7737c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s: not a directory\n", 7747c478bd9Sstevel@tonic-gate myname, argv[optind]); 7757c478bd9Sstevel@tonic-gate exit(1); 7767c478bd9Sstevel@tonic-gate } 7777c478bd9Sstevel@tonic-gate } 7787c478bd9Sstevel@tonic-gate 7797c478bd9Sstevel@tonic-gate init_list(&first_list, HASH_SIZE); 7807c478bd9Sstevel@tonic-gate init_list(&second_list, HASH_SIZE); 7817c478bd9Sstevel@tonic-gate init_list(&exception_list, HASH_SIZE); 7827c478bd9Sstevel@tonic-gate 7837c478bd9Sstevel@tonic-gate for (i = 0; i < n_exception_files; i++) { 7847c478bd9Sstevel@tonic-gate (void) read_in_exceptions(exception_files[i], verbose); 7857c478bd9Sstevel@tonic-gate } 7867c478bd9Sstevel@tonic-gate 7877c478bd9Sstevel@tonic-gate for (i = 0; i < n_proto_refs; i++) { 7887c478bd9Sstevel@tonic-gate first_file_name = proto_refs[i]; 7897c478bd9Sstevel@tonic-gate (void) read_in_file(first_file_name, &first_list); 7907c478bd9Sstevel@tonic-gate } 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate if (set_group || set_user || set_perm) { 7937c478bd9Sstevel@tonic-gate if (chdir(argv[optind]) == -1) { 7947c478bd9Sstevel@tonic-gate perror(argv[optind]); 7957c478bd9Sstevel@tonic-gate exit(1); 7967c478bd9Sstevel@tonic-gate } 7977c478bd9Sstevel@tonic-gate i = nftw(".", set_values, MAX_DEPTH, FTW_PHYS|FTW_DEPTH); 7987c478bd9Sstevel@tonic-gate if (i == -1) { 7997c478bd9Sstevel@tonic-gate perror("nftw"); 8007c478bd9Sstevel@tonic-gate i = 1; 8017c478bd9Sstevel@tonic-gate } 8027c478bd9Sstevel@tonic-gate exit(i); 8037c478bd9Sstevel@tonic-gate } 8047c478bd9Sstevel@tonic-gate 8057c478bd9Sstevel@tonic-gate for (i = optind; i < argc; i++) { 8067c478bd9Sstevel@tonic-gate second_file_name = argv[i]; 8077c478bd9Sstevel@tonic-gate (void) read_in_file(second_file_name, &second_list); 8087c478bd9Sstevel@tonic-gate } 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate open_output_files(); 8117c478bd9Sstevel@tonic-gate 8127c478bd9Sstevel@tonic-gate if (verbose) 8137c478bd9Sstevel@tonic-gate (void) puts("comparing build to packages..."); 8147c478bd9Sstevel@tonic-gate 8157c478bd9Sstevel@tonic-gate check_first_vs_second(list_filtered_exceptions); 8167c478bd9Sstevel@tonic-gate 8177c478bd9Sstevel@tonic-gate if (verbose) 8187c478bd9Sstevel@tonic-gate (void) puts("checking over packages..."); 8197c478bd9Sstevel@tonic-gate check_second_vs_first(list_filtered_exceptions); 8207c478bd9Sstevel@tonic-gate 8217c478bd9Sstevel@tonic-gate close_output_files(); 8227c478bd9Sstevel@tonic-gate 8237c478bd9Sstevel@tonic-gate print_results(); 8247c478bd9Sstevel@tonic-gate 8257c478bd9Sstevel@tonic-gate clean_up(); 8267c478bd9Sstevel@tonic-gate 8277c478bd9Sstevel@tonic-gate return (0); 8287c478bd9Sstevel@tonic-gate } 829