xref: /onnv-gate/usr/src/tools/depcheck/make_pkg_db (revision 0:68f95e015346)
1*0Sstevel@tonic-gate#!/usr/bin/perl
2*0Sstevel@tonic-gate#
3*0Sstevel@tonic-gate# CDDL HEADER START
4*0Sstevel@tonic-gate#
5*0Sstevel@tonic-gate# The contents of this file are subject to the terms of the
6*0Sstevel@tonic-gate# Common Development and Distribution License, Version 1.0 only
7*0Sstevel@tonic-gate# (the "License").  You may not use this file except in compliance
8*0Sstevel@tonic-gate# with the License.
9*0Sstevel@tonic-gate#
10*0Sstevel@tonic-gate# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11*0Sstevel@tonic-gate# or http://www.opensolaris.org/os/licensing.
12*0Sstevel@tonic-gate# See the License for the specific language governing permissions
13*0Sstevel@tonic-gate# and limitations under the License.
14*0Sstevel@tonic-gate#
15*0Sstevel@tonic-gate# When distributing Covered Code, include this CDDL HEADER in each
16*0Sstevel@tonic-gate# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17*0Sstevel@tonic-gate# If applicable, add the following below this CDDL HEADER, with the
18*0Sstevel@tonic-gate# fields enclosed by brackets "[]" replaced with your own identifying
19*0Sstevel@tonic-gate# information: Portions Copyright [yyyy] [name of copyright owner]
20*0Sstevel@tonic-gate#
21*0Sstevel@tonic-gate# CDDL HEADER END
22*0Sstevel@tonic-gate#
23*0Sstevel@tonic-gate#
24*0Sstevel@tonic-gate# Copyright (c) 2000 by Sun Microsystems, Inc.
25*0Sstevel@tonic-gate# All rights reserved.
26*0Sstevel@tonic-gate#
27*0Sstevel@tonic-gate
28*0Sstevel@tonic-gate# ident	"%Z%%M%	%I%	%E% SMI"
29*0Sstevel@tonic-gate
30*0Sstevel@tonic-gate$PkgDir = "/var/sadm/pkg";	# where to find the pkg directories
31*0Sstevel@tonic-gate$PROGRAM_NAME = "make_pkg_db";
32*0Sstevel@tonic-gate$DBM_DIR_CHARACTERIZATION = "directory for the dbm databases";
33*0Sstevel@tonic-gate$INPUT_FILES_CHARACTERIZATION = "one or more files in /var/sadm/install/contents format";
34*0Sstevel@tonic-gate$PKGDEFS_DIRECTORY = "package pool directory";
35*0Sstevel@tonic-gate
36*0Sstevel@tonic-gate$Usage =
37*0Sstevel@tonic-gate"Usage: $PROGRAM_NAME
38*0Sstevel@tonic-gate  [-ifiles <$INPUT_FILES_CHARACTERIZATION>]
39*0Sstevel@tonic-gate  [-pkgdef <$PKGDEFS_DIRECTORY>]
40*0Sstevel@tonic-gate  -dbdir <$DBM_DIR_CHARACTERIZATION>
41*0Sstevel@tonic-gate  [-h for help]\n";
42*0Sstevel@tonic-gate
43*0Sstevel@tonic-gate$Help =
44*0Sstevel@tonic-gate"This program initializes a set of dbm databases with information
45*0Sstevel@tonic-gatefrom /var/sadm/install/contents or a user-defined package pool directory.
46*0Sstevel@tonic-gateThere is one required argument:
47*0Sstevel@tonic-gate
48*0Sstevel@tonic-gate        -dbdir  <dir>			the $DBM_DIR_CHARACTERIZATION
49*0Sstevel@tonic-gate
50*0Sstevel@tonic-gate\nThe optional argument -h produces this message instead of any processing.
51*0Sstevel@tonic-gate\nThe optional argument -ifiles is used for symbolic link resolution.
52*0Sstevel@tonic-gate\nThe optional argument -pkgdef creates the databases based upon a package \npool directory instead of /var/sadm/install/contents on the local machine.
53*0Sstevel@tonic-gate";
54*0Sstevel@tonic-gate
55*0Sstevel@tonic-gate
56*0Sstevel@tonic-gate#
57*0Sstevel@tonic-gate# check for perl5 -- we use things unavailable in perl4
58*0Sstevel@tonic-gate#
59*0Sstevel@tonic-gate
60*0Sstevel@tonic-gatedie "Sorry, this program requires perl version 5.000 or up. You have $]. Stopping" if $] < 5.000;
61*0Sstevel@tonic-gate
62*0Sstevel@tonic-gate#
63*0Sstevel@tonic-gate# process arguments
64*0Sstevel@tonic-gate#
65*0Sstevel@tonic-gate
66*0Sstevel@tonic-gate$PKGDefs = "";
67*0Sstevel@tonic-gate
68*0Sstevel@tonic-gatewhile (@ARGV) {
69*0Sstevel@tonic-gate    $arg = shift (@ARGV);
70*0Sstevel@tonic-gate    if ($arg eq "-h") {
71*0Sstevel@tonic-gate        print "$Help\n$Usage";
72*0Sstevel@tonic-gate        exit 0;
73*0Sstevel@tonic-gate    } elsif ($arg eq "-ifiles") {
74*0Sstevel@tonic-gate	while (($ARGV[0] !~ /^-/) && (@ARGV)){
75*0Sstevel@tonic-gate	    push (@IFiles, shift(@ARGV));
76*0Sstevel@tonic-gate	}
77*0Sstevel@tonic-gate    } elsif ($arg eq "-dbdir") {
78*0Sstevel@tonic-gate        $DBDir = shift(@ARGV) unless ($ARGV[0] =~ /^-/);
79*0Sstevel@tonic-gate    } elsif ($arg eq "-pkgdef") {
80*0Sstevel@tonic-gate        $PKGDefs = shift(@ARGV) unless ($ARGV[0] =~ /^-/);
81*0Sstevel@tonic-gate    } else {
82*0Sstevel@tonic-gate        print STDERR "Unrecognized argument $arg. \n$Usage";
83*0Sstevel@tonic-gate        exit 1;
84*0Sstevel@tonic-gate    }
85*0Sstevel@tonic-gate}
86*0Sstevel@tonic-gate
87*0Sstevel@tonic-gate# make sure the package pool directory exists
88*0Sstevel@tonic-gateif (($PKGDefs) && !(-d $PKGDefs)) {
89*0Sstevel@tonic-gate	print STDERR "Cannot open the directory $PKGDefs\n";
90*0Sstevel@tonic-gate	exit 1;
91*0Sstevel@tonic-gate}
92*0Sstevel@tonic-gate
93*0Sstevel@tonic-gate# Here we define the input files which will be parsed
94*0Sstevel@tonic-gateif ($PKGDefs) {
95*0Sstevel@tonic-gate
96*0Sstevel@tonic-gate	$dirs = `ls $PKGDefs`;
97*0Sstevel@tonic-gate	@dirlist = split(/\s*\n\s*/, $dirs);
98*0Sstevel@tonic-gate
99*0Sstevel@tonic-gate	foreach $dir (@dirlist) {
100*0Sstevel@tonic-gate		push(@IFiles, "$PKGDefs/$dir/pkgmap");
101*0Sstevel@tonic-gate	}
102*0Sstevel@tonic-gate
103*0Sstevel@tonic-gate	reverse(@IFiles);
104*0Sstevel@tonic-gate}
105*0Sstevel@tonic-gateelse {
106*0Sstevel@tonic-gate	push(@IFiles, "/var/sadm/install/contents");
107*0Sstevel@tonic-gate}
108*0Sstevel@tonic-gate
109*0Sstevel@tonic-gateif (!@IFiles) {
110*0Sstevel@tonic-gate    print STDERR "Required argument -ifiles missing. \n$Usage";
111*0Sstevel@tonic-gate    exit 1;
112*0Sstevel@tonic-gate}
113*0Sstevel@tonic-gate
114*0Sstevel@tonic-gateif (!$DBDir) {
115*0Sstevel@tonic-gate    print STDERR "Required argument -dbdir missing. \n$Usage";
116*0Sstevel@tonic-gate    exit 1;
117*0Sstevel@tonic-gate}
118*0Sstevel@tonic-gate
119*0Sstevel@tonic-gate$Struct = \%struct;	# here is the structure we'll store everything in
120*0Sstevel@tonic-gate
121*0Sstevel@tonic-gate
122*0Sstevel@tonic-gate
123*0Sstevel@tonic-gate#
124*0Sstevel@tonic-gate# now open the dbm databases we will initialize
125*0Sstevel@tonic-gate#
126*0Sstevel@tonic-gate&yelp ("...initializing the databases\n");
127*0Sstevel@tonic-gate
128*0Sstevel@tonic-gateunless (-d "$DBDir") {
129*0Sstevel@tonic-gate	&yelp("Creating directory $DBDir\n");
130*0Sstevel@tonic-gate	mkdir($DBDir, 0777);
131*0Sstevel@tonic-gate}
132*0Sstevel@tonic-gate
133*0Sstevel@tonic-gate# db for package names from the /var/sadm/pkg/foo/pkginfo files
134*0Sstevel@tonic-gatedbmopen(%PKGNAMES, "$DBDir/PKGNAMES", 0644) || die"Cannot open dbm db $DBDir/PKGNAMES\n";
135*0Sstevel@tonic-gate
136*0Sstevel@tonic-gate# db for entity file types
137*0Sstevel@tonic-gatedbmopen(%FTYPE, "$DBDir/FTYPE", 0664) || die"Cannot open dbm db $DBDir/FTYPE\n";
138*0Sstevel@tonic-gate
139*0Sstevel@tonic-gate# db for entity modes types
140*0Sstevel@tonic-gatedbmopen(%MODE, "$DBDir/MODE", 0664) || die"Cannot open dbm db $DBDir/MODE\n";
141*0Sstevel@tonic-gate
142*0Sstevel@tonic-gate# db for entity packages
143*0Sstevel@tonic-gatedbmopen(%PKGS, "$DBDir/PKGS", 0664) || die"Cannot open dbm db $DBDir/PKGS\n";
144*0Sstevel@tonic-gate
145*0Sstevel@tonic-gate# db for absolute link targets
146*0Sstevel@tonic-gatedbmopen(%ABSLINK, "$DBDir/ABSLINK", 0664) || die"Cannot open dbm db $DBDir/ABSLINK\n";
147*0Sstevel@tonic-gate
148*0Sstevel@tonic-gate
149*0Sstevel@tonic-gateundef %FTYPE;		# remove existing records, if any
150*0Sstevel@tonic-gateundef %MODE;
151*0Sstevel@tonic-gateundef %PKGS;
152*0Sstevel@tonic-gateundef %ABSLINK;
153*0Sstevel@tonic-gateundef %PKGNAMES;
154*0Sstevel@tonic-gate
155*0Sstevel@tonic-gate$Debug = 1;				# print extra gibberish
156*0Sstevel@tonic-gate
157*0Sstevel@tonic-gate#
158*0Sstevel@tonic-gate# go make the package names db
159*0Sstevel@tonic-gate#
160*0Sstevel@tonic-gate
161*0Sstevel@tonic-gate&MakePackageNamesDB($PkgDir);
162*0Sstevel@tonic-gate
163*0Sstevel@tonic-gate#
164*0Sstevel@tonic-gate# read and parse each input file in contents file format
165*0Sstevel@tonic-gate#
166*0Sstevel@tonic-gate
167*0Sstevel@tonic-gate&yelp ("...making the FTYPE MODE and PKGS databases\n");
168*0Sstevel@tonic-gateforeach $IFile (@IFiles) {
169*0Sstevel@tonic-gate    if ($PKGDefs) {
170*0Sstevel@tonic-gate       unless (-r $IFile) {
171*0Sstevel@tonic-gate           print STDERR "Could not open file: $IFile\n";
172*0Sstevel@tonic-gate           next;
173*0Sstevel@tonic-gate       }
174*0Sstevel@tonic-gate
175*0Sstevel@tonic-gate       @pkgname = split("/", $IFile);
176*0Sstevel@tonic-gate       $thisPkg = @pkgname[($#pkgname-1)];
177*0Sstevel@tonic-gate       $pkgInfo="$PKGDefs/$thisPkg/pkginfo";
178*0Sstevel@tonic-gate       $thisBaseDir="";
179*0Sstevel@tonic-gate       if (-r $pkgInfo) {
180*0Sstevel@tonic-gate            $BASEDIR = `grep '^BASEDIR' $pkgInfo`;
181*0Sstevel@tonic-gate            $BASEDIR =~ s/^BASEDIR=//;
182*0Sstevel@tonic-gate            chomp($BASEDIR);
183*0Sstevel@tonic-gate            $thisBaseDir = $BASEDIR;
184*0Sstevel@tonic-gate       }
185*0Sstevel@tonic-gate    }
186*0Sstevel@tonic-gate
187*0Sstevel@tonic-gate    open (IFILE, "$IFile") || die "cannot open input file $IFile\n";
188*0Sstevel@tonic-gate
189*0Sstevel@tonic-gate    # Tell the user what we are looking at UNLESS they are looking at a package
190*0Sstevel@tonic-gate    # pool.  A package pool could have hundreds of entries which just creates
191*0Sstevel@tonic-gate    # a lot of useless (and confusing) output.
192*0Sstevel@tonic-gate    &yelp("...opening $IFile\n") unless ($PKGDefs);
193*0Sstevel@tonic-gate
194*0Sstevel@tonic-gate    while (<IFILE>) {	# loop over file line-at-a-time
195*0Sstevel@tonic-gate	if ($PKGDefs) {
196*0Sstevel@tonic-gate		next if /^:/;		# ignore these lines from a pkgmap
197*0Sstevel@tonic-gate		next if (/(\S+)\s+[i]\s+/);
198*0Sstevel@tonic-gate	}
199*0Sstevel@tonic-gate	else {
200*0Sstevel@tonic-gate		next if /^#/;		# ignore comments
201*0Sstevel@tonic-gate		next if /^\s*$/;	# ignore blanks
202*0Sstevel@tonic-gate	}
203*0Sstevel@tonic-gate
204*0Sstevel@tonic-gate
205*0Sstevel@tonic-gate	chop;
206*0Sstevel@tonic-gate	undef $FType;
207*0Sstevel@tonic-gate	undef $Mode;
208*0Sstevel@tonic-gate
209*0Sstevel@tonic-gate	$line=$_;
210*0Sstevel@tonic-gate
211*0Sstevel@tonic-gate	if ($PKGDefs) {
212*0Sstevel@tonic-gate		&ParsePkgmapEntry($line);
213*0Sstevel@tonic-gate		@Pkgs = $thisPkg;
214*0Sstevel@tonic-gate	}
215*0Sstevel@tonic-gate	else {
216*0Sstevel@tonic-gate		&ParseContentsEntry($_);
217*0Sstevel@tonic-gate	}
218*0Sstevel@tonic-gate
219*0Sstevel@tonic-gate	# if this entry was supplied by a earlier file, skip it
220*0Sstevel@tonic-gate
221*0Sstevel@tonic-gate	if ($FTYPE{$Entity} =~ /\w/) {
222*0Sstevel@tonic-gate
223*0Sstevel@tonic-gate            # don't bother complaining about directories, we know the same
224*0Sstevel@tonic-gate            # directory could exist in multiple packages
225*0Sstevel@tonic-gate	    next if ($FTYPE{$Entity} eq "d");
226*0Sstevel@tonic-gate
227*0Sstevel@tonic-gate            if ($PKGDefs) {
228*0Sstevel@tonic-gate                 # In the case where we are going through a package pool, we
229*0Sstevel@tonic-gate                 # expect that a file may reside in multiple packages.  If
230*0Sstevel@tonic-gate                 # that is detected, we simply add this package to the list of
231*0Sstevel@tonic-gate                 # packages for that file
232*0Sstevel@tonic-gate
233*0Sstevel@tonic-gate                 $currPkgs = $PKGS{$Entity};
234*0Sstevel@tonic-gatenext if ($FTYPE{$Entity} eq "s");
235*0Sstevel@tonic-gate                 $PKGS{$Entity} = "$currPkgs $thisPkg";
236*0Sstevel@tonic-gate            }
237*0Sstevel@tonic-gate            else {
238*0Sstevel@tonic-gate                 # In the case where we are reading in from
239*0Sstevel@tonic-gate                 # /var/sadm/install.contents, we do not expect to see any
240*0Sstevel@tonic-gate                 # over-ridden files EXCEPT when the "-ifiles" option is used.
241*0Sstevel@tonic-gate	         &yelp("...OVERRIDDEN: $line\n");
242*0Sstevel@tonic-gate            }
243*0Sstevel@tonic-gate	    next;
244*0Sstevel@tonic-gate	} else {
245*0Sstevel@tonic-gate	    $Package = join(" ",@Pkgs);# store supplying packages sep by " "
246*0Sstevel@tonic-gate
247*0Sstevel@tonic-gate            # This is a hack.  In the case of directories like /bin which
248*0Sstevel@tonic-gate            # would belong in many packages, the $PKGS hash would not
249*0Sstevel@tonic-gate            # be able to handle such a long entry.  So for directories, I
250*0Sstevel@tonic-gate            # just place the first package I find.  For this tool, it doesn't
251*0Sstevel@tonic-gate            # matter since this tool does not report which directories come
252*0Sstevel@tonic-gate            # from which package.
253*0Sstevel@tonic-gate
254*0Sstevel@tonic-gate            if ($FType eq "d") {
255*0Sstevel@tonic-gate                @FirstPackage = split(" ", $Package);
256*0Sstevel@tonic-gate                $PKGS{$Entity} = $FirstPackage[0];
257*0Sstevel@tonic-gate            }
258*0Sstevel@tonic-gate            else {
259*0Sstevel@tonic-gate	        $PKGS{$Entity} = $Package; # update PKGS database
260*0Sstevel@tonic-gate            }
261*0Sstevel@tonic-gate	}
262*0Sstevel@tonic-gate
263*0Sstevel@tonic-gate	#
264*0Sstevel@tonic-gate	# put what we need from this entry line into the dbs
265*0Sstevel@tonic-gate	#
266*0Sstevel@tonic-gate
267*0Sstevel@tonic-gate	&yelp ("***NO FILETYPE! IGNORING ENTRY: $_\n") unless $FType;
268*0Sstevel@tonic-gate	$FTYPE{$Entity} = $FType;	# update the FTYPE database
269*0Sstevel@tonic-gate
270*0Sstevel@tonic-gate	#
271*0Sstevel@tonic-gate	# now collect the possible paths for each basename
272*0Sstevel@tonic-gate	#
273*0Sstevel@tonic-gate
274*0Sstevel@tonic-gate	($path, $base) = $Entity =~ /(.*\/)(.*)/;
275*0Sstevel@tonic-gate	push(@{$Struct->{"PATHS"}->{$base}}, $Entity);
276*0Sstevel@tonic-gate	if ($FType =~ /[ls]/) {			# link
277*0Sstevel@tonic-gate	    $rellinkent = "$Entity;$RelEntity";
278*0Sstevel@tonic-gate	    push (@RelLinkEnts,$rellinkent);	# make list of ents to resolve
279*0Sstevel@tonic-gate	} else {
280*0Sstevel@tonic-gate	    $MODE{$Entity} = $Mode if $Mode ne "";	# update MODE database
281*0Sstevel@tonic-gate	}
282*0Sstevel@tonic-gate    }
283*0Sstevel@tonic-gate    close IFILE;
284*0Sstevel@tonic-gate} # end foreach $IFile
285*0Sstevel@tonic-gate
286*0Sstevel@tonic-gate#
287*0Sstevel@tonic-gate# now convert the relative links into absolute ones
288*0Sstevel@tonic-gate#
289*0Sstevel@tonic-gate
290*0Sstevel@tonic-gate&yelp ("...making the ABSLINK database\n");
291*0Sstevel@tonic-gateforeach $rellinkent (@RelLinkEnts) {
292*0Sstevel@tonic-gate    ($Entity, $RelEntity) = split(/;/, $rellinkent);
293*0Sstevel@tonic-gate    $AbsLink = &GetAbsLink($Entity, $RelEntity);
294*0Sstevel@tonic-gate    $ABSLINK{$Entity} = $AbsLink;
295*0Sstevel@tonic-gate}
296*0Sstevel@tonic-gate
297*0Sstevel@tonic-gate#
298*0Sstevel@tonic-gate# close the dbs -- we're done
299*0Sstevel@tonic-gate#
300*0Sstevel@tonic-gate
301*0Sstevel@tonic-gatedbmclose (FTYPE);
302*0Sstevel@tonic-gatedbmclose (MODE);
303*0Sstevel@tonic-gatedbmclose (PKGS);
304*0Sstevel@tonic-gatedbmclose (ABSLINK);
305*0Sstevel@tonic-gatedbmclose (PKGNAMES);
306*0Sstevel@tonic-gate
307*0Sstevel@tonic-gate&yelp ("...DONE\n");
308*0Sstevel@tonic-gate#===========================END OF MAIN====================================
309*0Sstevel@tonic-gate
310*0Sstevel@tonic-gatesub GetAbsLink {	# convert relative link to actual one
311*0Sstevel@tonic-gatelocal ($entry, $rellink) = @_;
312*0Sstevel@tonic-gate
313*0Sstevel@tonic-gate    return $rellink if $rellink =~ /^\//;	# just return if abs already
314*0Sstevel@tonic-gate
315*0Sstevel@tonic-gate    @RelPath = split(/\//,$rellink);
316*0Sstevel@tonic-gate    @EntryPath = split(/\//,$entry);
317*0Sstevel@tonic-gate
318*0Sstevel@tonic-gate    #
319*0Sstevel@tonic-gate    # get the filename part
320*0Sstevel@tonic-gate    #
321*0Sstevel@tonic-gate
322*0Sstevel@tonic-gate    undef @AbsPath;
323*0Sstevel@tonic-gate    @AbsPath = (pop(@RelPath)) if $RelPath[$#RelPath] =~ /w/;
324*0Sstevel@tonic-gate    pop @EntryPath;
325*0Sstevel@tonic-gate
326*0Sstevel@tonic-gate    #
327*0Sstevel@tonic-gate    # pop the relative path until a relative dir shows up
328*0Sstevel@tonic-gate    #
329*0Sstevel@tonic-gate
330*0Sstevel@tonic-gate    while (@RelPath) {
331*0Sstevel@tonic-gate	$relhere = pop(@RelPath);
332*0Sstevel@tonic-gate	if ($relhere =~ /\w/) {			# there's a letter or number
333*0Sstevel@tonic-gate	    unshift (@AbsPath, $relhere);	# its a dirname; keep it
334*0Sstevel@tonic-gate	} elsif ($relhere =~ /^\.\.$/) {	# its a .. pop up one dir
335*0Sstevel@tonic-gate	    pop(@EntryPath);
336*0Sstevel@tonic-gate	} elsif ($relhere =~ /^\.$/) {		# it's a . -- stop
337*0Sstevel@tonic-gate	    last;
338*0Sstevel@tonic-gate	}
339*0Sstevel@tonic-gate    }
340*0Sstevel@tonic-gate
341*0Sstevel@tonic-gate    while (@EntryPath) {			# complete the path
342*0Sstevel@tonic-gate	unshift(@AbsPath, pop(@EntryPath));	# ...from the remaining entry
343*0Sstevel@tonic-gate    }
344*0Sstevel@tonic-gate    $abspath = join("/", @AbsPath);
345*0Sstevel@tonic-gate    if (!$FTYPE{$abspath}) {			# no installed entity !
346*0Sstevel@tonic-gate# NICKI - for now
347*0Sstevel@tonic-gate	&yelp("***CANNOT FIND ABSOLUTE PATH $abspath FOR ENTRY: $entry=$rellink\n");
348*0Sstevel@tonic-gate#	&yelp("***CANNOT RESOLVE ABSOLUTE PATH $abspath\n");
349*0Sstevel@tonic-gate
350*0Sstevel@tonic-gate# COMMENTED OUT BY NICKI
351*0Sstevel@tonic-gate#	$base = $rellink;
352*0Sstevel@tonic-gate#	$base =~ s/.*\///;			# get basename we're looking for
353*0Sstevel@tonic-gate#	@cans = @{$Struct->{"PATHS"}->{$base}};	# get all entities ...
354*0Sstevel@tonic-gate#	$numcans = $#cans + 1;				# ... with this base
355*0Sstevel@tonic-gate
356*0Sstevel@tonic-gate#	&yelp("   There are $numcans entries with this basename:\n");
357*0Sstevel@tonic-gate#	foreach $can (@cans) {
358*0Sstevel@tonic-gate#	    &yelp("       $can\n");
359*0Sstevel@tonic-gate#	}
360*0Sstevel@tonic-gate#	$abspath = "";
361*0Sstevel@tonic-gate    }
362*0Sstevel@tonic-gate    return $abspath;
363*0Sstevel@tonic-gate}
364*0Sstevel@tonic-gate
365*0Sstevel@tonic-gatesub ParseContentsEntry {
366*0Sstevel@tonic-gate#invocation: &ParseContentsEntry($l);	# $l is a line in the file
367*0Sstevel@tonic-gatelocal ($l) = @_;
368*0Sstevel@tonic-gate
369*0Sstevel@tonic-gate    #
370*0Sstevel@tonic-gate    # look for b or c entries, like:
371*0Sstevel@tonic-gate    #  /devices/pseudo/openeepr@0:openprom c none 38 0 0640 root sys SUNWcsd
372*0Sstevel@tonic-gate    #
373*0Sstevel@tonic-gate
374*0Sstevel@tonic-gate    if (($Entity,$FType,$Class,$Maj,$Min,$Mode,$Owner,$Group,@Pkgs) =
375*0Sstevel@tonic-gate      ($l =~ /^(\S+)\s+([bc])\s+(\w+)\s+([0-9]+)\s+([0-9]+)\s+([0-7]+)\s+([a-z]+)\s+([a-z]+)\s+([A-Z].*)/)) {
376*0Sstevel@tonic-gate
377*0Sstevel@tonic-gate    #
378*0Sstevel@tonic-gate    # look for d entries, like
379*0Sstevel@tonic-gate    #   /devices/pseudo d none 0755 root sys SUNWcsd
380*0Sstevel@tonic-gate    #
381*0Sstevel@tonic-gate
382*0Sstevel@tonic-gate    } elsif  (($Entity,$FType,$Class,$Mode,$Owner,$Group,@Pkgs) =
383*0Sstevel@tonic-gate      ($l =~ /^(\S+)\s+([d])\s+(\w+)\s+([0-7]+)\s+([a-z]+)\s+([a-z]+)\s+([A-Z].*)/)) {
384*0Sstevel@tonic-gate
385*0Sstevel@tonic-gate    #
386*0Sstevel@tonic-gate    # look for f or e  or v entries, like
387*0Sstevel@tonic-gate    #   /etc/asppp.cf f none 0744 root sys 360 27915 801314234 SUNWapppr
388*0Sstevel@tonic-gate    #
389*0Sstevel@tonic-gate
390*0Sstevel@tonic-gate    } elsif  (($Entity,$FType,$Class,$Mode,$Owner,$Group,
391*0Sstevel@tonic-gate      $Size,$Checksum,$Modtime,@Pkgs) =
392*0Sstevel@tonic-gate      ($l =~ /^(\S+)\s+([fev])\s+(\w+)\s+([0-7]+)\s+([a-z]+)\s+([a-z]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+([A-Z].*)/)) {
393*0Sstevel@tonic-gate
394*0Sstevel@tonic-gate    #
395*0Sstevel@tonic-gate    # look for l or s entries, like
396*0Sstevel@tonic-gate    #   /bin=./usr/bin s none SUNWcsr
397*0Sstevel@tonic-gate    #
398*0Sstevel@tonic-gate
399*0Sstevel@tonic-gate    } elsif  (($Entity,$RelEntity,$FType,$Class,@Pkgs) =
400*0Sstevel@tonic-gate      ($l =~ /^([^=]+)=(\S+)\s+([ls])\s+(\w+)\s+([A-Z].*)/)) {
401*0Sstevel@tonic-gate    } else {
402*0Sstevel@tonic-gate	print STDERR "Unrecognized entry in $IFile: $l\n";
403*0Sstevel@tonic-gate    }
404*0Sstevel@tonic-gate}
405*0Sstevel@tonic-gate
406*0Sstevel@tonic-gatesub ParsePkgmapEntry {
407*0Sstevel@tonic-gatelocal ($line) = @_;
408*0Sstevel@tonic-gate
409*0Sstevel@tonic-gate	# for validation of input
410*0Sstevel@tonic-gate	$Unresolved = true;
411*0Sstevel@tonic-gate
412*0Sstevel@tonic-gate	# look for d entries, like
413*0Sstevel@tonic-gate	# 1 d root etc 775 root sys
414*0Sstevel@tonic-gate
415*0Sstevel@tonic-gate	if (($Part,$FType,$Class,$Entity,$Mode,$Owner,$Group) =
416*0Sstevel@tonic-gate		($line =~ /^(\S+)\s+([d])\s+(\w+)\s+(\S+)\s+(\d+)\s+(\w+)\s+(\w+)/)) {
417*0Sstevel@tonic-gate		# prepend a install root
418*0Sstevel@tonic-gate		if ($thisBaseDir eq "/") {
419*0Sstevel@tonic-gate			$Entity = "/$Entity";
420*0Sstevel@tonic-gate		}
421*0Sstevel@tonic-gate		else {
422*0Sstevel@tonic-gate			$Entity = "$thisBaseDir/$Entity";
423*0Sstevel@tonic-gate		}
424*0Sstevel@tonic-gate		$Unresolved = false;
425*0Sstevel@tonic-gate	}
426*0Sstevel@tonic-gate
427*0Sstevel@tonic-gate	# look for e,f or v entries, like
428*0Sstevel@tonic-gate	# 1 e master boot/solaris/devicedb/master 0644 root sys 75 5775 940882596
429*0Sstevel@tonic-gate
430*0Sstevel@tonic-gate	elsif (($Part,$FType,$Class,$Entity,$Mode,$Owner,$Group,$Size,$Checksum,$Modtime) =
431*0Sstevel@tonic-gate		($line =~ /^(\S+)\s+([efv])\s+(\w+)\s+(\S+)\s+(\d+)\s+(\w+)\s+(\w+)/)) {
432*0Sstevel@tonic-gate
433*0Sstevel@tonic-gate		# prepend a install root
434*0Sstevel@tonic-gate		if ($thisBaseDir eq "/") {
435*0Sstevel@tonic-gate			$Entity = "/$Entity";
436*0Sstevel@tonic-gate		}
437*0Sstevel@tonic-gate		else {
438*0Sstevel@tonic-gate			$Entity = "$thisBaseDir/$Entity";
439*0Sstevel@tonic-gate		}
440*0Sstevel@tonic-gate		$Unresolved = false;
441*0Sstevel@tonic-gate	}
442*0Sstevel@tonic-gate	elsif  (($Part, $FType, $Class, $Entity, $RelEntity) =
443*0Sstevel@tonic-gate		($line =~ /^(\S+)\s+([ls])\s+(\w+)\s+(\S+)[=](\S+)/)) {
444*0Sstevel@tonic-gate
445*0Sstevel@tonic-gate		# prepend a install root
446*0Sstevel@tonic-gate		if ($thisBaseDir eq "/") {
447*0Sstevel@tonic-gate			$Entity = "/$Entity";
448*0Sstevel@tonic-gate		}
449*0Sstevel@tonic-gate		else {
450*0Sstevel@tonic-gate			$Entity = "$thisBaseDir/$Entity";
451*0Sstevel@tonic-gate		}
452*0Sstevel@tonic-gate		$Unresolved = false;
453*0Sstevel@tonic-gate	}
454*0Sstevel@tonic-gate
455*0Sstevel@tonic-gate	print ("UNRESOLVED: $line\n") if ($Unresolved eq true);
456*0Sstevel@tonic-gate}
457*0Sstevel@tonic-gate
458*0Sstevel@tonic-gatesub ParsePrototypeEntry {
459*0Sstevel@tonic-gate#invocation: &ParsePrototypeEntry($l);	# $l is a line in the file
460*0Sstevel@tonic-gatelocal ($l) = @_;
461*0Sstevel@tonic-gate
462*0Sstevel@tonic-gate    #
463*0Sstevel@tonic-gate    # look for b or c entries, like:
464*0Sstevel@tonic-gate    #  /devices/pseudo/openeepr@0:openprom c none 38 0 0640 root sys SUNWcsd
465*0Sstevel@tonic-gate    #
466*0Sstevel@tonic-gate
467*0Sstevel@tonic-gate    if (($Entity,$FType,$Class,$Maj,$Min,$Mode,$Owner,$Group,@Pkgs) =
468*0Sstevel@tonic-gate      ($l =~ /^(\S+)\s+([bc])\s+(\w+)\s+([0-9]+)\s+([0-9]+)\s+([0-7]+)\s+([a-z]+)\s+([a-z]+)\s+([A-Z].*)/)) {
469*0Sstevel@tonic-gate
470*0Sstevel@tonic-gate    #
471*0Sstevel@tonic-gate    # look for d entries, like
472*0Sstevel@tonic-gate    #   d root etc 775 root sys
473*0Sstevel@tonic-gate    #
474*0Sstevel@tonic-gate
475*0Sstevel@tonic-gate    } elsif  (($FType,$Class,$Entity,$Mode,$Owner,$Group) =
476*0Sstevel@tonic-gate      ($l =~ /^([d])\s+(\w+)\s+(\S+)\s+([0-7]+)\s+(\w+)\s+(\w+)/)) {
477*0Sstevel@tonic-gate
478*0Sstevel@tonic-gate    #
479*0Sstevel@tonic-gate    # look for f or e  or v entries, like
480*0Sstevel@tonic-gate    #   e preserve etc/acct/holidays 664 bin bin
481*0Sstevel@tonic-gate    #
482*0Sstevel@tonic-gate
483*0Sstevel@tonic-gate    } elsif  (($FType,$Class,$Entity,$Mode,$Owner,$Group) =
484*0Sstevel@tonic-gate      ($l =~ /^([fev])\s+(\w+)\s+(\S+)\s+([0-7]+)\s+(\w+)\s+(\w+)/)) {
485*0Sstevel@tonic-gate
486*0Sstevel@tonic-gate    #
487*0Sstevel@tonic-gate    # look for l or s entries, like
488*0Sstevel@tonic-gate    #   l root etc/rc2.d/S21perf=../../etc/init.d/perf
489*0Sstevel@tonic-gate    #
490*0Sstevel@tonic-gate
491*0Sstevel@tonic-gate    } elsif  (($FType,$Class,$Entity,$RelEntity) =
492*0Sstevel@tonic-gate      ($l =~ /^([ls])\s+(\w+)\s+([^=]+)=(\S+)/)) {
493*0Sstevel@tonic-gate    } else {
494*0Sstevel@tonic-gate	print STDERR "Unrecognized Prototype File entry: $l\n";
495*0Sstevel@tonic-gate    }
496*0Sstevel@tonic-gate}
497*0Sstevel@tonic-gate
498*0Sstevel@tonic-gatesub yelp {
499*0Sstevel@tonic-gatelocal($String) = @_;
500*0Sstevel@tonic-gate    print "$String";
501*0Sstevel@tonic-gate}
502*0Sstevel@tonic-gate
503*0Sstevel@tonic-gate
504*0Sstevel@tonic-gate
505*0Sstevel@tonic-gatesub MakePackageNamesDB  {
506*0Sstevel@tonic-gate#invocation: &MakePackageNamesDB($PkgDir);
507*0Sstevel@tonic-gatelocal ($PkgDir) = @_;		# argument is parent directory of pkg dirs
508*0Sstevel@tonic-gate
509*0Sstevel@tonic-gate    #$PkgDir = "/var/sadm/pkg";
510*0Sstevel@tonic-gate    opendir(PKGDIR, "$PkgDir") || die "Cannot open package directory $PkgDir\n";
511*0Sstevel@tonic-gate    @Pkgs = grep(/^[A-Z]/,readdir(PKGDIR));	# list of all package directories
512*0Sstevel@tonic-gate    foreach $Pkg (@Pkgs) {	# loop over 'em
513*0Sstevel@tonic-gate	$InfoFile = "$PkgDir/$Pkg/pkginfo";	# full name of the pkginfo file
514*0Sstevel@tonic-gate	if (-r $InfoFile) {	# if we can read it
515*0Sstevel@tonic-gate	    $str = `grep '^NAME=' $InfoFile`;	# just grep the entry
516*0Sstevel@tonic-gate	    $str =~ s/\s*\n$//;	# trim trailing ws
517*0Sstevel@tonic-gate	    $str =~ s/.*=\s*//;	# trim leading NAME=
518*0Sstevel@tonic-gate	    if ($str =~ /\w/) {	# if the name has a letter or number in it
519*0Sstevel@tonic-gate		$PKGNAMES{$Pkg} = $str;
520*0Sstevel@tonic-gate	    } else {
521*0Sstevel@tonic-gate		&yelp("***Cannot find usable NAME entry in $InfoFile\n");
522*0Sstevel@tonic-gate	    }
523*0Sstevel@tonic-gate	} else {
524*0Sstevel@tonic-gate	    &yelp("***Cannot find readable file $InfoFile\n");
525*0Sstevel@tonic-gate	}
526*0Sstevel@tonic-gate    } # end of loop over package directories
527*0Sstevel@tonic-gate}
528