1eef84043Sespie#! /usr/bin/perl
2eef84043Sespie
3eef84043Sespie# ex:ts=8 sw=4:
4*7068cea4Sespie# $OpenBSD: PkgCheck.pm,v 1.81 2023/06/16 10:38:29 espie Exp $
5eef84043Sespie#
645019a4aSespie# Copyright (c) 2003-2014 Marc Espie <espie@openbsd.org>
7eef84043Sespie#
8eef84043Sespie# Permission to use, copy, modify, and distribute this software for any
9eef84043Sespie# purpose with or without fee is hereby granted, provided that the above
10eef84043Sespie# copyright notice and this permission notice appear in all copies.
11eef84043Sespie#
12eef84043Sespie# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13eef84043Sespie# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14eef84043Sespie# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15eef84043Sespie# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16eef84043Sespie# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17eef84043Sespie# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18eef84043Sespie# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19eef84043Sespie
20039cbdaaSespieuse v5.36;
21eef84043Sespie
22eef84043Sespieuse OpenBSD::AddCreateDelete;
23eef84043Sespie
24556a8905Sespiepackage Installer::State;
25556a8905Sespieour @ISA = qw(OpenBSD::PkgAdd::State);
26039cbdaaSespiesub new($class, $cmd)
27556a8905Sespie{
28556a8905Sespie	my $state = $class->SUPER::new($cmd);
29556a8905Sespie	$state->{localbase} = OpenBSD::Paths->localbase;
30556a8905Sespie	return $state;
31556a8905Sespie}
32556a8905Sespie
33556a8905Sespiepackage Installer;
34556a8905Sespieour @ISA = qw(OpenBSD::PkgAdd);
35556a8905Sespie
36039cbdaaSespiesub new($class, $mystate)
37556a8905Sespie{
38556a8905Sespie	my $state = Installer::State->new("pkg_check");
39556a8905Sespie	$state->{v} = $mystate->{v};
407279417dSespie	$state->{subst} = $mystate->{subst};
41556a8905Sespie	$state->{interactive} = $mystate->{interactive};
42556a8905Sespie	$state->{destdir} = $mystate->{destdir};
4356f6d8b7Sespie	$state->{signature_style} = $mystate->{signature_style};
44e05b4ceeSespie	$state->progress->setup($state->opt('x'), $state->opt('m'), $state);
45556a8905Sespie	bless { state => $state}, $class;
46556a8905Sespie}
47556a8905Sespie
48039cbdaaSespiesub install($self, $pkg)
49556a8905Sespie{
50556a8905Sespie	my $state = $self->{state};
51556a8905Sespie	push(@{$state->{setlist}},
52556a8905Sespie	    $state->updateset->add_hints2($pkg));
53fddcf565Sespie	$self->try_and_run_command($state);
54556a8905Sespie	return $state->{bad} != 0;
55556a8905Sespie}
56556a8905Sespie
57eef84043Sespiepackage OpenBSD::PackingElement;
58039cbdaaSespiesub thorough_check($self, $state)
59eef84043Sespie{
60eef84043Sespie	$self->basic_check($state);
61eef84043Sespie}
62eef84043Sespie
63039cbdaaSespiesub basic_check($, $)
64eef84043Sespie{
659a24c98bSespie	1
66eef84043Sespie}
67eef84043Sespie
68039cbdaaSespie# $self->find_dpendencies($state, $l, $checker, $pkgname)
69039cbdaaSespiesub find_dependencies($, $, $, $, $)
70eef84043Sespie{
71eef84043Sespie}
72eef84043Sespie
73039cbdaaSespie# XXX this is a snag for ShareLibs OO-ness
74039cbdaaSespie# $self->mark_indirect_depends($pkgname, $state)
75039cbdaaSespiesub mark_indirect_depends($self, $pkgname, $state)
7602ee83faSespie{
7708eb747cSespie	$self->mark_available_lib($pkgname, $state->shlibs);
7802ee83faSespie}
7902ee83faSespie
80039cbdaaSespie# $self->cache_depends($copy)
81039cbdaaSespiesub cache_depends($, $)
824be5dd99Sespie{
834be5dd99Sespie}
844be5dd99Sespie
8502ee83faSespiepackage OpenBSD::PackingElement::DefineTag;
8602ee83faSespie
87039cbdaaSespiesub mark_indirect_depends($self, $pkgname, $state)
8802ee83faSespie{
8902ee83faSespie	$state->{tagdefinition}{$self->name} = $pkgname;
9002ee83faSespie}
9102ee83faSespie
92eef84043Sespiepackage OpenBSD::PackingElement::FileBase;
93eef84043Sespieuse File::Basename;
94eef84043Sespie
95039cbdaaSespiesub basic_check($self, $state)
96eef84043Sespie{
970f19ffacSespie	my $name = $state->destdir($self->fullname);
98eef84043Sespie	$state->{known}{dirname($name)}{basename($name)} = 1;
99eef84043Sespie	if ($self->{symlink}) {
100eef84043Sespie		if (!-l $name) {
1010dc934edSespie			if (!-e $name) {
1027e83eca3Sespie				$state->log("#1 should be a symlink but does not exist", $name);
1030dc934edSespie			} else {
1047e83eca3Sespie				$state->log("#1 is not a symlink", $name);
1050dc934edSespie			}
1069a24c98bSespie			return 0;
107eb01027bSespie		} else {
108eb01027bSespie			if (readlink($name) ne $self->{symlink}) {
1097e83eca3Sespie				$state->log("#1 should point to #2 but points to #3 instead",
1107e83eca3Sespie				    $name, $self->{symlink}, readlink($name));
1119a24c98bSespie				return 0;
112eb01027bSespie			}
113eef84043Sespie		}
1149a24c98bSespie		return 1;
115eef84043Sespie	}
1160dc934edSespie	if (!-e $name) {
1170dc934edSespie		if (-l $name) {
1187e83eca3Sespie			$state->log("#1 points to non-existent #2",
1197e83eca3Sespie			    $name, readlink($name));
1200dc934edSespie		} else {
1217e83eca3Sespie			$state->log("#1 should exist", $name);
1220dc934edSespie		}
1239a24c98bSespie	    	return 0;
1249a24c98bSespie	} elsif (!-f _) {
1257e83eca3Sespie		$state->log("#1 is not a file", $name);
1269a24c98bSespie		return 0;
127eef84043Sespie	}
128eb01027bSespie	if ($self->{link}) {
129eb01027bSespie		my ($a, $b) = (stat _)[0, 1];
1300f19ffacSespie		if (!-f $state->destdir($self->{link})) {
1317e83eca3Sespie			$state->log("#1 should link to non-existent #2",
1327e83eca3Sespie			    $name, $self->{link});
1339a24c98bSespie			return 0;
134eb01027bSespie		} else {
135eb01027bSespie			my ($c, $d) = (stat _)[0, 1];
136eb01027bSespie			if (defined $a && defined $c) {
137eb01027bSespie				if ($a != $c || $b != $d) {
1387e83eca3Sespie					$state->log("#1 doesn't link to #2",
1397e83eca3Sespie					    $name, $self->{link});
1409a24c98bSespie					return 0;
141eb01027bSespie				}
142eb01027bSespie			}
1439a24c98bSespie
144eb01027bSespie		}
145eb01027bSespie	}
1469a24c98bSespie	return 1;
147eef84043Sespie}
148eef84043Sespie
149039cbdaaSespiesub thorough_check($self, $state)
150eef84043Sespie{
1510f19ffacSespie	my $name = $state->destdir($self->fullname);
1529a24c98bSespie	if (!$self->basic_check($state)) {
1539a24c98bSespie		return;
1549a24c98bSespie	}
155eef84043Sespie	return if $self->{link} or $self->{symlink} or $self->{nochecksum};
156eef84043Sespie	if (!-r $name) {
1577e83eca3Sespie		$state->log("can't read #1", $name);
158eef84043Sespie		return;
159eef84043Sespie	}
16000231fa2Sespie	if (!defined $self->{d}) {
16100231fa2Sespie		$state->log("no checksum for #1", $name);
16200231fa2Sespie		return;
16300231fa2Sespie	}
164a5de4416Sespie	my $d = $self->compute_digest($name, $self->{d});
165eef84043Sespie	if (!$d->equals($self->{d})) {
1667e83eca3Sespie		$state->log("checksum for #1 does not match", $name);
167eef84043Sespie	}
168eef84043Sespie}
169eef84043Sespie
170eef84043Sespiepackage OpenBSD::PackingElement::SpecialFile;
171039cbdaaSespiesub basic_check	# forwarder
172eef84043Sespie{
173eef84043Sespie	&OpenBSD::PackingElement::FileBase::basic_check;
174eef84043Sespie}
175eef84043Sespie
176039cbdaaSespiesub thorough_check	# forwarder
177eef84043Sespie{
178eef84043Sespie	&OpenBSD::PackingElement::FileBase::basic_check;
179eef84043Sespie}
180eef84043Sespie
181eef84043Sespiepackage OpenBSD::PackingElement::DirlikeObject;
182039cbdaaSespiesub basic_check($self, $state)
183eef84043Sespie{
1840f19ffacSespie	my $name = $state->destdir($self->fullname);
185eef84043Sespie	$state->{known}{$name} //= {};
186eef84043Sespie	if (!-e $name) {
1877e83eca3Sespie		$state->log("#1 should exist", $name);
188eef84043Sespie	}
189eef84043Sespie	if (!-d _) {
1907e83eca3Sespie		$state->log("#1 is not a directory", $name);
191eef84043Sespie	}
192eef84043Sespie}
193eef84043Sespie
194a991246fSespiepackage OpenBSD::PackingElement::Sample;
195a991246fSespieuse File::Basename;
196039cbdaaSespiesub basic_check($self, $state)
197a991246fSespie{
1980f19ffacSespie	my $name = $state->destdir($self->fullname);
199a991246fSespie	$state->{known}{dirname($name)}{basename($name)} = 1;
2009a24c98bSespie	return 1;
201a991246fSespie}
202a991246fSespie
203a991246fSespiepackage OpenBSD::PackingElement::Sampledir;
204039cbdaaSespiesub basic_check($self, $state)
205a991246fSespie{
2060f19ffacSespie	my $name = $state->destdir($self->fullname);
207a991246fSespie	$state->{known}{$name} //= {};
2089a24c98bSespie	return 1;
209a991246fSespie}
210a991246fSespie
211eef84043Sespiepackage OpenBSD::PackingElement::Mandir;
212039cbdaaSespiesub basic_check($self, $state)
213eef84043Sespie{
214eef84043Sespie	$self->SUPER::basic_check($state);
2150f19ffacSespie	my $name = $state->destdir($self->fullname);
216f723c71dSespie	for my $file (OpenBSD::Paths->man_cruft) {
217752d47c3Sespie		$state->{known}{$name}{$file} = 1;
218752d47c3Sespie	}
2199a24c98bSespie	return 1;
220eef84043Sespie}
221eef84043Sespie
222eef84043Sespiepackage OpenBSD::PackingElement::Fontdir;
223039cbdaaSespiesub basic_check($self, $state)
224eef84043Sespie{
225eef84043Sespie	$self->SUPER::basic_check($state);
2260f19ffacSespie	my $name = $state->destdir($self->fullname);
227eef84043Sespie	for my $i (qw(fonts.alias fonts.scale fonts.dir)) {
228eef84043Sespie		$state->{known}{$name}{$i} = 1;
229eef84043Sespie	}
2309a24c98bSespie	return 1;
231eef84043Sespie}
232eef84043Sespie
233eef84043Sespiepackage OpenBSD::PackingElement::Infodir;
234039cbdaaSespiesub basic_check($self, $state)
235eef84043Sespie{
236eef84043Sespie	$self->SUPER::basic_check($state);
2370f19ffacSespie	my $name = $state->destdir($self->fullname);
238eef84043Sespie	$state->{known}{$name}{'dir'} = 1;
2399a24c98bSespie	return 1;
240eef84043Sespie}
241eef84043Sespie
2424be5dd99Sespiepackage OpenBSD::PackingElement::Depend;
243039cbdaaSespiesub cache_depends($self, $copy)
2444be5dd99Sespie{
2454be5dd99Sespie	$self->add_object($copy);
2464be5dd99Sespie}
2474be5dd99Sespie
248eef84043Sespiepackage OpenBSD::PackingElement::Dependency;
249039cbdaaSespiesub find_dependencies($self, $state, $l, $checker, $pkgname)
250eef84043Sespie{
251eef84043Sespie	# several ways to failure
252eef84043Sespie	if (!$self->spec->is_valid) {
253eef84043Sespie		$state->log("invalid \@", $self->keyword, " ",
254eef84043Sespie		    $self->stringize);
255eef84043Sespie		return;
256eef84043Sespie	}
257eef84043Sespie	my @deps = $self->spec->filter(@$l);
258eef84043Sespie	if (@deps == 0) {
25902ee83faSespie		$state->log("dependency #1 in #2 does not match any installed package",
26002ee83faSespie		    $self->stringize, $pkgname);
261eef84043Sespie		return;
262eef84043Sespie	}
263eef84043Sespie	my $okay = 0;
264eef84043Sespie	for my $i (@deps) {
265bf3472c5Sespie		if ($checker->find($i)) {
266eef84043Sespie			$okay = 1;
267eef84043Sespie		}
268eef84043Sespie	}
269eef84043Sespie	if (!$okay) {
270bf3472c5Sespie		$checker->not_found($deps[0]);
271eef84043Sespie	}
272eef84043Sespie}
273eef84043Sespie
27410f87983Sespiepackage OpenBSD::PackingElement::Wantlib;
275039cbdaaSespiesub find_dependencies($self, $state, $l, $checker, $pkgname)
27610f87983Sespie{
27708eb747cSespie	my $r = $state->shlibs->lookup_libspec($state->{localbase},
27810f87983Sespie	    $self->spec);
2797e83eca3Sespie	if (defined $r && @$r != 0) {
28010f87983Sespie		my $okay = 0;
28110f87983Sespie		for my $lib (@$r) {
28210f87983Sespie			my $i = $lib->origin;
28310f87983Sespie			if ($i eq 'system') {
28410f87983Sespie				$okay = 1;
2852779f69aSespie				$state->{needed_libs}{$lib->to_string} = 1;
28610f87983Sespie				next;
28710f87983Sespie			}
288bf3472c5Sespie			if ($checker->find($i)) {
28910f87983Sespie				$okay = 1;
29010f87983Sespie			}
29110f87983Sespie		}
29210f87983Sespie		if (!$okay) {
293bf3472c5Sespie			$checker->not_found($r->[0]->origin);
29410f87983Sespie		}
29510f87983Sespie	} else {
29602ee83faSespie		$state->log("#1 in #2 not found", $self->stringize, $pkgname);
29702ee83faSespie	}
29802ee83faSespie}
29902ee83faSespie
30002ee83faSespiepackage OpenBSD::PackingElement::Tag;
301039cbdaaSespiesub find_dependencies($self, $state, $l, $checker, $pkgname)
30202ee83faSespie{
30302ee83faSespie	my $location = $state->{tagdefinition}{$self->name};
30402ee83faSespie	if (defined $location) {
30502ee83faSespie		if ($location eq $pkgname) {
30602ee83faSespie			return;
30702ee83faSespie		}
30802ee83faSespie		if (!$checker->find($location)) {
30902ee83faSespie			$checker->not_found($location);
31002ee83faSespie		}
31102ee83faSespie	} else {
31202ee83faSespie		$state->log("definition for #1 not found", $self->stringize);
31310f87983Sespie	}
31410f87983Sespie}
31510f87983Sespie
316039cbdaaSespiesub cache_depends	# forwarder
3174be5dd99Sespie{
3184be5dd99Sespie	&OpenBSD::PackingElement::Depend::cache_depends;
3194be5dd99Sespie}
3204be5dd99Sespie
321eef84043Sespiepackage OpenBSD::PkgCheck::State;
322eef84043Sespieour @ISA = qw(OpenBSD::AddCreateDelete::State);
323eef84043Sespie
3240f19ffacSespieuse File::Spec;
3255f05097cSespieuse OpenBSD::Log;
3260f19ffacSespieuse File::Basename;
3275f05097cSespie
328039cbdaaSespiesub init($self)
329eef84043Sespie{
330f4f6c15cSespie	$self->{l} = OpenBSD::Log->new($self);
331eef84043Sespie	$self->SUPER::init;
332eef84043Sespie}
333eef84043Sespie
334039cbdaaSespiesub log($self, @p)
335eef84043Sespie{
336039cbdaaSespie	if (@p == 0) {
337eef84043Sespie		return $self->{l};
338eef84043Sespie	} else {
339039cbdaaSespie		$self->{l}->say(@p);
340eef84043Sespie	}
341eef84043Sespie}
342eef84043Sespie
343039cbdaaSespiesub handle_options($self)
34483ad63f0Sespie{
34583ad63f0Sespie	$self->{no_exports} = 1;
34683ad63f0Sespie
3473f0a1a28Sespie	$self->add_interactive_options;
3488cd3e493Sespie	$self->SUPER::handle_options('fFB:q',
34983181d8dSjmc		'[-FfIimnqvx] [-B pkg-destdir] [-D value]');
35083ad63f0Sespie	$self->{force} = $self->opt('f');
351c3f1c9b4Sespie	$self->{quick} = $self->opt('q') // 0;
3528cd3e493Sespie	$self->{filesystem} = $self->opt('F');
35383ad63f0Sespie	if (defined $self->opt('B')) {
35483ad63f0Sespie		$self->{destdir} = $self->opt('B');
35583ad63f0Sespie	}
35683ad63f0Sespie	if (defined $self->{destdir}) {
35783ad63f0Sespie		$self->{destdir} .= '/';
35883ad63f0Sespie	} else {
35983ad63f0Sespie		$self->{destdir} = '';
36083ad63f0Sespie	}
3610f19ffacSespie}
3620f19ffacSespie
363039cbdaaSespiesub destdir($self, $path)
3640f19ffacSespie{
3650f19ffacSespie	return File::Spec->canonpath($self->{destdir}.$path);
3660f19ffacSespie}
3670f19ffacSespie
368039cbdaaSespiesub process_entry($self, $entry)
3690f19ffacSespie{
3700f19ffacSespie	my $name = $self->destdir($entry);
3710f19ffacSespie	$self->{known}{dirname($name)}{basename($name)} = 1;
37283ad63f0Sespie}
37383ad63f0Sespie
374bf3472c5Sespiepackage OpenBSD::DependencyCheck;
375bf3472c5Sespie
376039cbdaaSespiesub new($class, $state, $name, $req)
377bf3472c5Sespie{
378bf3472c5Sespie	my $o = bless {
379bf3472c5Sespie		not_yet => {},
380bf3472c5Sespie		possible => {},
381bf3472c5Sespie		others => {},
382bf3472c5Sespie		name => $name,
383bf3472c5Sespie		req => $req
384bf3472c5Sespie	    }, $class;
385bf3472c5Sespie	for my $pkg ($req->list) {
386bf3472c5Sespie		$o->{not_yet}{$pkg} = 1;
387bf3472c5Sespie		if ($state->{exists}{$pkg}) {
388bf3472c5Sespie			$o->{possible}{$pkg} = 1;
389bf3472c5Sespie		} else {
390549f66e1Sespie			$state->errsay("#1: bogus #2", $name, $o->string($pkg));
391bf3472c5Sespie		}
392bf3472c5Sespie	}
393bf3472c5Sespie	return $o;
394bf3472c5Sespie}
395bf3472c5Sespie
396039cbdaaSespiesub find($self, $name)
397bf3472c5Sespie{
398bf3472c5Sespie	if ($self->{possible}{$name}) {
399bf3472c5Sespie		delete $self->{not_yet}{$name};
400bf3472c5Sespie		return 1;
401bf3472c5Sespie	} else {
402bf3472c5Sespie		return 0;
403bf3472c5Sespie	}
404bf3472c5Sespie}
405bf3472c5Sespie
406039cbdaaSespiesub not_found($self, $name)
407bf3472c5Sespie{
408bf3472c5Sespie	$self->{others}{$name} = 1;
409bf3472c5Sespie}
410bf3472c5Sespie
411039cbdaaSespiesub ask_delete_deps($self, $state, $l)
412bf3472c5Sespie{
413bf3472c5Sespie	if ($state->{force}) {
414bf3472c5Sespie		$self->{req}->delete(@$l);
415fb75580aSespie	} elsif ($state->confirm_defaults_to_no(
416949b3cdfSespie	    "Remove extra #1", $self->string(@$l))) {
417bf3472c5Sespie			$self->{req}->delete(@$l);
418bf3472c5Sespie	}
419bf3472c5Sespie}
420bf3472c5Sespie
421039cbdaaSespiesub ask_add_deps($self, $state, $l)
422bf3472c5Sespie{
423bf3472c5Sespie	if ($state->{force}) {
424bf3472c5Sespie		$self->{req}->add(@$l);
425fb75580aSespie	} elsif ($state->confirm_defaults_to_no(
426fb75580aSespie	    "Add missing #1", $self->string(@$l))) {
427bf3472c5Sespie			$self->{req}->add(@$l);
428bf3472c5Sespie	}
429bf3472c5Sespie}
430bf3472c5Sespie
431039cbdaaSespiesub adjust($self, $state)
432bf3472c5Sespie{
433bf3472c5Sespie	if (keys %{$self->{not_yet}} > 0) {
434bf3472c5Sespie		my @todo = sort keys %{$self->{not_yet}};
4357e83eca3Sespie		unless ($state->{subst}->value("weed_libs")) {
4367e83eca3Sespie			@todo = grep {!/^\.libs/} @todo;
4377e83eca3Sespie		}
4387e83eca3Sespie		if (@todo != 0) {
4395f4221d5Ssthen			$state->errsay("#1 has too many #2",
440549f66e1Sespie			    $self->{name}, $self->string(@todo));
441bf3472c5Sespie			$self->ask_delete_deps($state, \@todo);
442bf3472c5Sespie		}
4437e83eca3Sespie	}
444bf3472c5Sespie	if (keys %{$self->{others}} > 0) {
445bf3472c5Sespie		my @todo = sort keys %{$self->{others}};
4467e83eca3Sespie		$state->errsay("#1 is missing #2",
4477e83eca3Sespie		    $self->{name}, $self->string(@todo));
44834134382Sespie		    if ($self->{name} =~ m/^partial/) {
44934134382Sespie			    $state->errsay("not a problem, since this is a partial- package");
45034134382Sespie		    } else {
451bf3472c5Sespie			    $self->ask_add_deps($state, \@todo);
452bf3472c5Sespie		    }
453bf3472c5Sespie	}
45434134382Sespie}
455bf3472c5Sespie
456bf3472c5Sespiepackage OpenBSD::DirectDependencyCheck;
457bf3472c5Sespieour @ISA = qw(OpenBSD::DependencyCheck);
458bf3472c5Sespieuse OpenBSD::RequiredBy;
459039cbdaaSespiesub string($self, @p)
460bf3472c5Sespie{
461039cbdaaSespie	return "dependencies: ". join(' ', @p);
462bf3472c5Sespie}
463bf3472c5Sespie
464039cbdaaSespiesub new($class, $state, $name)
465bf3472c5Sespie{
466bf3472c5Sespie	return $class->SUPER::new($state, $name,
467bf3472c5Sespie	    OpenBSD::Requiring->new($name));
468bf3472c5Sespie}
469bf3472c5Sespie
470bf3472c5Sespiepackage OpenBSD::ReverseDependencyCheck;
471bf3472c5Sespieour @ISA = qw(OpenBSD::DependencyCheck);
472bf3472c5Sespieuse OpenBSD::RequiredBy;
473039cbdaaSespiesub string($self, @p)
474bf3472c5Sespie{
475039cbdaaSespie	return "reverse dependencies: ". join(' ', @p);
476bf3472c5Sespie}
477bf3472c5Sespie
478039cbdaaSespiesub new($class, $state, $name)
479bf3472c5Sespie{
480bf3472c5Sespie	return $class->SUPER::new($state, $name,
481bf3472c5Sespie	    OpenBSD::RequiredBy->new($name));
482bf3472c5Sespie}
483bf3472c5Sespie
484bd2f84f9Sespiepackage OpenBSD::Pkglocate;
485039cbdaaSespiesub new($class, $state)
486556a8905Sespie{
487e0cbfadbSespie	bless {state => $state, result => {unknown => []},
488e0cbfadbSespie	    params => []}, $class;
489556a8905Sespie}
490556a8905Sespie
491039cbdaaSespiesub add_param($self, @p)
492556a8905Sespie{
493556a8905Sespie	push(@{$self->{params}}, @p);
494bd2f84f9Sespie	while (@{$self->{params}} > 200) {
495556a8905Sespie		$self->run_command;
496556a8905Sespie	}
497556a8905Sespie}
498556a8905Sespie
499039cbdaaSespiesub run_command($self)
500556a8905Sespie{
501556a8905Sespie	if (@{$self->{params}} == 0) {
502556a8905Sespie		return;
503556a8905Sespie	}
504556a8905Sespie	my %h = map {($_, 1)} @{$self->{params}};
505bd2f84f9Sespie	open(my $cmd, '-|', 'pkg_locate', map {"*:$_"} @{$self->{params}});
506556a8905Sespie	while (<$cmd>) {
507556a8905Sespie		chomp;
508bd2f84f9Sespie		my ($pkgname, $pkgpath, $path) = split(':', $_, 3);
509e0cbfadbSespie
510556a8905Sespie		# pkglocate will return false positives, so trim them
511556a8905Sespie		if ($h{$path}) {
512bd2f84f9Sespie			push(@{$self->{result}{"$pkgname:$pkgpath"} }, $path);
513556a8905Sespie			delete $h{$path};
514556a8905Sespie		}
515556a8905Sespie	}
516556a8905Sespie	close($cmd);
517556a8905Sespie	for my $k (keys %h) {
518556a8905Sespie		push(@{$self->{result}{unknown}}, $k);
519556a8905Sespie	}
520556a8905Sespie
521556a8905Sespie	$self->{params} = [];
522556a8905Sespie}
523556a8905Sespie
524*7068cea4Sespiesub show_results($self)
525556a8905Sespie{
526556a8905Sespie	while (@{$self->{params}} > 0) {
527556a8905Sespie		$self->run_command;
528556a8905Sespie	}
529556a8905Sespie	my $state = $self->{state};
530556a8905Sespie	my $r = $self->{result};
531556a8905Sespie	my $u = $r->{unknown};
532556a8905Sespie	delete $r->{unknown};
53347e4d683Sespie
53447e4d683Sespie	$state->say("Not found:");
53547e4d683Sespie	for my $e (sort @$u) {
53647e4d683Sespie		$state->say("\t#1", $e);
53747e4d683Sespie	}
53847e4d683Sespie
539556a8905Sespie	for my $k (sort keys %{$r}) {
540556a8905Sespie		$state->say("In #1:", $k);
541556a8905Sespie		for my $e (sort @{$r->{$k}}) {
542556a8905Sespie			$state->say("\t#1", $e);
543556a8905Sespie		}
544556a8905Sespie	}
545556a8905Sespie}
546556a8905Sespie
547eef84043Sespiepackage OpenBSD::PkgCheck;
548eef84043Sespieour @ISA = qw(OpenBSD::AddCreateDelete);
549eef84043Sespie
550eef84043Sespieuse OpenBSD::PackageInfo;
551eef84043Sespieuse OpenBSD::PackingList;
552eef84043Sespieuse File::Find;
553eef84043Sespieuse OpenBSD::Paths;
554eef84043Sespieuse OpenBSD::Mtree;
555eef84043Sespie
556039cbdaaSespiesub fill_base_system($self, $state)
557bd2f84f9Sespie{
558bd2f84f9Sespie	open(my $cmd, '-|', 'locate',
55961d49fb8Sespie	    '-d', OpenBSD::Paths->srclocatedb,
56061d49fb8Sespie	    '-d', OpenBSD::Paths->xlocatedb, ':');
561bd2f84f9Sespie	while (<$cmd>) {
562bd2f84f9Sespie		chomp;
563bd2f84f9Sespie		my ($set, $path) = split(':', $_, 2);
564bd2f84f9Sespie		$state->{basesystem}{$path} = 1;
565bd2f84f9Sespie	}
566bd2f84f9Sespie	close($cmd);
567bd2f84f9Sespie}
568bd2f84f9Sespie
569039cbdaaSespiesub remove($self, $state, $name)
570eef84043Sespie{
571eef84043Sespie	$state->{removed}{$name} = 1;
572eef84043Sespie	my $dir = installed_info($name);
573eef84043Sespie	for my $i (@OpenBSD::PackageInfo::info) {
574eef84043Sespie		if (-e $dir.$i) {
575eef84043Sespie			if ($state->verbose) {
576549f66e1Sespie				$state->say("unlink(#1)", $dir.$i);
577eef84043Sespie			}
578eef84043Sespie			unless ($state->{not}) {
579eef84043Sespie				unlink($dir.$i) or
5807e83eca3Sespie				    $state->errsay("#1: Couldn't delete #2: #3",
581549f66e1Sespie				    	$name, $dir.$i, $!);
582eef84043Sespie			}
583eef84043Sespie		}
584eef84043Sespie	}
585eef84043Sespie	if (-f $dir) {
586eef84043Sespie		if ($state->verbose) {
587549f66e1Sespie			$state->say("unlink(#1)", $dir);
588eef84043Sespie		}
589eef84043Sespie		unless ($state->{not}) {
590eef84043Sespie			unlink($dir) or
5917e83eca3Sespie			    $state->errsay("#1: Couldn't delete #2: #3",
592549f66e1Sespie				$name, $dir, $!);
593eef84043Sespie		}
594eef84043Sespie	} elsif (-d $dir) {
595eef84043Sespie		if ($state->verbose) {
596549f66e1Sespie			$state->say("rmdir(#1)", $dir);
597eef84043Sespie		}
598eef84043Sespie		unless ($state->{not}) {
599eef84043Sespie			rmdir($dir) or
6007e83eca3Sespie			    $state->errsay("#1: Couldn't delete #2: #3",
601549f66e1Sespie			    	$name, $dir, $!);
602eef84043Sespie		}
603eef84043Sespie	}
604eef84043Sespie}
605eef84043Sespie
606039cbdaaSespiesub may_remove($self, $state, $name)
607eef84043Sespie{
608eef84043Sespie	if ($state->{force}) {
609eef84043Sespie		$self->remove($state, $name);
610fb75580aSespie	} elsif ($state->confirm_defaults_to_no(
611fb75580aSespie	    "Remove wrong package #1", $name)) {
612eef84043Sespie			$self->remove($state, $name);
613eef84043Sespie	}
61457231a67Sespie	$state->{bogus}{$name} = 1;
615eef84043Sespie}
616eef84043Sespie
617039cbdaaSespiesub may_unlink($self, $state, $path)
6188734ed95Sespie{
6198734ed95Sespie	if (!$state->{force} &&
620fb75580aSespie	    !$state->confirm_defaults_to_no("Remove #1", $path)) {
6218734ed95Sespie		return;
6228734ed95Sespie	}
6238734ed95Sespie	if ($state->verbose) {
624549f66e1Sespie		$state->say("remove #1", $path);
6258734ed95Sespie	}
6268734ed95Sespie	return if $state->{not};
627549f66e1Sespie	unlink($path) or rmdir($path) or
628549f66e1Sespie	    $state->errsay("Couldn't delete #1: #2", $path, $!);
6298734ed95Sespie}
6308734ed95Sespie
631039cbdaaSespiesub may_fix_ownership($self, $state, $path)
632ebe8b9f1Sespie{
633ebe8b9f1Sespie	if (!$state->{force} &&
634fb75580aSespie	    !$state->confirm_defaults_to_no("Give #1 to root:wheel", $path)) {
635ebe8b9f1Sespie		return;
636ebe8b9f1Sespie	}
637ebe8b9f1Sespie	if ($state->verbose) {
638549f66e1Sespie		$state->say("chown root:wheel #1", $path);
639ebe8b9f1Sespie	}
640ebe8b9f1Sespie	return if $state->{not};
641ebe8b9f1Sespie	chown 0, 0, $path or
642549f66e1Sespie	    $state->errsay("Couldn't fix ownership for #1: #2", $path, $!);
643ebe8b9f1Sespie}
644ebe8b9f1Sespie
645039cbdaaSespiesub may_fix_perms($self, $state, $path, $perm, $readable)
6468734ed95Sespie{
6478734ed95Sespie	if (!$state->{force} &&
648fb75580aSespie	    !$state->confirm_defaults_to_no("Make #1 #2", $path,
649ebe8b9f1Sespie	    ($readable ? "not world/group-writable" : "world readable"))) {
6508734ed95Sespie		return;
6518734ed95Sespie	}
6528734ed95Sespie	if ($state->verbose) {
653549f66e1Sespie		$state->say("chmod #1 #2", sprintf("%04o", $perm), $path);
6548734ed95Sespie	}
6558734ed95Sespie	return if $state->{not};
6568734ed95Sespie	chmod $perm, $path or
657549f66e1Sespie	    $state->errsay("Couldn't fix perms for #1: #2", $path, $!);
6588734ed95Sespie}
6598734ed95Sespie
660039cbdaaSespiesub for_all_packages($self, $state, $l, $msg, $code)
6610dc934edSespie{
662f4f6c15cSespie	$state->progress->for_list($msg, $l,
663039cbdaaSespie	    sub($name) {
664039cbdaaSespie		return if $state->{removed}{$name};
665039cbdaaSespie		if ($state->{bogus}{$name}) {
666039cbdaaSespie			$state->errsay("skipping #1", $name);
66757231a67Sespie			return;
66857231a67Sespie		}
669039cbdaaSespie		&$code($name);
670f4f6c15cSespie	    });
6710dc934edSespie}
6720dc934edSespie
673039cbdaaSespiesub check_dir_permissions($self, $state, $dir)
6748734ed95Sespie{
675ebe8b9f1Sespie	my ($perm, $uid, $gid) = (stat $dir)[2, 4, 5];
676ebe8b9f1Sespie	$perm &= 0777;
6778734ed95Sespie
6788734ed95Sespie	if (($perm & 0555) != 0555) {
679549f66e1Sespie		$state->errsay("Directory #1 is not world-readable", $dir);
680ebe8b9f1Sespie		$perm |= 0555;
681ebe8b9f1Sespie		$self->may_fix_perms($state, $dir, $perm, 0);
6828734ed95Sespie	}
683ebe8b9f1Sespie	if ($uid != 0 || $gid != 0) {
684ebe8b9f1Sespie		$state->errsay("Directory #1 does not belong to root:wheel",
685549f66e1Sespie		    $dir);
686ebe8b9f1Sespie	    	$self->may_fix_ownership($state, $dir);
687ebe8b9f1Sespie	}
688ebe8b9f1Sespie	if (($perm & 0022) != 0) {
689549f66e1Sespie		$state->errsay("Directory #1 is world/group writable", $dir);
690ebe8b9f1Sespie		$perm &= 0755;
691ebe8b9f1Sespie		$self->may_fix_perms($state, $dir, $perm, 1);
692ebe8b9f1Sespie	}
693ebe8b9f1Sespie}
694ebe8b9f1Sespie
695039cbdaaSespiesub check_permissions($self, $state, $dir)
696ebe8b9f1Sespie{
697ebe8b9f1Sespie	$self->check_dir_permissions($state, $dir);
698549f66e1Sespie	opendir(my $d, $dir) or return;
699549f66e1Sespie	for my $name (readdir $d) {
700549f66e1Sespie		next if $name eq '.' or $name eq '..';
701ebe8b9f1Sespie		my $file = $dir.$name;
702549f66e1Sespie		if (!grep {$_ eq $name} (@OpenBSD::PackageInfo::info)) {
703549f66e1Sespie			$state->errsay("Weird filename in pkg db: #1",
704549f66e1Sespie			    $file);
705549f66e1Sespie			$self->may_unlink($state, $file);
706549f66e1Sespie			next;
707549f66e1Sespie		}
708ebe8b9f1Sespie		my ($perm, $uid, $gid) = (stat $file)[2, 4, 5];
7098734ed95Sespie		if (!-f $file) {
710549f66e1Sespie			$state->errsay("#1 should be a file", $file);
7118734ed95Sespie			$self->may_unlink($state, $file);
712ebe8b9f1Sespie			next;
713ebe8b9f1Sespie		}
714ebe8b9f1Sespie		$perm &= 0777;
715ebe8b9f1Sespie		if (($perm & 0444) != 0444) {
716549f66e1Sespie			$state->errsay("File #1 is not world-readable", $file);
717ebe8b9f1Sespie			$perm |= 0444;
718ebe8b9f1Sespie			$self->may_fix_perms($state, $file, $perm, 0);
7198734ed95Sespie		}
720ebe8b9f1Sespie		if ($uid != 0 || $gid != 0) {
721ebe8b9f1Sespie			$state->errsay("File #1 does not belong to root:wheel",
722549f66e1Sespie			    $file);
723ebe8b9f1Sespie			$self->may_fix_ownership($state, $file);
724ebe8b9f1Sespie		}
725ebe8b9f1Sespie		if (($perm & 0022) != 0) {
726ebe8b9f1Sespie			$state->errsay("File #1 is world/group writable",
727549f66e1Sespie			    $file);
728ebe8b9f1Sespie			$perm &= 0755;
729ebe8b9f1Sespie			$self->may_fix_perms($state, $file, $perm, 1);
730ebe8b9f1Sespie		}
7318734ed95Sespie	}
732549f66e1Sespie	closedir($d);
7338734ed95Sespie}
7348734ed95Sespie
7358734ed95Sespie
736039cbdaaSespiesub sanity_check($self, $state, $l)
737eef84043Sespie{
7388734ed95Sespie	# let's find /var/db/pkg or its equivalent
7398734ed95Sespie	my $base = installed_info("");
7408734ed95Sespie	$base =~ s,/*$,,;
741ebe8b9f1Sespie	$self->check_dir_permissions($state, $base);
7428734ed95Sespie
743039cbdaaSespie	$self->for_all_packages($state, $l, "Packing-list sanity", sub($name) {
744549f66e1Sespie		if ($name ne $state->safe($name)) {
745549f66e1Sespie			$state->errsay("#1: bogus pkgname", $name);
746549f66e1Sespie			$self->may_remove($state, $name);
747549f66e1Sespie			return;
748549f66e1Sespie		}
749eef84043Sespie		my $info = installed_info($name);
750eef84043Sespie		if (-f $info) {
75123bb920cSespie			$state->errsay("#1: #2 should be a directory",
752549f66e1Sespie			    $name, $info);
753eef84043Sespie			if ($info =~ m/\.core$/) {
7547e83eca3Sespie				$state->errsay("looks like a core dump, ".
755eef84043Sespie					"removing");
756eef84043Sespie				$self->remove($state, $name);
757eef84043Sespie			} else {
758eef84043Sespie				$self->may_remove($state, $name);
759eef84043Sespie			}
760a1f569a1Sespie			return;
761eef84043Sespie		}
7628734ed95Sespie		$self->check_permissions($state, $info);
763eef84043Sespie		my $contents = $info.OpenBSD::PackageInfo::CONTENTS;
764eef84043Sespie		unless (-f $contents) {
765549f66e1Sespie			$state->errsay("#1: missing #2", $name, $contents);
766eef84043Sespie			$self->may_remove($state, $name);
767a1f569a1Sespie			return;
768eef84043Sespie		}
769eef84043Sespie		my $plist;
770eef84043Sespie		eval {
771eef84043Sespie			$plist = OpenBSD::PackingList->fromfile($contents);
772eef84043Sespie		};
773ff2f6eceSespie		if ($@ || !defined $plist) {
774549f66e1Sespie			$state->errsay("#1: bad packing-list", $name);
7759873b3f8Sespie			if ($@) {
776549f66e1Sespie				$state->errsay("#1", $@);
7779873b3f8Sespie			}
778eef84043Sespie			$self->may_remove($state, $name);
779a1f569a1Sespie			return;
780eef84043Sespie		}
78178bb2478Sespie		if (!defined $plist->pkgname) {
782549f66e1Sespie			$state->errsay("#1: no pkgname in plist", $name);
78378bb2478Sespie			$self->may_remove($state, $name);
78478bb2478Sespie			return;
78578bb2478Sespie		}
786eef84043Sespie		if ($plist->pkgname ne $name) {
787549f66e1Sespie			$state->errsay("#1: pkgname does not match", $name);
788eef84043Sespie			$self->may_remove($state, $name);
789eef84043Sespie		}
79002ee83faSespie		$plist->mark_indirect_depends($plist->pkgname, $state);
7914be5dd99Sespie		my $p = OpenBSD::PackingList->new;
7924be5dd99Sespie		$plist->cache_depends($p);
7934be5dd99Sespie		$state->{plist_cache}{$plist->pkgname} = $p;
7940dc934edSespie		$state->{exists}{$plist->pkgname} = 1;
7950dc934edSespie	});
796eef84043Sespie}
797eef84043Sespie
798039cbdaaSespiesub dependencies_check($self, $state, $l)
799eef84043Sespie{
80008eb747cSespie	$state->shlibs->add_libs_from_system($state->{destdir});
801039cbdaaSespie	$self->for_all_packages($state, $l, "Direct dependencies", sub($name) {
8022779f69aSespie		$state->log->set_context($name);
8034be5dd99Sespie		my $plist = $state->{plist_cache}{$name};
804bf3472c5Sespie		my $checker = OpenBSD::DirectDependencyCheck->new($state,
805bf3472c5Sespie		    $name);
80610f87983Sespie		$state->{localbase} = $plist->localbase;
80702ee83faSespie		$plist->find_dependencies($state, $l, $checker, $name);
808bf3472c5Sespie		$checker->adjust($state);
809bf3472c5Sespie		for my $dep ($checker->{req}->list) {
81079cf49beSespie			push(@{$state->{reverse}{$dep}}, $name);
81179cf49beSespie		}
81279cf49beSespie	});
8134be5dd99Sespie	delete $state->{plist_cache};
81479cf49beSespie}
81579cf49beSespie
816039cbdaaSespiesub reverse_dependencies_check($self, $state, $l)
81779cf49beSespie{
818039cbdaaSespie	$self->for_all_packages($state, $l, "Reverse dependencies", sub($name) {
819bf3472c5Sespie		my $checker = OpenBSD::ReverseDependencyCheck->new($state,
820bf3472c5Sespie		    $name);
82179cf49beSespie		for my $i (@{$state->{reverse}{$name}}) {
822bf3472c5Sespie			$checker->find($i) or $checker->not_found($i);
82379cf49beSespie		}
824bf3472c5Sespie		$checker->adjust($state);
8250dc934edSespie	});
826eef84043Sespie}
827eef84043Sespie
828039cbdaaSespiesub package_files_check($self, $state, $l)
829eef84043Sespie{
830039cbdaaSespie	$self->for_all_packages($state, $l, "Files from packages", sub($name) {
831eef84043Sespie		my $plist = OpenBSD::PackingList->from_installation($name);
832eef84043Sespie		$state->log->set_context($name);
833eef84043Sespie		if ($state->{quick}) {
834eef84043Sespie			$plist->basic_check($state);
835eef84043Sespie		} else {
836eef84043Sespie			$plist->thorough_check($state);
837eef84043Sespie		}
83808eb747cSespie		$plist->mark_available_lib($plist->pkgname, $state->shlibs);
8390dc934edSespie	});
840eef84043Sespie}
841eef84043Sespie
842039cbdaaSespiesub install_pkglocate($self, $state)
843556a8905Sespie{
844bd2f84f9Sespie	my $spec = 'pkglocatedb->=1.1';
845c5ec2d87Sespie
846c5ec2d87Sespie	my @l = installed_stems()->find('pkglocatedb');
8476a9c80c4Sespie	require OpenBSD::PkgSpec;
848c5ec2d87Sespie	if (OpenBSD::PkgSpec->new($spec)->match_ref(\@l)) {
849556a8905Sespie		return 1;
850556a8905Sespie	}
851fb75580aSespie	unless ($state->confirm_defaults_to_no("Unknown file system entries.\n".
852c5ec2d87Sespie	    "Do you want to install $spec to look them up")) {
853556a8905Sespie	    	return 0;
854556a8905Sespie	}
855556a8905Sespie
856556a8905Sespie	require OpenBSD::PkgAdd;
857556a8905Sespie
858556a8905Sespie	$state->{installer} //= Installer->new($state);
859c5ec2d87Sespie	if ($state->{installer}->install('pkglocatedb--')) {
860556a8905Sespie		return 1;
861556a8905Sespie	} else {
862c5ec2d87Sespie		$state->errsay("Couldn't install #1", $spec);
863556a8905Sespie		return 0;
864556a8905Sespie	}
865556a8905Sespie}
866556a8905Sespie
867556a8905Sespie# non fancy display of unknown objects
868039cbdaaSespiesub display_unknown($self, $state)
869556a8905Sespie{
870556a8905Sespie	if (defined $state->{unknown}{file}) {
871556a8905Sespie		$state->say("Unknown files:");
872556a8905Sespie		for my $e (sort @{$state->{unknown}{file}}) {
873556a8905Sespie			$state->say("\t#1", $e);
874556a8905Sespie		}
875556a8905Sespie	}
876556a8905Sespie	if (defined $state->{unknown}{dir}) {
877556a8905Sespie		$state->say("Unknown directories:");
878556a8905Sespie		for my $e (sort {$b cmp $a } @{$state->{unknown}{dir}}) {
879556a8905Sespie			$state->say("\t#1", $e);
880556a8905Sespie		}
881556a8905Sespie	}
882556a8905Sespie}
883556a8905Sespie
884039cbdaaSespiesub display_tmps($self, $state)
885ebff90d8Sespie{
886ebff90d8Sespie	$state->say("Unregistered temporary files:");
887ebff90d8Sespie	for my $e (sort @{$state->{tmps}}) {
888ebff90d8Sespie		$state->say("\t#1", $e);
889ebff90d8Sespie	}
890ebff90d8Sespie	if ($state->{force}) {
891ebff90d8Sespie		unlink(@{$state->{tmps}});
892fb75580aSespie	} elsif ($state->confirm_defaults_to_no("Remove")) {
893ebff90d8Sespie			unlink(@{$state->{tmps}});
894ebff90d8Sespie	}
895ebff90d8Sespie}
896ebff90d8Sespie
897039cbdaaSespiesub display_unregs($self, $state)
8982779f69aSespie{
8992779f69aSespie	$state->say("System libs NOT in locate dbs:");
9002779f69aSespie	for my $e (sort @{$state->{unreg_libs}}) {
9012779f69aSespie		$state->say("\t#1", $e);
9022779f69aSespie	}
9032779f69aSespie}
9042779f69aSespie
905039cbdaaSespiesub locate_unknown($self, $state)
906556a8905Sespie{
907bd2f84f9Sespie	my $locator = OpenBSD::Pkglocate->new($state);
908556a8905Sespie	if (defined $state->{unknown}{file}) {
909556a8905Sespie		$state->progress->for_list("Locating unknown files",
910556a8905Sespie		    $state->{unknown}{file},
911039cbdaaSespie			sub($p) {
912039cbdaaSespie				$locator->add_param($p);
913556a8905Sespie			});
914556a8905Sespie	}
915556a8905Sespie	if (defined $state->{unknown}{dir}) {
916556a8905Sespie		$state->progress->for_list("Locating unknown directories",
917556a8905Sespie		    $state->{unknown}{dir},
918039cbdaaSespie			sub($p) {
919039cbdaaSespie				$locator->add_param($p);
920556a8905Sespie			});
921556a8905Sespie	}
922*7068cea4Sespie	$locator->show_results;
923556a8905Sespie}
924556a8905Sespie
925039cbdaaSespiesub fill_localbase($self, $state, $base)
926eef84043Sespie{
927f723c71dSespie	for my $file (OpenBSD::Paths->man_cruft) {
928752d47c3Sespie		$state->{known}{$base."/man"}{$file} = 1;
929752d47c3Sespie	}
930eb01027bSespie	$state->{known}{$base."/info"}{'dir'} = 1;
931eb01027bSespie	$state->{known}{$base."/lib/X11"}{'app-defaults'} = 1;
932eb01027bSespie	$state->{known}{$base."/libdata"} = {};
933eb01027bSespie	$state->{known}{$base."/libdata/perl5"} = {};
9340f19ffacSespie}
9350f19ffacSespie
936039cbdaaSespiesub fill_root($self, $state, $root)
9370f19ffacSespie{
9380f19ffacSespie	OpenBSD::Mtree::parse($state->{known}, $root,
9390f19ffacSespie	    '/etc/mtree/4.4BSD.dist', 1);
9400f19ffacSespie	OpenBSD::Mtree::parse($state->{known}, $root,
9410f19ffacSespie	    '/etc/mtree/BSD.x11.dist', 1);
9420f19ffacSespie}
9430f19ffacSespie
944039cbdaaSespiesub filesystem_check($self, $state)
9450f19ffacSespie{
9460f19ffacSespie	$state->{known} //= {};
947e0cbfadbSespie	$self->fill_localbase($state,
948e0cbfadbSespie	    $state->destdir(OpenBSD::Paths->localbase));
949e0cbfadbSespie	my $root = $state->{destdir} || '/';
9500f19ffacSespie	$self->fill_root($state, $root);
951bd2f84f9Sespie	$self->fill_base_system($state);
9520f19ffacSespie
953556a8905Sespie	$state->progress->set_header("Checking file system");
954039cbdaaSespie	find(sub() {
955eef84043Sespie		$state->progress->working(1024);
95661d49fb8Sespie		if (-d $_) {
95761d49fb8Sespie			for my $i ('/dev', '/home', OpenBSD::Paths->pkgdb, '/var/log', '/var/backups', '/var/cron', '/var/run', '/tmp', '/var/tmp') {
95861d49fb8Sespie				if ($File::Find::name eq $state->destdir($i)) {
95961d49fb8Sespie					$File::Find::prune = 1;
96061d49fb8Sespie				}
96161d49fb8Sespie			}
96261d49fb8Sespie		}
963bd2f84f9Sespie		if (defined $state->{basesystem}{$File::Find::name}) {
964bd2f84f9Sespie			delete $state->{basesystem}{$File::Find::name};
965bd2f84f9Sespie			return;
966bd2f84f9Sespie		}
9672779f69aSespie		if (defined $state->{needed_libs}{$File::Find::name}) {
9682779f69aSespie			push(@{$state->{unreg_libs}}, $File::Find::name);
9692779f69aSespie			return;
9702779f69aSespie		}
971eef84043Sespie		if (-d $_) {
9720f19ffacSespie			if ($_ eq "lost+found") {
973087e0674Sespie				$state->say("fsck(8) info found: #1",
974087e0674Sespie				    $File::Find::name);
975087e0674Sespie				$File::Find::prune = 1;
976087e0674Sespie				return;
977087e0674Sespie			}
9780f19ffacSespie			# some directories we've got to ignore
9796af91da1Sespie			if (! -r -x _) {
9806af91da1Sespie				$File::Find::prune = 1;
9816af91da1Sespie				$state->errsay("can't enter #1",
9826af91da1Sespie				    $File::Find::name);
9836af91da1Sespie			}
984eef84043Sespie			return if defined $state->{known}{$File::Find::name};
985eb01027bSespie			if (-l $_) {
986eef84043Sespie				return if $state->{known}{$File::Find::dir}{$_};
987eef84043Sespie			}
988556a8905Sespie			push(@{$state->{unknown}{dir}}, $File::Find::name);
9890f19ffacSespie			$File::Find::prune = 1;
990eb01027bSespie		} else {
991eb01027bSespie			return if $state->{known}{$File::Find::dir}{$_};
992ebff90d8Sespie			if (m/^pkg\..{10}$/) {
993ebff90d8Sespie				push(@{$state->{tmps}}, $File::Find::name);
994ebff90d8Sespie			} else {
995ebff90d8Sespie				push(@{$state->{unknown}{file}},
996ebff90d8Sespie				    $File::Find::name);
997ebff90d8Sespie			}
998eb01027bSespie		}
9990f19ffacSespie	}, $root);
1000ebff90d8Sespie	if (defined $state->{tmps}) {
1001ebff90d8Sespie		$self->display_tmps($state);
1002ebff90d8Sespie	}
10032779f69aSespie	if (defined $state->{unreg_libs}) {
10042779f69aSespie		$self->display_unregs($state);
10052779f69aSespie	}
1006556a8905Sespie	if (defined $state->{unknown}) {
1007556a8905Sespie		if ($self->install_pkglocate($state)) {
1008bd2f84f9Sespie			$self->locate_unknown($state);
1009556a8905Sespie		} else {
1010bd2f84f9Sespie			$self->display_unknown($state);
1011556a8905Sespie		}
1012556a8905Sespie	}
1013eef84043Sespie}
1014eef84043Sespie
1015039cbdaaSespiesub run($self, $state)
1016eef84043Sespie{
10176e815952Sespie	my $list = [installed_packages()];
10186e815952Sespie
10196e815952Sespie	my $list2;
10206e815952Sespie	if (@ARGV != 0) {
10216e815952Sespie		$list2 = \@ARGV;
10226e815952Sespie	} else {
10236e815952Sespie		$list2 = $list;
10246e815952Sespie	}
10256e815952Sespie	$self->sanity_check($state, $list);
10266e815952Sespie	$self->dependencies_check($state, $list);
102710f87983Sespie	$state->log->dump;
10286e815952Sespie	$self->reverse_dependencies_check($state, $list);
102979cf49beSespie	$state->log->dump;
10308cd3e493Sespie	if ($state->{quick} < 2) {
10316e815952Sespie		$self->package_files_check($state, $list2);
1032eef84043Sespie		$state->log->dump;
10338cd3e493Sespie	}
10348cd3e493Sespie	if ($state->{filesystem}) {
103561d49fb8Sespie		$self->filesystem_check($state);
1036eb01027bSespie		$state->progress->next;
1037eef84043Sespie	}
10388cd3e493Sespie}
1039eef84043Sespie
1040039cbdaaSespiesub parse_and_run($self, $cmd)
1041eef84043Sespie{
10427e83eca3Sespie	my $state = OpenBSD::PkgCheck::State->new($cmd);
104383ad63f0Sespie	$state->handle_options;
10448d5333baSespie	lock_db(0, $state) unless $state->{subst}->value('nolock');
1045eef84043Sespie	$self->run($state);
1046138429bfSespie	return 0;
1047eef84043Sespie}
1048eef84043Sespie
1049eef84043Sespie1;
1050