8990 /opt/onbld/gk is useless
[unleashed.git] / usr / src / tools / depcheck / make_pkg_db
blob56691e1f8b9a831ab10d5f2d9eb27bc7932a86bb
1 #!/usr/bin/perl
3 # CDDL HEADER START
5 # The contents of this file are subject to the terms of the
6 # Common Development and Distribution License, Version 1.0 only
7 # (the "License"). You may not use this file except in compliance
8 # with the License.
10 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11 # or http://www.opensolaris.org/os/licensing.
12 # See the License for the specific language governing permissions
13 # and limitations under the License.
15 # When distributing Covered Code, include this CDDL HEADER in each
16 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17 # If applicable, add the following below this CDDL HEADER, with the
18 # fields enclosed by brackets "[]" replaced with your own identifying
19 # information: Portions Copyright [yyyy] [name of copyright owner]
21 # CDDL HEADER END
24 # Copyright (c) 2000 by Sun Microsystems, Inc.
25 # All rights reserved.
28 # ident "%Z%%M% %I% %E% SMI"
30 $PkgDir = "/var/sadm/pkg"; # where to find the pkg directories
31 $PROGRAM_NAME = "make_pkg_db";
32 $DBM_DIR_CHARACTERIZATION = "directory for the dbm databases";
33 $INPUT_FILES_CHARACTERIZATION = "one or more files in /var/sadm/install/contents format";
34 $PKGDEFS_DIRECTORY = "package pool directory";
36 $Usage =
37 "Usage: $PROGRAM_NAME
38 [-ifiles <$INPUT_FILES_CHARACTERIZATION>]
39 [-pkgdef <$PKGDEFS_DIRECTORY>]
40 -dbdir <$DBM_DIR_CHARACTERIZATION>
41 [-h for help]\n";
43 $Help =
44 "This program initializes a set of dbm databases with information
45 from /var/sadm/install/contents or a user-defined package pool directory.
46 There is one required argument:
48 -dbdir <dir> the $DBM_DIR_CHARACTERIZATION
50 \nThe optional argument -h produces this message instead of any processing.
51 \nThe optional argument -ifiles is used for symbolic link resolution.
52 \nThe optional argument -pkgdef creates the databases based upon a package \npool directory instead of /var/sadm/install/contents on the local machine.
57 # check for perl5 -- we use things unavailable in perl4
60 die "Sorry, this program requires perl version 5.000 or up. You have $]. Stopping" if $] < 5.000;
63 # process arguments
66 $PKGDefs = "";
68 while (@ARGV) {
69 $arg = shift (@ARGV);
70 if ($arg eq "-h") {
71 print "$Help\n$Usage";
72 exit 0;
73 } elsif ($arg eq "-ifiles") {
74 while (($ARGV[0] !~ /^-/) && (@ARGV)){
75 push (@IFiles, shift(@ARGV));
77 } elsif ($arg eq "-dbdir") {
78 $DBDir = shift(@ARGV) unless ($ARGV[0] =~ /^-/);
79 } elsif ($arg eq "-pkgdef") {
80 $PKGDefs = shift(@ARGV) unless ($ARGV[0] =~ /^-/);
81 } else {
82 print STDERR "Unrecognized argument $arg. \n$Usage";
83 exit 1;
87 # make sure the package pool directory exists
88 if (($PKGDefs) && !(-d $PKGDefs)) {
89 print STDERR "Cannot open the directory $PKGDefs\n";
90 exit 1;
93 # Here we define the input files which will be parsed
94 if ($PKGDefs) {
96 $dirs = `ls $PKGDefs`;
97 @dirlist = split(/\s*\n\s*/, $dirs);
99 foreach $dir (@dirlist) {
100 push(@IFiles, "$PKGDefs/$dir/pkgmap");
103 reverse(@IFiles);
105 else {
106 push(@IFiles, "/var/sadm/install/contents");
109 if (!@IFiles) {
110 print STDERR "Required argument -ifiles missing. \n$Usage";
111 exit 1;
114 if (!$DBDir) {
115 print STDERR "Required argument -dbdir missing. \n$Usage";
116 exit 1;
119 $Struct = \%struct; # here is the structure we'll store everything in
124 # now open the dbm databases we will initialize
126 &yelp ("...initializing the databases\n");
128 unless (-d "$DBDir") {
129 &yelp("Creating directory $DBDir\n");
130 mkdir($DBDir, 0777);
133 # db for package names from the /var/sadm/pkg/foo/pkginfo files
134 dbmopen(%PKGNAMES, "$DBDir/PKGNAMES", 0644) || die"Cannot open dbm db $DBDir/PKGNAMES\n";
136 # db for entity file types
137 dbmopen(%FTYPE, "$DBDir/FTYPE", 0664) || die"Cannot open dbm db $DBDir/FTYPE\n";
139 # db for entity modes types
140 dbmopen(%MODE, "$DBDir/MODE", 0664) || die"Cannot open dbm db $DBDir/MODE\n";
142 # db for entity packages
143 dbmopen(%PKGS, "$DBDir/PKGS", 0664) || die"Cannot open dbm db $DBDir/PKGS\n";
145 # db for absolute link targets
146 dbmopen(%ABSLINK, "$DBDir/ABSLINK", 0664) || die"Cannot open dbm db $DBDir/ABSLINK\n";
149 undef %FTYPE; # remove existing records, if any
150 undef %MODE;
151 undef %PKGS;
152 undef %ABSLINK;
153 undef %PKGNAMES;
155 $Debug = 1; # print extra gibberish
158 # go make the package names db
161 &MakePackageNamesDB($PkgDir);
164 # read and parse each input file in contents file format
167 &yelp ("...making the FTYPE MODE and PKGS databases\n");
168 foreach $IFile (@IFiles) {
169 if ($PKGDefs) {
170 unless (-r $IFile) {
171 print STDERR "Could not open file: $IFile\n";
172 next;
175 @pkgname = split("/", $IFile);
176 $thisPkg = @pkgname[($#pkgname-1)];
177 $pkgInfo="$PKGDefs/$thisPkg/pkginfo";
178 $thisBaseDir="";
179 if (-r $pkgInfo) {
180 $BASEDIR = `grep '^BASEDIR' $pkgInfo`;
181 $BASEDIR =~ s/^BASEDIR=//;
182 chomp($BASEDIR);
183 $thisBaseDir = $BASEDIR;
187 open (IFILE, "$IFile") || die "cannot open input file $IFile\n";
189 # Tell the user what we are looking at UNLESS they are looking at a package
190 # pool. A package pool could have hundreds of entries which just creates
191 # a lot of useless (and confusing) output.
192 &yelp("...opening $IFile\n") unless ($PKGDefs);
194 while (<IFILE>) { # loop over file line-at-a-time
195 if ($PKGDefs) {
196 next if /^:/; # ignore these lines from a pkgmap
197 next if (/(\S+)\s+[i]\s+/);
199 else {
200 next if /^#/; # ignore comments
201 next if /^\s*$/; # ignore blanks
205 chop;
206 undef $FType;
207 undef $Mode;
209 $line=$_;
211 if ($PKGDefs) {
212 &ParsePkgmapEntry($line);
213 @Pkgs = $thisPkg;
215 else {
216 &ParseContentsEntry($_);
219 # if this entry was supplied by a earlier file, skip it
221 if ($FTYPE{$Entity} =~ /\w/) {
223 # don't bother complaining about directories, we know the same
224 # directory could exist in multiple packages
225 next if ($FTYPE{$Entity} eq "d");
227 if ($PKGDefs) {
228 # In the case where we are going through a package pool, we
229 # expect that a file may reside in multiple packages. If
230 # that is detected, we simply add this package to the list of
231 # packages for that file
233 $currPkgs = $PKGS{$Entity};
234 next if ($FTYPE{$Entity} eq "s");
235 $PKGS{$Entity} = "$currPkgs $thisPkg";
237 else {
238 # In the case where we are reading in from
239 # /var/sadm/install.contents, we do not expect to see any
240 # over-ridden files EXCEPT when the "-ifiles" option is used.
241 &yelp("...OVERRIDDEN: $line\n");
243 next;
244 } else {
245 $Package = join(" ",@Pkgs);# store supplying packages sep by " "
247 # This is a hack. In the case of directories like /bin which
248 # would belong in many packages, the $PKGS hash would not
249 # be able to handle such a long entry. So for directories, I
250 # just place the first package I find. For this tool, it doesn't
251 # matter since this tool does not report which directories come
252 # from which package.
254 if ($FType eq "d") {
255 @FirstPackage = split(" ", $Package);
256 $PKGS{$Entity} = $FirstPackage[0];
258 else {
259 $PKGS{$Entity} = $Package; # update PKGS database
264 # put what we need from this entry line into the dbs
267 &yelp ("***NO FILETYPE! IGNORING ENTRY: $_\n") unless $FType;
268 $FTYPE{$Entity} = $FType; # update the FTYPE database
271 # now collect the possible paths for each basename
274 ($path, $base) = $Entity =~ /(.*\/)(.*)/;
275 push(@{$Struct->{"PATHS"}->{$base}}, $Entity);
276 if ($FType =~ /[ls]/) { # link
277 $rellinkent = "$Entity;$RelEntity";
278 push (@RelLinkEnts,$rellinkent); # make list of ents to resolve
279 } else {
280 $MODE{$Entity} = $Mode if $Mode ne ""; # update MODE database
283 close IFILE;
284 } # end foreach $IFile
287 # now convert the relative links into absolute ones
290 &yelp ("...making the ABSLINK database\n");
291 foreach $rellinkent (@RelLinkEnts) {
292 ($Entity, $RelEntity) = split(/;/, $rellinkent);
293 $AbsLink = &GetAbsLink($Entity, $RelEntity);
294 $ABSLINK{$Entity} = $AbsLink;
298 # close the dbs -- we're done
301 dbmclose (FTYPE);
302 dbmclose (MODE);
303 dbmclose (PKGS);
304 dbmclose (ABSLINK);
305 dbmclose (PKGNAMES);
307 &yelp ("...DONE\n");
308 #===========================END OF MAIN====================================
310 sub GetAbsLink { # convert relative link to actual one
311 local ($entry, $rellink) = @_;
313 return $rellink if $rellink =~ /^\//; # just return if abs already
315 @RelPath = split(/\//,$rellink);
316 @EntryPath = split(/\//,$entry);
319 # get the filename part
322 undef @AbsPath;
323 @AbsPath = (pop(@RelPath)) if $RelPath[$#RelPath] =~ /w/;
324 pop @EntryPath;
327 # pop the relative path until a relative dir shows up
330 while (@RelPath) {
331 $relhere = pop(@RelPath);
332 if ($relhere =~ /\w/) { # there's a letter or number
333 unshift (@AbsPath, $relhere); # its a dirname; keep it
334 } elsif ($relhere =~ /^\.\.$/) { # its a .. pop up one dir
335 pop(@EntryPath);
336 } elsif ($relhere =~ /^\.$/) { # it's a . -- stop
337 last;
341 while (@EntryPath) { # complete the path
342 unshift(@AbsPath, pop(@EntryPath)); # ...from the remaining entry
344 $abspath = join("/", @AbsPath);
345 if (!$FTYPE{$abspath}) { # no installed entity !
346 # NICKI - for now
347 &yelp("***CANNOT FIND ABSOLUTE PATH $abspath FOR ENTRY: $entry=$rellink\n");
348 # &yelp("***CANNOT RESOLVE ABSOLUTE PATH $abspath\n");
350 # COMMENTED OUT BY NICKI
351 # $base = $rellink;
352 # $base =~ s/.*\///; # get basename we're looking for
353 # @cans = @{$Struct->{"PATHS"}->{$base}}; # get all entities ...
354 # $numcans = $#cans + 1; # ... with this base
356 # &yelp(" There are $numcans entries with this basename:\n");
357 # foreach $can (@cans) {
358 # &yelp(" $can\n");
360 # $abspath = "";
362 return $abspath;
365 sub ParseContentsEntry {
366 #invocation: &ParseContentsEntry($l); # $l is a line in the file
367 local ($l) = @_;
370 # look for b or c entries, like:
371 # /devices/pseudo/openeepr@0:openprom c none 38 0 0640 root sys SUNWcsd
374 if (($Entity,$FType,$Class,$Maj,$Min,$Mode,$Owner,$Group,@Pkgs) =
375 ($l =~ /^(\S+)\s+([bc])\s+(\w+)\s+([0-9]+)\s+([0-9]+)\s+([0-7]+)\s+([a-z]+)\s+([a-z]+)\s+([A-Z].*)/)) {
378 # look for d entries, like
379 # /devices/pseudo d none 0755 root sys SUNWcsd
382 } elsif (($Entity,$FType,$Class,$Mode,$Owner,$Group,@Pkgs) =
383 ($l =~ /^(\S+)\s+([d])\s+(\w+)\s+([0-7]+)\s+([a-z]+)\s+([a-z]+)\s+([A-Z].*)/)) {
386 # look for f or e or v entries, like
387 # /etc/asppp.cf f none 0744 root sys 360 27915 801314234 SUNWapppr
390 } elsif (($Entity,$FType,$Class,$Mode,$Owner,$Group,
391 $Size,$Checksum,$Modtime,@Pkgs) =
392 ($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].*)/)) {
395 # look for l or s entries, like
396 # /bin=./usr/bin s none SUNWcsr
399 } elsif (($Entity,$RelEntity,$FType,$Class,@Pkgs) =
400 ($l =~ /^([^=]+)=(\S+)\s+([ls])\s+(\w+)\s+([A-Z].*)/)) {
401 } else {
402 print STDERR "Unrecognized entry in $IFile: $l\n";
406 sub ParsePkgmapEntry {
407 local ($line) = @_;
409 # for validation of input
410 $Unresolved = true;
412 # look for d entries, like
413 # 1 d root etc 775 root sys
415 if (($Part,$FType,$Class,$Entity,$Mode,$Owner,$Group) =
416 ($line =~ /^(\S+)\s+([d])\s+(\w+)\s+(\S+)\s+(\d+)\s+(\w+)\s+(\w+)/)) {
417 # prepend a install root
418 if ($thisBaseDir eq "/") {
419 $Entity = "/$Entity";
421 else {
422 $Entity = "$thisBaseDir/$Entity";
424 $Unresolved = false;
427 # look for e,f or v entries, like
428 # 1 e master boot/solaris/devicedb/master 0644 root sys 75 5775 940882596
430 elsif (($Part,$FType,$Class,$Entity,$Mode,$Owner,$Group,$Size,$Checksum,$Modtime) =
431 ($line =~ /^(\S+)\s+([efv])\s+(\w+)\s+(\S+)\s+(\d+)\s+(\w+)\s+(\w+)/)) {
433 # prepend a install root
434 if ($thisBaseDir eq "/") {
435 $Entity = "/$Entity";
437 else {
438 $Entity = "$thisBaseDir/$Entity";
440 $Unresolved = false;
442 elsif (($Part, $FType, $Class, $Entity, $RelEntity) =
443 ($line =~ /^(\S+)\s+([ls])\s+(\w+)\s+(\S+)[=](\S+)/)) {
445 # prepend a install root
446 if ($thisBaseDir eq "/") {
447 $Entity = "/$Entity";
449 else {
450 $Entity = "$thisBaseDir/$Entity";
452 $Unresolved = false;
455 print ("UNRESOLVED: $line\n") if ($Unresolved eq true);
458 sub ParsePrototypeEntry {
459 #invocation: &ParsePrototypeEntry($l); # $l is a line in the file
460 local ($l) = @_;
463 # look for b or c entries, like:
464 # /devices/pseudo/openeepr@0:openprom c none 38 0 0640 root sys SUNWcsd
467 if (($Entity,$FType,$Class,$Maj,$Min,$Mode,$Owner,$Group,@Pkgs) =
468 ($l =~ /^(\S+)\s+([bc])\s+(\w+)\s+([0-9]+)\s+([0-9]+)\s+([0-7]+)\s+([a-z]+)\s+([a-z]+)\s+([A-Z].*)/)) {
471 # look for d entries, like
472 # d root etc 775 root sys
475 } elsif (($FType,$Class,$Entity,$Mode,$Owner,$Group) =
476 ($l =~ /^([d])\s+(\w+)\s+(\S+)\s+([0-7]+)\s+(\w+)\s+(\w+)/)) {
479 # look for f or e or v entries, like
480 # e preserve etc/acct/holidays 664 bin bin
483 } elsif (($FType,$Class,$Entity,$Mode,$Owner,$Group) =
484 ($l =~ /^([fev])\s+(\w+)\s+(\S+)\s+([0-7]+)\s+(\w+)\s+(\w+)/)) {
487 # look for l or s entries, like
488 # l root etc/rc2.d/S21perf=../../etc/init.d/perf
491 } elsif (($FType,$Class,$Entity,$RelEntity) =
492 ($l =~ /^([ls])\s+(\w+)\s+([^=]+)=(\S+)/)) {
493 } else {
494 print STDERR "Unrecognized Prototype File entry: $l\n";
498 sub yelp {
499 local($String) = @_;
500 print "$String";
505 sub MakePackageNamesDB {
506 #invocation: &MakePackageNamesDB($PkgDir);
507 local ($PkgDir) = @_; # argument is parent directory of pkg dirs
509 #$PkgDir = "/var/sadm/pkg";
510 opendir(PKGDIR, "$PkgDir") || die "Cannot open package directory $PkgDir\n";
511 @Pkgs = grep(/^[A-Z]/,readdir(PKGDIR)); # list of all package directories
512 foreach $Pkg (@Pkgs) { # loop over 'em
513 $InfoFile = "$PkgDir/$Pkg/pkginfo"; # full name of the pkginfo file
514 if (-r $InfoFile) { # if we can read it
515 $str = `grep '^NAME=' $InfoFile`; # just grep the entry
516 $str =~ s/\s*\n$//; # trim trailing ws
517 $str =~ s/.*=\s*//; # trim leading NAME=
518 if ($str =~ /\w/) { # if the name has a letter or number in it
519 $PKGNAMES{$Pkg} = $str;
520 } else {
521 &yelp("***Cannot find usable NAME entry in $InfoFile\n");
523 } else {
524 &yelp("***Cannot find readable file $InfoFile\n");
526 } # end of loop over package directories