xref: /titanic_51/usr/src/tools/protocmp/protocmp.c (revision ed1591688000a5d179c4ba27793cae55590c55d2)
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