xref: /openbsd/usr.sbin/pkg_add/pkg_mklocatedb (revision a6445c1d)
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