protocmp.c revision 63360950109af2ce85a962ca61f40b8782f11100
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <errno.h>
#include <unistd.h>
#include <ftw.h>
#include "list.h"
#include "protocmp.h"
#include "proto_list.h"
#include "protodir.h"
#include "exception_list.h"
#include "stdusers.h"
#define MAX_PROTO_REFS 5
#define MAX_EXCEPTION_FILES 5
#define MAX_DEPTH 50
/*
* default flag values
*/
static int check_group = 1;
static int set_group = 0;
static int check_user = 1;
static int set_user = 0;
static int check_perm = 1;
static int set_perm = 0;
static int check_link = 1;
static int check_sym = 1;
static int check_majmin = 1;
static elem_list first_list;
static char *first_file_name;
static elem_list second_list;
static char *second_file_name;
static FILE *need_add_fp;
static char *need_add_file;
static FILE *need_rm_fp;
static char *need_rm_file;
static char *differ_file;
static char *myname;
/*
* default flag values
*/
static int verbose = 0;
static void
usage(void)
{
(void) fputs("usage: protocmp [-gupGUPlmsLv] "
"[-e <exception-list> ...] "
"-d <protolist|pkg dir>\n\t[-d <protolist|pkg dir> ...] "
"[<protolist|pkg dir>...]|<root>]\n",
stderr);
stderr);
(void) fputs("\n"
"If any of the -[GUP] flags are given, then the final argument must be the\n"
"proto root directory itself on which to set permissions according to the\n"
"packaging data specified via -d options.\n", stderr);
}
static void
open_output_files(void)
{
if ((need_add_fp =
exit(1);
}
if ((need_rm_fp =
exit(1);
}
if ((differ_fp =
exit(1);
}
}
static void
close_output_files(void)
{
(void) fclose(need_add_fp);
(void) fclose(need_rm_fp);
}
static void
print_file(char *file)
{
int count;
}
}
static void
print_header(void)
{
(void) printf("%c %-30s %-20s %-4s %-5s %-5s %-5s %-2s %2s %2s %-9s\n",
"inode", "lnk", "maj", "min", "package(s)");
(void) puts("-------------------------------------------------------"
"-----------------------------------------------------");
}
static void
print_results(void)
{
(void) puts("*******************************************************");
(void) puts("*");
(void) printf("* Entries found in %s, but not found in %s\n",
(void) puts("*");
(void) puts("*******************************************************");
print_header();
(void) puts("*******************************************************");
(void) puts("*");
(void) printf("* Entries found in %s, but not found in %s\n",
(void) puts("*");
(void) puts("*******************************************************");
print_header();
(void) puts("*******************************************************");
(void) puts("*");
(void) printf("* Entries that differ between %s and %s\n",
(void) puts("*");
(void) puts("*");
(void) puts("*******************************************************");
print_header();
}
static void
clean_up(void)
{
(void) unlink(need_add_file);
(void) unlink(need_rm_file);
(void) unlink(differ_file);
}
/*
* elem_compare(a,b)
*
* Args:
* a - element a
* b - element b
* different_types -
* value = 0 -> comparing two elements of same
* type (eg: protodir elem vs. protodir elem).
* value != 0 -> comparing two elements of different type
* (eg: protodir elem vs. protolist elem).
*
* Returns:
* 0 - elements are identical
* >0 - elements differ
* check flags to see which fields differ.
*/
static int
{
int res = 0;
elem *i, *j;
/*
* if these are hard links to other files - those are the
* files that should be compared.
*/
i = a->link_parent ? a->link_parent : a;
j = b->link_parent ? b->link_parent : b;
/*
* We do not compare inodes - they always differ.
* We do not compare names because we assume that was
* checked before.
*/
/*
* Special rules for comparison:
*
* 1) if directory - ignore ref_cnt.
* 2) if sym_link - only check file_type & symlink
* 3) elem type of FILE_T, EDIT_T, & VOLATILE_T are equivilant when
* comparing a protodir entry to a protolist entry.
*/
if (different_types) {
/*
* Check to see if filetypes are FILE_T vs.
* EDIT_T/VOLATILE_T/LINK_T comparisons.
*/
(j->file_type == VOLATILE_T) ||
/*EMPTY*/
(i->file_type == VOLATILE_T) ||
/*EMPTY*/
} else
} else
}
/*
* if symlink - check the symlink value and then
* return. symlink is the only field of concern
* in SYMLINKS.
*/
else {
/*
* if either symlink starts with a './' strip it off,
* its irrelevant.
*/
i->symsrc += 2;
j->symsrc += 2;
}
return (res);
}
return (res);
}
static void
{
elem p;
pkg_list *l;
/*
* If this is a LINK to another file, then adopt
* the permissions of that file.
*/
if (e->link_parent) {
p = *((elem *)e->link_parent);
e = &p;
}
maj[0] = '-';
} else {
}
min[0] = '-';
} else {
}
if (!check_perm) {
perm[0] = '-';
} else {
}
if (!check_link) {
ref_cnt[0] = '-';
} else {
}
/*
* dump package list - if any.
*/
if (!e->pkgs)
}
}
/*
* do_compare(a,b)
*
* Args:
* different_types - see elem_compare() for explanation.
*/
static void
{
int rc;
print_elem(differ_fp, a);
print_elem(differ_fp, b);
}
}
static void
{
int i;
for (i = 0; i < second_list.num_of_buckets; i++) {
FOLLOW_LINK)) {
/*
* this entry is filtered, we don't
* need to do any more processing.
*/
if (verbose) {
(void) printf(
"Filtered: Need Deletion "
"of:\n\t");
}
continue;
}
/*
* It is possible for arch specific files to be
* found in a protodir but listed as arch
* independent in a protolist file. If this is
* a protodir vs. a protolist we will make
* that check.
*/
/*
* do a lookup for same file, but as
* type ISA.
*/
elem *e;
if (e) {
do_compare(e, cur,
continue;
}
}
}
}
}
}
static void
{
int i;
elem *e;
for (i = 0; i < first_list.num_of_buckets; i++) {
/*
* this entry is filtered, we don't need to do
* any more processing.
*/
if (verbose) {
(void) printf("Filtered: Need "
"Addition of:\n\t");
}
continue;
}
/*
* Search package database for file.
*/
/*
* It is possible for arch specific files to be found
* in a protodir but listed as arch independent in a
* protolist file. If this is a protodir vs. a
* protolist we will make that check.
*/
/*
* do a lookup for same file, but as type ISA.
*/
}
/*
* do a lookup for same file, but as any
* type but ISA
*/
}
if (e == NULL)
else {
do_compare(cur, e,
}
}
}
}
static int
{
int count = 0;
if (verbose) {
(void) printf("file(%s): trying to process "
"as protolist...\n", file_name);
}
if (verbose)
(void) printf("directory(%s): trying to "
"process as protodir...\n", file_name);
} else {
"%s not a file or a directory.\n", file_name);
usage();
exit(1);
}
} else {
usage();
exit(1);
}
return (count);
}
/* ARGSUSED */
static int
{
return (0);
/* skip leading "./" */
fname += 2;
switch (otype) {
case FTW_F:
case FTW_D:
case FTW_DP:
return (1);
}
}
/*
* Do nothing if this is a hard or symbolic link,
* since links don't have this information.
*
* Assume it's a file on the exception list if it's
* not found in the packaging. Those are root:bin 755.
*/
return (0);
}
if (!set_group) {
gid = -1;
gid = 0;
return (1);
}
if (!set_user) {
uid = -1;
uid = 2;
return (1);
}
if (verbose) {
(void) printf("chown %s:%s %s\n",
} else if (set_user) {
fname);
} else {
fname);
}
}
return (1);
}
}
if (verbose)
return (1);
}
}
return (0);
case FTW_DNR:
case FTW_NS:
return (1);
case FTW_SL:
case FTW_SLN:
return (0);
default:
return (1);
}
}
int
{
int errflg = 0;
int i, c;
int list_filtered_exceptions = NULL;
int n_proto_refs = 0;
int n_exception_files = 0;
char *proto_refs[MAX_PROTO_REFS];
char *exception_files[MAX_EXCEPTION_FILES];
myname = "protocmp";
switch (c) {
case 's':
check_sym = 0;
break;
case 'm':
check_majmin = 0;
break;
case 'g':
check_group = 0;
break;
case 'G':
set_group = 1;
break;
case 'u':
check_user = 0;
break;
case 'U':
set_user = 1;
break;
case 'l':
check_link = 0;
break;
case 'p':
check_perm = 0;
break;
case 'P':
set_perm = 1;
break;
case 'e':
if (n_exception_files >= MAX_EXCEPTION_FILES) {
errflg++;
"Only %d exception files supported\n",
} else {
}
break;
case 'L':
break;
case 'v':
verbose++;
break;
case 'd':
if (n_proto_refs >= MAX_PROTO_REFS) {
errflg++;
"Only %d proto references supported\n",
} else {
}
break;
case '?':
default:
errflg++;
break;
}
}
usage();
exit(1);
}
usage();
exit(1);
}
exit(1);
}
exit(1);
}
}
for (i = 0; i < n_exception_files; i++) {
}
for (i = 0; i < n_proto_refs; i++) {
first_file_name = proto_refs[i];
}
exit(1);
}
if (i == -1) {
perror("nftw");
i = 1;
}
exit(i);
}
second_file_name = argv[i];
}
if (verbose)
(void) puts("comparing build to packages...");
if (verbose)
(void) puts("checking over packages...");
clean_up();
return (0);
}