1#! /usr/bin/perl 2 3# ex:ts=8 sw=4: 4# $OpenBSD: PkgCheck.pm,v 1.62 2016/08/26 18:19:21 espie Exp $ 5# 6# Copyright (c) 2003-2014 Marc Espie <espie@openbsd.org> 7# 8# Permission to use, copy, modify, and distribute this software for any 9# purpose with or without fee is hereby granted, provided that the above 10# copyright notice and this permission notice appear in all copies. 11# 12# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 20use strict; 21use warnings; 22 23use OpenBSD::AddCreateDelete; 24use OpenBSD::SharedLibs; 25 26package Installer::State; 27our @ISA = qw(OpenBSD::PkgAdd::State); 28sub new 29{ 30 my ($class, $cmd) = @_; 31 my $state = $class->SUPER::new($cmd); 32 $state->{localbase} = OpenBSD::Paths->localbase; 33 return $state; 34} 35 36package Installer; 37our @ISA = qw(OpenBSD::PkgAdd); 38 39sub new 40{ 41 my ($class, $mystate) = @_; 42 my $state = Installer::State->new("pkg_check"); 43 $state->{v} = $mystate->{v}; 44 $state->{subst} = $mystate->{subst}; 45 $state->{interactive} = $mystate->{interactive}; 46 $state->{destdir} = $mystate->{destdir}; 47 $state->progress->setup($state->opt('x'), $state->opt('m'), $state); 48 bless { state => $state}, $class; 49} 50 51sub install 52{ 53 my ($self, $pkg) = @_; 54 my $state = $self->{state}; 55 push(@{$state->{setlist}}, 56 $state->updateset->add_hints2($pkg)); 57 $self->framework($state); 58 return $state->{bad} != 0; 59} 60 61package OpenBSD::PackingElement; 62sub thorough_check 63{ 64 my ($self, $state) = @_; 65 $self->basic_check($state); 66} 67 68sub basic_check 69{ 70} 71 72sub find_dependencies 73{ 74} 75 76package OpenBSD::PackingElement::FileBase; 77use File::Basename; 78 79sub basic_check 80{ 81 my ($self, $state) = @_; 82 83 my $name = $state->destdir($self->fullname); 84 $state->{known}{dirname($name)}{basename($name)} = 1; 85 if ($self->{symlink}) { 86 if (!-l $name) { 87 if (!-e $name) { 88 $state->log("#1 should be a symlink but does not exist", $name); 89 } else { 90 $state->log("#1 is not a symlink", $name); 91 } 92 } else { 93 if (readlink($name) ne $self->{symlink}) { 94 $state->log("#1 should point to #2 but points to #3 instead", 95 $name, $self->{symlink}, readlink($name)); 96 } 97 } 98 return; 99 } 100 if (!-e $name) { 101 if (-l $name) { 102 $state->log("#1 points to non-existent #2", 103 $name, readlink($name)); 104 } else { 105 $state->log("#1 should exist", $name); 106 } 107 } 108 if (!-f _) { 109 $state->log("#1 is not a file", $name); 110 } 111 if ($self->{link}) { 112 my ($a, $b) = (stat _)[0, 1]; 113 if (!-f $state->destdir($self->{link})) { 114 $state->log("#1 should link to non-existent #2", 115 $name, $self->{link}); 116 } else { 117 my ($c, $d) = (stat _)[0, 1]; 118 if (defined $a && defined $c) { 119 if ($a != $c || $b != $d) { 120 $state->log("#1 doesn't link to #2", 121 $name, $self->{link}); 122 } 123 } 124 } 125 } 126} 127 128sub thorough_check 129{ 130 my ($self, $state) = @_; 131 my $name = $state->destdir($self->fullname); 132 $self->basic_check($state); 133 return if $self->{link} or $self->{symlink} or $self->{nochecksum}; 134 if (!-r $name) { 135 $state->log("can't read #1", $name); 136 return; 137 } 138 if (!defined $self->{d}) { 139 $state->log("no checksum for #1", $name); 140 return; 141 } 142 my $d = $self->compute_digest($name, ref($self->{d})); 143 if (!$d->equals($self->{d})) { 144 $state->log("checksum for #1 does not match", $name); 145 } 146} 147 148package OpenBSD::PackingElement::SpecialFile; 149sub basic_check 150{ 151 &OpenBSD::PackingElement::FileBase::basic_check; 152} 153 154sub thorough_check 155{ 156 &OpenBSD::PackingElement::FileBase::basic_check; 157} 158 159package OpenBSD::PackingElement::DirlikeObject; 160sub basic_check 161{ 162 my ($self, $state) = @_; 163 my $name = $state->destdir($self->fullname); 164 $state->{known}{$name} //= {}; 165 if (!-e $name) { 166 $state->log("#1 should exist", $name); 167 } 168 if (!-d _) { 169 $state->log("#1 is not a directory", $name); 170 } 171} 172 173package OpenBSD::PackingElement::Sample; 174use File::Basename; 175sub basic_check 176{ 177 my ($self, $state) = @_; 178 my $name = $state->destdir($self->fullname); 179 $state->{known}{dirname($name)}{basename($name)} = 1; 180} 181 182package OpenBSD::PackingElement::Sampledir; 183sub basic_check 184{ 185 my ($self, $state) = @_; 186 my $name = $state->destdir($self->fullname); 187 $state->{known}{$name} //= {}; 188} 189 190package OpenBSD::PackingElement::Mandir; 191sub basic_check 192{ 193 my ($self, $state) = @_; 194 $self->SUPER::basic_check($state); 195 my $name = $state->destdir($self->fullname); 196 for my $file (OpenBSD::Paths::man_cruft()) { 197 $state->{known}{$name}{$file} = 1; 198 } 199} 200 201package OpenBSD::PackingElement::Fontdir; 202sub basic_check 203{ 204 my ($self, $state) = @_; 205 $self->SUPER::basic_check($state); 206 my $name = $state->destdir($self->fullname); 207 for my $i (qw(fonts.alias fonts.scale fonts.dir)) { 208 $state->{known}{$name}{$i} = 1; 209 } 210} 211 212package OpenBSD::PackingElement::Infodir; 213sub basic_check 214{ 215 my ($self, $state) = @_; 216 $self->SUPER::basic_check($state); 217 my $name = $state->destdir($self->fullname); 218 $state->{known}{$name}{'dir'} = 1; 219} 220 221package OpenBSD::PackingElement::Dependency; 222sub find_dependencies 223{ 224 my ($self, $state, $l, $checker) = @_; 225 # several ways to failure 226 if (!$self->spec->is_valid) { 227 $state->log("invalid \@", $self->keyword, " ", 228 $self->stringize); 229 return; 230 } 231 my @deps = $self->spec->filter(@$l); 232 if (@deps == 0) { 233 $state->log("dependency #1 does not match any installed package", 234 $self->stringize); 235 return; 236 } 237 my $okay = 0; 238 for my $i (@deps) { 239 if ($checker->find($i)) { 240 $okay = 1; 241 } 242 } 243 if (!$okay) { 244 $checker->not_found($deps[0]); 245 } 246} 247 248package OpenBSD::PackingElement::Wantlib; 249sub find_dependencies 250{ 251 my ($self, $state, $l, $checker) = @_; 252 my $r = OpenBSD::SharedLibs::lookup_libspec($state->{localbase}, 253 $self->spec); 254 if (defined $r && @$r != 0) { 255 my $okay = 0; 256 for my $lib (@$r) { 257 my $i = $lib->origin; 258 if ($i eq 'system') { 259 $okay = 1; 260 $state->{needed_libs}{$lib->to_string} = 1; 261 next; 262 } 263 if ($checker->find($i)) { 264 $okay = 1; 265 } 266 } 267 if (!$okay) { 268 $checker->not_found($r->[0]->origin); 269 } 270 } else { 271 $state->log("#1 not found", $self->stringize); 272 } 273} 274 275package OpenBSD::PkgCheck::State; 276our @ISA = qw(OpenBSD::AddCreateDelete::State); 277 278use File::Spec; 279use OpenBSD::Log; 280use File::Basename; 281 282sub init 283{ 284 my $self = shift; 285 $self->{l} = OpenBSD::Log->new($self); 286 $self->SUPER::init; 287} 288 289sub log 290{ 291 my $self = shift; 292 if (@_ == 0) { 293 return $self->{l}; 294 } else { 295 $self->{l}->say(@_); 296 } 297} 298 299sub safe 300{ 301 my ($self, $string) = @_; 302 $string =~ s/[^\w\d\s\+\-\.\>\<\=\/\;\:\,\(\)\[\]]/?/g; 303 return $string; 304} 305 306sub handle_options 307{ 308 my $self = shift; 309 $self->{no_exports} = 1; 310 311 $self->add_interactive_options; 312 $self->SUPER::handle_options('fFB:q', 313 '[-FfIimnqvx] [-B pkg-destdir] [-D value]'); 314 $self->{force} = $self->opt('f'); 315 $self->{quick} = $self->opt('q') // 0; 316 $self->{filesystem} = $self->opt('F'); 317 if (defined $self->opt('B')) { 318 $self->{destdir} = $self->opt('B'); 319 } 320 if (defined $self->{destdir}) { 321 $self->{destdir} .= '/'; 322 } else { 323 $self->{destdir} = ''; 324 } 325} 326 327sub build_tag 328{ 329} 330 331sub destdir 332{ 333 my ($self, $path) = @_; 334 return File::Spec->canonpath($self->{destdir}.$path); 335} 336 337sub process_entry 338{ 339 my ($self, $entry) = @_; 340 my $name = $self->destdir($entry); 341 $self->{known}{dirname($name)}{basename($name)} = 1; 342} 343 344package OpenBSD::DependencyCheck; 345 346sub new 347{ 348 my ($class, $state, $name, $req) = @_; 349 my $o = bless { 350 not_yet => {}, 351 possible => {}, 352 others => {}, 353 name => $name, 354 req => $req 355 }, $class; 356 for my $pkg ($req->list) { 357 $o->{not_yet}{$pkg} = 1; 358 if ($state->{exists}{$pkg}) { 359 $o->{possible}{$pkg} = 1; 360 } else { 361 $state->errsay("#1: bogus #2", 362 $name, $o->string($state->safe($pkg))); 363 } 364 } 365 return $o; 366} 367 368sub find 369{ 370 my ($self, $name) = @_; 371 if ($self->{possible}{$name}) { 372 delete $self->{not_yet}{$name}; 373 return 1; 374 } else { 375 return 0; 376 } 377} 378 379sub not_found 380{ 381 my ($self, $name) = @_; 382 $self->{others}{$name} = 1; 383} 384 385sub ask_delete_deps 386{ 387 my ($self, $state, $l) = @_; 388 if ($state->{force}) { 389 $self->{req}->delete(@$l); 390 } elsif ($state->confirm("Remove missing ". 391 $state->safe($self->string(@$l)))) { 392 $self->{req}->delete(@$l); 393 } 394} 395 396sub ask_add_deps 397{ 398 my ($self, $state, $l) = @_; 399 if ($state->{force}) { 400 $self->{req}->add(@$l); 401 } elsif ($state->confirm("Add missing ". 402 $self->string(@$l))) { 403 $self->{req}->add(@$l); 404 } 405} 406 407sub adjust 408{ 409 my ($self, $state) = @_; 410 if (keys %{$self->{not_yet}} > 0) { 411 my @todo = sort keys %{$self->{not_yet}}; 412 unless ($state->{subst}->value("weed_libs")) { 413 @todo = grep {!/^\.libs/} @todo; 414 } 415 if (@todo != 0) { 416 $state->errsay("#1 has too many #2", 417 $self->{name}, $state->safe($self->string(@todo))); 418 $self->ask_delete_deps($state, \@todo); 419 } 420 } 421 if (keys %{$self->{others}} > 0) { 422 my @todo = sort keys %{$self->{others}}; 423 $state->errsay("#1 is missing #2", 424 $self->{name}, $self->string(@todo)); 425 if ($self->{name} =~ m/^partial/) { 426 $state->errsay("not a problem, since this is a partial- package"); 427 } else { 428 $self->ask_add_deps($state, \@todo); 429 } 430 } 431} 432 433package OpenBSD::DirectDependencyCheck; 434our @ISA = qw(OpenBSD::DependencyCheck); 435use OpenBSD::RequiredBy; 436sub string 437{ 438 my $self = shift; 439 return "dependencies: ". join(' ', @_); 440} 441 442sub new 443{ 444 my ($class, $state, $name) = @_; 445 return $class->SUPER::new($state, $name, 446 OpenBSD::Requiring->new($name)); 447} 448 449package OpenBSD::ReverseDependencyCheck; 450our @ISA = qw(OpenBSD::DependencyCheck); 451use OpenBSD::RequiredBy; 452sub string 453{ 454 my $self = shift; 455 return "reverse dependencies: ". join(' ', @_); 456} 457 458sub new 459{ 460 my ($class, $state, $name) = @_; 461 return $class->SUPER::new($state, $name, 462 OpenBSD::RequiredBy->new($name)); 463} 464 465package OpenBSD::Pkglocate; 466sub new 467{ 468 my ($class, $state) = @_; 469 bless {state => $state, result => {unknown => []}, 470 params => []}, $class; 471} 472 473sub add_param 474{ 475 my ($self, @p) = @_; 476 push(@{$self->{params}}, @p); 477 while (@{$self->{params}} > 200) { 478 $self->run_command; 479 } 480} 481 482sub run_command 483{ 484 my $self = shift; 485 486 if (@{$self->{params}} == 0) { 487 return; 488 } 489 my %h = map {($_, 1)} @{$self->{params}}; 490 open(my $cmd, '-|', 'pkg_locate', map {"*:$_"} @{$self->{params}}); 491 while (<$cmd>) { 492 chomp; 493 my ($pkgname, $pkgpath, $path) = split(':', $_, 3); 494 495 # pkglocate will return false positives, so trim them 496 if ($h{$path}) { 497 push(@{$self->{result}{"$pkgname:$pkgpath"} }, $path); 498 delete $h{$path}; 499 } 500 } 501 close($cmd); 502 for my $k (keys %h) { 503 push(@{$self->{result}{unknown}}, $k); 504 } 505 506 $self->{params} = []; 507} 508 509sub result 510{ 511 my $self = shift; 512 while (@{$self->{params}} > 0) { 513 $self->run_command; 514 } 515 my $state = $self->{state}; 516 my $r = $self->{result}; 517 my $u = $r->{unknown}; 518 delete $r->{unknown}; 519 520 $state->say("Not found:"); 521 for my $e (sort @$u) { 522 $state->say("\t#1", $e); 523 } 524 525 for my $k (sort keys %{$r}) { 526 $state->say("In #1:", $k); 527 for my $e (sort @{$r->{$k}}) { 528 $state->say("\t#1", $e); 529 } 530 } 531} 532 533package OpenBSD::PkgCheck; 534our @ISA = qw(OpenBSD::AddCreateDelete); 535 536use OpenBSD::PackageInfo; 537use OpenBSD::PackingList; 538use File::Find; 539use OpenBSD::Paths; 540use OpenBSD::Mtree; 541 542sub fill_base_system 543{ 544 my ($self, $state) = @_; 545 open(my $cmd, '-|', 'locate', 546 '-d', OpenBSD::Paths->srclocatedb, 547 '-d', OpenBSD::Paths->xlocatedb, ':'); 548 while (<$cmd>) { 549 chomp; 550 my ($set, $path) = split(':', $_, 2); 551 $state->{basesystem}{$path} = 1; 552 } 553 close($cmd); 554} 555 556sub remove 557{ 558 my ($self, $state, $name) = @_; 559 $state->{removed}{$name} = 1; 560 my $dir = installed_info($name); 561 for my $i (@OpenBSD::PackageInfo::info) { 562 if (-e $dir.$i) { 563 if ($state->verbose) { 564 $state->say("unlink(#1)", $dir.$i); 565 } 566 unless ($state->{not}) { 567 unlink($dir.$i) or 568 $state->errsay("#1: Couldn't delete #2: #3", 569 $name, $dir.$i, $!); 570 } 571 } 572 } 573 if (-f $dir) { 574 if ($state->verbose) { 575 $state->say("unlink(#1)", $dir); 576 } 577 unless ($state->{not}) { 578 unlink($dir) or 579 $state->errsay("#1: Couldn't delete #2: #3", 580 $name, $dir, $!); 581 } 582 } elsif (-d $dir) { 583 if ($state->verbose) { 584 $state->say("rmdir(#1)", $dir); 585 } 586 unless ($state->{not}) { 587 rmdir($dir) or 588 $state->errsay("#1: Couldn't delete #2: #3", 589 $name, $dir, $!); 590 } 591 } 592} 593 594sub may_remove 595{ 596 my ($self, $state, $name) = @_; 597 if ($state->{force}) { 598 $self->remove($state, $name); 599 } elsif ($state->confirm("Remove wrong package $name")) { 600 $self->remove($state, $name); 601 } 602 $state->{bogus}{$name} = 1; 603} 604 605sub for_all_packages 606{ 607 my ($self, $state, $l, $msg, $code) = @_; 608 609 $state->progress->for_list($msg, $l, 610 sub { 611 return if $state->{removed}{$_[0]}; 612 if ($state->{bogus}{$_[0]}) { 613 $state->errsay("skipping #1", $_[0]); 614 return; 615 } 616 &$code; 617 }); 618} 619 620sub sanity_check 621{ 622 my ($self, $state, $l) = @_; 623 $self->for_all_packages($state, $l, "Packing-list sanity", sub { 624 my $name = shift; 625 my $info = installed_info($name); 626 if (-f $info) { 627 $state->errsay("#1: #2 should be a directory", 628 $state->safe($name), $state->safe($info)); 629 if ($info =~ m/\.core$/) { 630 $state->errsay("looks like a core dump, ". 631 "removing"); 632 $self->remove($state, $name); 633 } else { 634 $self->may_remove($state, $name); 635 } 636 return; 637 } 638 my $contents = $info.OpenBSD::PackageInfo::CONTENTS; 639 unless (-f $contents) { 640 $state->errsay("#1: missing #2", 641 $state->safe($name), $state->safe($contents)); 642 $self->may_remove($state, $name); 643 return; 644 } 645 my $plist; 646 eval { 647 $plist = OpenBSD::PackingList->fromfile($contents); 648 }; 649 if ($@ || !defined $plist) { 650 $state->errsay("#1: bad packing-list", $state->safe($name)); 651 $self->may_remove($state, $name); 652 return; 653 } 654 if (!defined $plist->pkgname) { 655 $state->errsay("#1: no pkgname in plist", 656 $state->safe($name)); 657 $self->may_remove($state, $name); 658 return; 659 } 660 if ($plist->pkgname ne $name) { 661 $state->errsay("#1: pkgname does not match", 662 $state->safe($name)); 663 $self->may_remove($state, $name); 664 } 665 $plist->mark_available_lib($plist->pkgname, $state); 666 $state->{exists}{$plist->pkgname} = 1; 667 }); 668} 669 670sub dependencies_check 671{ 672 my ($self, $state, $l) = @_; 673 OpenBSD::SharedLibs::add_libs_from_system($state->{destdir}, $state); 674 $self->for_all_packages($state, $l, "Direct dependencies", sub { 675 my $name = shift; 676 $state->log->set_context($name); 677 my $plist = OpenBSD::PackingList->from_installation($name, 678 \&OpenBSD::PackingList::DependOnly); 679 my $checker = OpenBSD::DirectDependencyCheck->new($state, 680 $name); 681 $state->{localbase} = $plist->localbase; 682 $plist->find_dependencies($state, $l, $checker); 683 $checker->adjust($state); 684 for my $dep ($checker->{req}->list) { 685 push(@{$state->{reverse}{$dep}}, $name); 686 } 687 }); 688} 689 690sub reverse_dependencies_check 691{ 692 my ($self, $state, $l) = @_; 693 $self->for_all_packages($state, $l, "Reverse dependencies", sub { 694 my $name = shift; 695 my $checker = OpenBSD::ReverseDependencyCheck->new($state, 696 $name); 697 for my $i (@{$state->{reverse}{$name}}) { 698 $checker->find($i) or $checker->not_found($i); 699 } 700 $checker->adjust($state); 701 }); 702} 703 704sub package_files_check 705{ 706 my ($self, $state, $l) = @_; 707 $self->for_all_packages($state, $l, "Files from packages", sub { 708 my $name = shift; 709 my $plist = OpenBSD::PackingList->from_installation($name); 710 $state->log->set_context($name); 711 if ($state->{quick}) { 712 $plist->basic_check($state); 713 } else { 714 $plist->thorough_check($state); 715 } 716 $plist->mark_available_lib($plist->pkgname, $state); 717 }); 718} 719 720sub install_pkglocate 721{ 722 my ($self, $state) = @_; 723 724 my $spec = 'pkglocatedb->=1.1'; 725 726 my @l = installed_stems()->find('pkglocatedb'); 727 require OpenBSD::PkgSpec; 728 if (OpenBSD::PkgSpec->new($spec)->match_ref(\@l)) { 729 return 1; 730 } 731 unless ($state->confirm("Unknown file system entries.\n". 732 "Do you want to install $spec to look them up")) { 733 return 0; 734 } 735 736 require OpenBSD::PkgAdd; 737 738 $state->{installer} //= Installer->new($state); 739 if ($state->{installer}->install('pkglocatedb--')) { 740 return 1; 741 } else { 742 $state->errsay("Couldn't install #1", $spec); 743 return 0; 744 } 745} 746 747# non fancy display of unknown objects 748sub display_unknown 749{ 750 my ($self, $state) = @_; 751 if (defined $state->{unknown}{file}) { 752 $state->say("Unknown files:"); 753 for my $e (sort @{$state->{unknown}{file}}) { 754 $state->say("\t#1", $e); 755 } 756 } 757 if (defined $state->{unknown}{dir}) { 758 $state->say("Unknown directories:"); 759 for my $e (sort {$b cmp $a } @{$state->{unknown}{dir}}) { 760 $state->say("\t#1", $e); 761 } 762 } 763} 764 765sub display_tmps 766{ 767 my ($self, $state) = @_; 768 $state->say("Unregistered temporary files:"); 769 for my $e (sort @{$state->{tmps}}) { 770 $state->say("\t#1", $e); 771 } 772 if ($state->{force}) { 773 unlink(@{$state->{tmps}}); 774 } elsif ($state->confirm("Remove")) { 775 unlink(@{$state->{tmps}}); 776 } 777} 778 779sub display_unregs 780{ 781 my ($self, $state) = @_; 782 $state->say("System libs NOT in locate dbs:"); 783 for my $e (sort @{$state->{unreg_libs}}) { 784 $state->say("\t#1", $e); 785 } 786} 787 788sub locate_unknown 789{ 790 my ($self, $state) = @_; 791 my $locator = OpenBSD::Pkglocate->new($state); 792 if (defined $state->{unknown}{file}) { 793 $state->progress->for_list("Locating unknown files", 794 $state->{unknown}{file}, 795 sub { 796 $locator->add_param($_[0]); 797 }); 798 } 799 if (defined $state->{unknown}{dir}) { 800 $state->progress->for_list("Locating unknown directories", 801 $state->{unknown}{dir}, 802 sub { 803 $locator->add_param($_[0]); 804 }); 805 } 806 $locator->result($state); 807} 808 809sub fill_localbase 810{ 811 my ($self, $state, $base) = @_; 812 for my $file (OpenBSD::Paths::man_cruft()) { 813 $state->{known}{$base."/man"}{$file} = 1; 814 } 815 $state->{known}{$base."/info"}{'dir'} = 1; 816 $state->{known}{$base."/lib/X11"}{'app-defaults'} = 1; 817 $state->{known}{$base."/libdata"} = {}; 818 $state->{known}{$base."/libdata/perl5"} = {}; 819} 820 821sub fill_root 822{ 823 my ($self, $state, $root) = @_; 824 OpenBSD::Mtree::parse($state->{known}, $root, 825 '/etc/mtree/4.4BSD.dist', 1); 826 OpenBSD::Mtree::parse($state->{known}, $root, 827 '/etc/mtree/BSD.x11.dist', 1); 828} 829 830sub filesystem_check 831{ 832 my ($self, $state) = @_; 833 $state->{known} //= {}; 834 $self->fill_localbase($state, 835 $state->destdir(OpenBSD::Paths->localbase)); 836 my $root = $state->{destdir} || '/'; 837 $self->fill_root($state, $root); 838 $self->fill_base_system($state); 839 840 $state->progress->set_header("Checking file system"); 841 find(sub { 842 $state->progress->working(1024); 843 if (-d $_) { 844 for my $i ('/dev', '/home', OpenBSD::Paths->pkgdb, '/var/log', '/var/backups', '/var/cron', '/var/run', '/tmp', '/var/tmp') { 845 if ($File::Find::name eq $state->destdir($i)) { 846 $File::Find::prune = 1; 847 } 848 } 849 } 850 if (defined $state->{basesystem}{$File::Find::name}) { 851 delete $state->{basesystem}{$File::Find::name}; 852 return; 853 } 854 if (defined $state->{needed_libs}{$File::Find::name}) { 855 push(@{$state->{unreg_libs}}, $File::Find::name); 856 return; 857 } 858 if (-d $_) { 859 if ($_ eq "lost+found") { 860 $state->say("fsck(8) info found: #1", 861 $File::Find::name); 862 $File::Find::prune = 1; 863 return; 864 } 865 # some directories we've got to ignore 866 if (! -r -x _) { 867 $File::Find::prune = 1; 868 $state->errsay("can't enter #1", 869 $File::Find::name); 870 } 871 return if defined $state->{known}{$File::Find::name}; 872 if (-l $_) { 873 return if $state->{known}{$File::Find::dir}{$_}; 874 } 875 push(@{$state->{unknown}{dir}}, $File::Find::name); 876 $File::Find::prune = 1; 877 } else { 878 return if $state->{known}{$File::Find::dir}{$_}; 879 if (m/^pkg\..{10}$/) { 880 push(@{$state->{tmps}}, $File::Find::name); 881 } else { 882 push(@{$state->{unknown}{file}}, 883 $File::Find::name); 884 } 885 } 886 }, $root); 887 if (defined $state->{tmps}) { 888 $self->display_tmps($state); 889 } 890 if (defined $state->{unreg_libs}) { 891 $self->display_unregs($state); 892 } 893 if (defined $state->{unknown}) { 894 if ($self->install_pkglocate($state)) { 895 $self->locate_unknown($state); 896 } else { 897 $self->display_unknown($state); 898 } 899 } 900} 901 902sub run 903{ 904 my ($self, $state) = @_; 905 906 my @list = installed_packages(); 907 $self->sanity_check($state, \@list); 908 $self->dependencies_check($state, \@list); 909 $state->log->dump; 910 $self->reverse_dependencies_check($state, \@list); 911 $state->log->dump; 912 if ($state->{quick} < 2) { 913 $self->package_files_check($state, \@list); 914 $state->log->dump; 915 } 916 if ($state->{filesystem}) { 917 $self->filesystem_check($state); 918 $state->progress->next; 919 } 920} 921 922sub parse_and_run 923{ 924 my ($self, $cmd) = @_; 925 926 my $state = OpenBSD::PkgCheck::State->new($cmd); 927 $state->handle_options; 928 if (@ARGV != 0) { 929 $state->usage; 930 } 931 lock_db(0, $state) unless $state->{subst}->value('nolock'); 932 $self->run($state); 933 return 0; 934} 935 9361; 937