#! /usr/bin/perl # ex:ts=8 sw=4: # $OpenBSD: pkg_info,v 1.25 2004/12/16 11:07:33 espie Exp $ # # Copyright (c) 2003-2004 Marc Espie # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. use strict; use warnings; use OpenBSD::PackageInfo; use OpenBSD::PackageName; use OpenBSD::Getopt; use OpenBSD::Error; my $total_size = 0; my $pkgs = 0; sub find_pkg { my ($pkg, $code) = @_; if (is_installed($pkg)) { &$code($pkg, installed_info($pkg)); return; } if (OpenBSD::PackageName::is_stem($pkg)) { my @l = sort (OpenBSD::PackageName::findstem($pkg, installed_packages())); if (@l != 0) { for my $p (@l) { &$code($p, installed_info($p)); } return; } } require OpenBSD::PackageLocator; my $true_package = OpenBSD::PackageLocator->find($pkg); return unless $true_package; my $dir = $true_package->info(); &$code($pkg, $dir); $true_package->close(); } sub printfile { my $filename = shift; local $_; open my $fh, '<', $filename or return; while(<$fh>) { print; } close $fh; } sub get_line { open my $fh, '<', shift or return ""; my $c = <$fh>; chomp($c); close $fh; return $c; } sub find_by_spec { my $pat = shift; require OpenBSD::PkgSpec; return sort(OpenBSD::PkgSpec::match($pat, installed_packages())); } sub filter_files { require OpenBSD::PackingOld; require OpenBSD::PackingList; my $search = shift; my @result = (); for my $arg (@_) { find_pkg($arg, sub { my ($pkg, $dir) = @_; my $plist = OpenBSD::PackingList->fromfile($dir.CONTENTS, \&OpenBSD::PackingList::FilesOnly); for my $item (@{$plist->{items}}) { next unless $item->IsFile(); my $fname = $item->fullname(); if (defined $search->{"$fname"}) { push(@{$search->{$fname}}, $pkg); push(@result, $pkg); } } }); } return @result; } my $all_plists; sub find_by_path { my $pat = shift; if (!defined $all_plists) { require OpenBSD::PackingOld; require OpenBSD::PackingList; $all_plists = []; for my $pkg (installed_packages()) { push(@$all_plists, OpenBSD::PackingList->from_installation($pkg, \&OpenBSD::PackingList::ExtraInfoOnly)); } } my @result = (); for my $plist (@$all_plists) { if ($plist->{extrainfo}->{subdir} eq $pat) { push(@result, $plist->pkgname()); } } return @result; } our ($opt_c, $opt_D, $opt_d, $opt_f, $opt_I, $opt_i, $opt_k, $opt_K, $opt_L, $opt_m, $opt_p, $opt_q, $opt_R, $opt_r, $opt_s, $opt_v, $opt_h, $opt_l, $opt_a, $opt_M, $opt_U, $opt_A); my $terse = 0; my $exit_code = 0; my @sought_files; sub print_info { my ($pkg, $dir) = @_; unless (-d $dir) { print STDERR "Error printing info for $pkg: no info ?\n"; } if ($opt_I) { my $l = 20 - length($pkg); $l = 1 if $l <= 0; print $pkg, " "x$l, get_line($dir.COMMENT), "\n"; } else { if ($terse) { print $opt_l, $pkg, "\n" unless $opt_q; } else { print $opt_l, "Information for ", $pkg, "\n\n" unless $opt_q; } if ($opt_c) { print $opt_l, "Comment:\n" unless $opt_q; printfile($dir.COMMENT); print "\n"; } if ($opt_R && -f $dir.REQUIRED_BY) { print $opt_l, "Required by:\n" unless $opt_q; printfile($dir.REQUIRED_BY); print "\n"; } if ($opt_d) { print $opt_l, "Description:\n" unless $opt_q; printfile($dir.DESC); print "\n"; } if ($opt_M && -f $dir.DISPLAY) { print $opt_l, "Install notice:\n" unless $opt_q; printfile($dir.DISPLAY); print "\n"; } if ($opt_U && -f $dir.UNDISPLAY) { print $opt_l, "Deinstall notice:\n" unless $opt_q; printfile($dir.UNDISPLAY); print "\n"; } if ($opt_i && -f $dir.INSTALL) { print $opt_l, "Install script:\n" unless $opt_q; printfile($dir.INSTALL); print "\n"; } if ($opt_k && -f $dir.DEINSTALL) { print $opt_l, "De-Install script:\n" unless $opt_q; printfile($dir.DEINSTALL, \*STDOUT); print "\n"; } if ($opt_r && -f $dir.REQUIRE) { print $opt_l, "Require script:\n" unless $opt_q; printfile($dir.REQUIRE, \*STDOUT); print "\n"; } my $plist; if ($opt_f || $opt_L || $opt_s) { require OpenBSD::PackingOld; require OpenBSD::PackingList; if ($opt_f || $opt_s) { $plist = OpenBSD::PackingList->fromfile($dir.CONTENTS); } else { $plist = OpenBSD::PackingList->fromfile($dir.CONTENTS, \&OpenBSD::PackingList::FilesOnly); } Fatal "Bad packing list" unless defined $plist; } if ($opt_L) { print $opt_l, "Files:\n" unless $opt_q; for my $item (@{$plist->{items}}) { next unless $item->IsFile(); if ($opt_K) { print '@', $item->keyword(), " "; } print $item->fullname(), "\n"; } print "\n"; } if ($opt_s) { my $size = 0; for my $item (@{$plist->{items}}) { next unless $item->IsFile(); if (defined $item->{size}) { $size += $item->{size}; } } print "Size: $size\n"; $total_size += $size; $pkgs++; } if ($opt_f) { print $opt_l, "Packing list:\n" unless $opt_q; $plist->write(\*STDOUT); print "\n"; } print $opt_l, "\n" unless $opt_q || $terse; } } set_usage('pkg_info [-cDdfIiKkLMpqRrsUv] [-E fname] [-e pkgname] [-l str] pkgname...', 'pkg_info [-Aa flags]'); try { getopts('cDdfhIikKLmpqRrsvhe:E:MU:l:aA', {'e' => sub { my $pat = shift; my @list; if ($pat =~ m/\//) { @list = find_by_path($pat); } else { @list = find_by_spec($pat); } if (@list == 0) { $exit_code = 1; } push(@ARGV, @list); $terse = 1; }, 'h' => sub { Usage(); }, 'E' => sub { require File::Spec; push(@sought_files, File::Spec->rel2abs(shift)); } }); } catchall { Usage($_); }; if ($opt_D) { $opt_M = 1; } unless ($opt_c || $opt_M || $opt_U || $opt_d || $opt_f || $opt_I || $opt_i || $opt_k || $opt_L || $opt_m || $opt_p || $opt_R || $opt_r || $opt_s || $terse) { if (@ARGV == 0) { $opt_I = $opt_a = 1; } else { $opt_c = $opt_d = $opt_R = 1; } } if ($opt_v) { $opt_c = $opt_d = $opt_f = $opt_i = $opt_k = $opt_r = $opt_M = $opt_U = $opt_m = $opt_R = $opt_s = 1; } if (!defined $opt_l) { $opt_l = ""; } if ($opt_K && !$opt_L) { Usage "-K only makes sense with -L"; } if (@ARGV == 0 && !$opt_a && !$opt_A) { Usage "Missing package name(s)" unless $terse && $opt_q; } if (@ARGV > 0 && ($opt_a || $opt_A)) { Usage "Can't specify package name(s) with -a"; } if (@ARGV == 0) { @ARGV = sort(installed_packages(defined $opt_A ? 0 : 1)); } if (@sought_files) { my %hash = map { ($_, []) } @sought_files; @ARGV = filter_files(\%hash, @ARGV); for my $f (@sought_files) { my $l = $hash{$f}; if (@$l) { print "$f: ", join(',', @$l), "\n" unless $opt_q; } else { $exit_code = 1; } } } for my $pkg (@ARGV) { find_pkg($pkg, \&print_info); } if ($pkgs > 1) { print "Total size: $total_size\n"; } exit($exit_code);