1#! /usr/bin/perl 2# Copyright (c) 2005-2010 Marc Espie <espie@openbsd.org> 3# $OpenBSD: pkg_mklocatedb,v 1.43 2014/07/13 15:54:28 espie Exp $ 4# 5# Permission to use, copy, modify, and distribute this software for any 6# purpose with or without fee is hereby granted, provided that the above 7# copyright notice and this permission notice appear in all copies. 8# 9# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 17use strict; 18use warnings; 19 20use OpenBSD::PackageInfo; 21use OpenBSD::PackingList; 22use OpenBSD::Getopt; 23use OpenBSD::Error; 24use OpenBSD::Paths; 25use OpenBSD::AddCreateDelete; 26 27package OpenBSD::Pkgmklocatedb::State; 28our @ISA = qw(OpenBSD::AddCreateDelete::State); 29 30sub handle_options 31{ 32 my $state = shift; 33 $state->{no_exports} = 1; 34 $state->SUPER::handle_options('ad:Knqp:Pu', 35 '[-aKnPqu] [-d repository] [-p portsdir] [pkg-name ...]'); 36 $state->{portsdir} = $state->opt('p'); 37 $state->{pkgdir} = $state->opt('d'); 38 $state->{quiet} = $state->opt('q'); 39 $state->{pkgpath} = $state->opt('P'); 40 $state->{allinfo} = $state->opt('a'); 41 $state->{nopipe} = $state->opt('n'); 42 $state->{full} = $state->opt('K'); 43 $state->{update} = $state->opt('u'); 44} 45 46package OpenBSD::PackingElement; 47sub print_name {} 48sub set_header {} 49 50package OpenBSD::PackingElement::Name; 51sub set_header 52{ 53 my ($self, $state) = @_; 54 $state->{currentheader} = $self->{name}.':'; 55} 56 57package OpenBSD::PackingElement::ExtraInfo; 58sub set_header 59{ 60 my ($self, $state) = @_; 61 if ($state->{allinfo}) { 62 $state->{currentheader} .= $self->{subdir}.':'; 63 } elsif ($state->{pkgpath}) { 64 $state->{currentheader} = $self->{subdir}.':'; 65 } 66 $state->{done}{$self->{subdir}} = 1; 67 $state->errsay($state->{currentheader}) unless $state->{quiet}; 68} 69 70package OpenBSD::PackingElement::FileObject; 71sub object_name 72{ 73 my ($self, $state) = @_; 74 if ($state->{full}) { 75 if ($self->needs_keyword) { 76 return "\@".$self->keyword." ".$self->fullname; 77 } 78 } 79 return $self->fullname; 80} 81 82sub print_name 83{ 84 my ($self, $state) = @_; 85 print {$state->{out}} $state->{currentheader}, 86 $self->object_name($state), "\n"; 87} 88 89package OpenBSD::PackingElement::Action; 90sub print_name 91{ 92 my ($self, $state) = @_; 93 print {$state->{out}} $state->{currentheader}, $self->fullstring, "\n"; 94} 95 96package OpenBSD::PackingElement::ExeclikeAction; 97sub print_name 98{ 99 my ($self, $state) = @_; 100 print {$state->{out}} $state->{currentheader}, "\@". 101 $self->keyword, " ", $self->{expanded}, "\n"; 102} 103 104package OpenBSD::PackingElement::DirBase; 105sub print_name 106{ 107 my ($self, $state) = @_; 108 print {$state->{out}} $state->{currentheader}, 109 $self->object_name($state), "/\n"; 110} 111 112package main; 113 114sub open_output 115{ 116 my $state = shift; 117 118 119 if ($state->{nopipe} or -t STDOUT) { 120 $state->{out} = \*STDOUT; 121 } else { 122 my $MKLOCATEDB = OpenBSD::Paths->mklocatedb; 123 124 open $state->{out}, "|-", $MKLOCATEDB, $MKLOCATEDB or 125 $state->fatal("couldn't open pipe to mklocatedb: #1", $!); 126 } 127} 128 129sub print_out 130{ 131 my ($plist, $state) = @_; 132 133 $plist->set_header($state); 134 $plist->print_name($state); 135} 136 137sub do_portsdir 138{ 139 my $state = shift; 140 my $make = $ENV{MAKE} || 'make'; 141 my $target = defined $ENV{SUBDIRLIST} ? 142 'print-plist' : 'print-plist-all'; 143 delete $ENV{FLAVOR}; 144 delete $ENV{SUBPACKAGE}; 145 open my $in, "cd $state->{portsdir} && $make $target |"; 146 my $done = 0; 147 while (!$done) { 148 my $plist = OpenBSD::PackingList->read($in, 149 sub { 150 my ($fh, $cont) = @_; 151 while (<$fh>) { 152 return if m/^\=\=\=\> /o; 153 &$cont($_); 154 } 155 $done = 1; 156 }); 157 if (defined $plist && defined $plist->pkgname) { 158 print_out($plist, $state); 159 } 160 } 161 close($in); 162} 163 164sub do_pkgdir 165{ 166 my $state = shift; 167 168 require File::Find; 169 no warnings qw(once); 170 $state->fatal("Bad argument: #1 is not a directory", $state->{pkgdir}) 171 unless -d $state->{pkgdir}; 172 File::Find::find( 173 sub { 174 return unless -f $_; 175 my $plist = $state->repo->grabPlist($File::Find::name); 176 return unless defined $plist; 177 print_out($plist, $state); 178 }, $state->{pkgdir}); 179} 180 181sub copy_stdin 182{ 183 my $state = shift; 184 while (<STDIN>) { 185 # if we find something that looks like a pkgpath we've done 186 # assume we were updating it 187 if (m,([^:]*/[^:]*)\:,) { 188 next if defined $state->{done}{$1}; 189 } 190 print {$state->{out}} $_; 191 } 192} 193 194my $state = OpenBSD::Pkgmklocatedb::State->new("pkg_mklocatedb"); 195$state->handle_options; 196 197open_output($state); 198 199if ($state->{fatals}) { 200 $state->fatal("Files not found, can't continue"); 201} 202 203if ($state->{portsdir}) { 204 do_portsdir($state); 205} elsif ($state->{pkgdir}) { 206 do_pkgdir($state); 207} elsif (@ARGV == 0) { 208 if (!$state->{update}) { 209 $state->progress->for_list("Scanning installation", 210 [installed_packages()], sub { 211 my $pkgname = shift; 212 my $plist = 213 OpenBSD::PackingList->from_installation($pkgname); 214 return unless defined $plist; 215 print_out($plist, $state); 216 }); 217 } 218} else { 219 $state->progress->for_list("Scanning packages", \@ARGV, 220 sub { 221 my $pkgname = shift; 222 my $plist = $state->repo->grabPlist($pkgname); 223 next unless $plist; 224 print_out($plist, $state); 225 }); 226} 227if ($state->{update}) { 228 copy_stdin($state); 229} 230