diff options
author | Marc Espie <espie@cvs.openbsd.org> | 2010-06-05 12:30:37 +0000 |
---|---|---|
committer | Marc Espie <espie@cvs.openbsd.org> | 2010-06-05 12:30:37 +0000 |
commit | 1b3f92afa619cfd154471fde302432bf183ed20d (patch) | |
tree | 9dbc87a2efb5ea3ded85a0baa9adedf066d88d28 /usr.sbin | |
parent | 4d97f7c4940c5939d1a06c83c874d47551762adf (diff) |
new command pkg_fsck, very incomplete for now. Runs only very basic checks.
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/pkg_add/Makefile | 9 | ||||
-rw-r--r-- | usr.sbin/pkg_add/OpenBSD/PkgFsck.pm | 318 | ||||
-rw-r--r-- | usr.sbin/pkg_add/pkg | 5 | ||||
-rw-r--r-- | usr.sbin/pkg_add/pkg.1 | 2 | ||||
-rw-r--r-- | usr.sbin/pkg_add/pkg_fsck.8 | 90 |
5 files changed, 419 insertions, 5 deletions
diff --git a/usr.sbin/pkg_add/Makefile b/usr.sbin/pkg_add/Makefile index 06e31691b53..0714ca11abe 100644 --- a/usr.sbin/pkg_add/Makefile +++ b/usr.sbin/pkg_add/Makefile @@ -1,11 +1,12 @@ -# $OpenBSD: Makefile,v 1.62 2010/06/04 13:19:39 espie Exp $ +# $OpenBSD: Makefile,v 1.63 2010/06/05 12:30:36 espie Exp $ .include <bsd.own.mk> MAN1=pkg_add.1 pkg_info.1 pkg_create.1 pkg_delete.1 pkg_merge.1 \ pkg.1 pkg_mklocatedb.1 MAN5=package.5 -MAN=${MAN1} ${MAN5} +MAN8=pkg_fsck.8 +MAN=${MAN1} ${MAN5} ${MAN8} NOPROG= POD2MAN=/usr/bin/pod2man @@ -45,6 +46,7 @@ PACKAGES= \ OpenBSD/PkgConfig.pm \ OpenBSD/PkgCreate.pm \ OpenBSD/PkgDelete.pm \ + OpenBSD/PkgFsck.pm \ OpenBSD/PkgInfo.pm \ OpenBSD/PkgSpec.pm \ OpenBSD/ProgressMeter/Term.pm \ @@ -77,6 +79,7 @@ SCRIPTS_LNK = \ pkg pkg_add \ pkg pkg_create \ pkg pkg_delete \ + pkg pkg_fsck \ pkg pkg_info LIBBASE=/usr/libdata/perl5 @@ -117,9 +120,11 @@ $p.3p: pod/$p.pod .ifndef NOMAN MANALL+=${MAN1:S/.1$/.cat1/} MANALL+=${MAN5:S/.5$/.cat5/} +MANALL+=${MAN8:S/.8$/.cat8/} . ifdef MANPS PSALL+= ${MAN1:S/.1$/.ps1/} PSALL+= ${MAN5:S/.5$/.ps5/} +PSALL+= ${MAN8:S/.8$/.ps8/} . endif .endif diff --git a/usr.sbin/pkg_add/OpenBSD/PkgFsck.pm b/usr.sbin/pkg_add/OpenBSD/PkgFsck.pm new file mode 100644 index 00000000000..93d8f0eca89 --- /dev/null +++ b/usr.sbin/pkg_add/OpenBSD/PkgFsck.pm @@ -0,0 +1,318 @@ +#! /usr/bin/perl + +# ex:ts=8 sw=4: +# $OpenBSD: PkgFsck.pm,v 1.1 2010/06/05 12:30:36 espie Exp $ +# +# Copyright (c) 2003-2010 Marc Espie <espie@openbsd.org> +# +# 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::AddCreateDelete; + +package OpenBSD::PackingElement; +sub thorough_check +{ + my ($self, $state) = @_; + $self->basic_check($state); +} + +sub basic_check +{ +} + +package OpenBSD::PackingElement::FileBase; +use File::Basename; + +sub basic_check +{ + my ($self, $state) = @_; + + my $name = $self->fullname; + $state->{known}{dirname($name)}{basename($name)} = 1; + if (!-e $name) { + $state->log("$name should exist\n"); + } + if ($self->{symlink}) { + if (!-l $name) { + $state->log("$name is not a symlink\n"); + } + return; + } + if (!-f _) { + $state->log("$name is not a file\n"); + } +} + +sub thorough_check +{ + my ($self, $state) = @_; + $self->basic_check($state); + return if $self->{link} or $self->{symlink} or $self->{nochecksum}; + if (!-r $self->fullname) { + $state->log("can't read ", $self->fullname, "\n"); + return; + } + my $d = $self->compute_digest($self->fullname); + if (!$d->equals($self->{d})) { + $state->log("checksum for ", $self->fullname, " does not match", "\n"); + } +} + +package OpenBSD::PackingElement::SpecialFile; +sub basic_check +{ + &OpenBSD::PackingElement::FileBase::basic_check; +} + +sub thorough_check +{ + &OpenBSD::PackingElement::FileBase::basic_check; +} + +package OpenBSD::PackingElement::DirlikeObject; +sub basic_check +{ + my ($self, $state) = @_; + my $name = $self->fullname; + $state->{known}{$name} //= {}; + if (!-e $name) { + $state->log("$name should exist\n"); + } + if (!-d _) { + $state->log("$name is not a directory\n"); + } +} + +package OpenBSD::PackingElement::Mandir; +sub basic_check +{ + my ($self, $state) = @_; + $self->SUPER::basic_check($state); + $state->{known}{$self->fullname}{'whatis.db'} = 1; +} + +package OpenBSD::PackingElement::Fontdir; +sub basic_check +{ + my ($self, $state) = @_; + $self->SUPER::basic_check($state); + for my $i (qw(fonts.alias fonts.scale fonts.dir)) { + $state->{known}{$self->fullname}{$i} = 1; + } +} + +package OpenBSD::PackingElement::Infodir; +sub basic_check +{ + my ($self, $state) = @_; + $self->SUPER::basic_check($state); + $state->{known}{$self->fullname}{'dir'} = 1; +} + +package OpenBSD::Log; +use OpenBSD::Error; +our @ISA = qw(OpenBSD::Error); + +sub set_context +{ + &OpenBSD::Error::set_pkgname; +} + +sub dump +{ + &OpenBSD::Error::delayed_output; +} + +package OpenBSD::PkgFsck::State; +our @ISA = qw(OpenBSD::AddCreateDelete::State); + +sub init +{ + my $self = shift; + $self->{l} = OpenBSD::Log->new; + $self->SUPER::init; +} + +sub log +{ + my $self = shift; + if (@_ == 0) { + return $self->{l}; + } else { + $self->{l}->print(@_); + } +} + +package OpenBSD::PkgFsck; +our @ISA = qw(OpenBSD::AddCreateDelete); + +use OpenBSD::PackageInfo; +use OpenBSD::PackingList; +use File::Find; +use OpenBSD::Paths; +use OpenBSD::Mtree; + +sub remove +{ + my ($self, $state, $name) = @_; + $state->{removed}{$name} = 1; + my $dir = installed_info($name); + for my $i (@OpenBSD::PackageInfo::info) { + if (-e $dir.$i) { + if ($state->verbose) { + $state->say("unlink($dir.$i)"); + } + unless ($state->{not}) { + unlink($dir.$i) or + $state->errsay("$name: Couldn't delete $dir.$i: $!"); + } + } + } + if (-f $dir) { + if ($state->verbose) { + $state->say("unlink($dir)"); + } + unless ($state->{not}) { + unlink($dir) or + $state->errsay("$name: Couldn't delete $dir: $!"); + } + } elsif (-d $dir) { + if ($state->verbose) { + $state->say("rmdir($dir)"); + } + unless ($state->{not}) { + rmdir($dir) or + $state->errsay("$name: Couldn't delete $dir: $!"); + } + } +} + +sub may_remove +{ + my ($self, $state, $name) = @_; + if ($state->{force}) { + $self->remove($state, $name); + } elsif ($state->{interactive}) { + require OpenBSD::Interactive; + if (OpenBSD::Interactive("Remove wrong package $name ?")) { + $self->remove($state, $name); + } + } +} + +sub sanity_check +{ + my ($self, $state, $l) = @_; + $state->progress->set_header("Packing-list sanity"); + my $i = 0; + for my $name (@$l) { + my $info = installed_info($name); + $state->progress->show(++$i, scalar @$l); + if (-f $info) { + $state->errsay("$name: $info should be a directory"); + if ($info =~ m/\.core$/) { + $state->errsay("looks like a core dump, ", + "removing"); + $self->remove($state, $name); + } else { + $self->may_remove($state, $name); + } + next; + } + my $contents = $info.OpenBSD::PackageInfo::CONTENTS; + unless (-f $contents) { + $state->errsay("$name: missing $contents"); + $self->may_remove($state, $name); + next; + } + my $plist; + eval { + $plist = OpenBSD::PackingList->fromfile($contents); + }; + if ($@) { + $state->errsay("$name: bad plist"); + $self->may_remove($state, $name); + next; + } + if ($plist->pkgname ne $name) { + $state->errsay("$name: pkgname does not match"); + $self->may_remove($state, $name); + } + } +} + +sub package_files_check +{ + my ($self, $state, $l) = @_; + $state->progress->set_header("Files from packages"); + my $i = 0; + for my $name (@$l) { + next if $state->{removed}{$name}; + $state->progress->show(++$i, scalar @$l); + my $plist = OpenBSD::PackingList->from_installation($name); + $state->log->set_context($name); + if ($state->{quick}) { + $plist->basic_check($state); + } else { + $plist->thorough_check($state); + } + } +} + +sub localbase_check +{ + my ($self, $state) = @_; + $state->{known} //= {}; + # XXX + OpenBSD::Mtree::parse($state->{known}, OpenBSD::Paths->localbase, + "/etc/mtree/BSD.local.dist", 1); + $state->progress->set_header("Other files"); + find(sub { + $state->progress->working(1024); + if (-d $_) { + return if defined $state->{known}{$File::Find::name}; + } else { + return if $state->{known}{$File::Find::dir}{$_}; + } + $state->say("Unknown object $File::Find::name"); + }, OpenBSD::Paths->localbase); +} + +sub run +{ + my ($self, $state) = @_; + + my @list = installed_packages(1); + $self->sanity_check($state, \@list); + $self->package_files_check($state, \@list); + $self->localbase_check($state); +} + +sub parse_and_run +{ + my $self = shift; + + my $state = OpenBSD::PkgFsck::State->new; + $self->handle_options('fiq', $state, + 'pkg_fsck [-fimnqvx] [-D value]'); + $state->{interactive} = $state->opt('i'); + $state->{force} = $state->opt('f'); + $state->{quick} = $state->opt('q'); + $self->run($state); + $state->log->dump; +} + +1; diff --git a/usr.sbin/pkg_add/pkg b/usr.sbin/pkg_add/pkg index 1d83e9cac87..16ea03fd0cd 100644 --- a/usr.sbin/pkg_add/pkg +++ b/usr.sbin/pkg_add/pkg @@ -1,6 +1,6 @@ #! /usr/bin/perl # ex:ts=8 sw=4: -# $OpenBSD: pkg,v 1.13 2010/06/04 13:19:39 espie Exp $ +# $OpenBSD: pkg,v 1.14 2010/06/05 12:30:36 espie Exp $ # # Copyright (c) 2010 Marc Espie <espie@openbsd.org> # @@ -28,8 +28,9 @@ sub run die $@; } $module->parse_and_run; + exit(0); } -my @l = qw(add create delete info); +my @l = qw(add create delete fsck info); for my $i (@l) { if ($0 =~ m/\/?pkg_$i$/) { diff --git a/usr.sbin/pkg_add/pkg.1 b/usr.sbin/pkg_add/pkg.1 index f603368d4e4..d3ce20f8127 100644 --- a/usr.sbin/pkg_add/pkg.1 +++ b/usr.sbin/pkg_add/pkg.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: pkg.1,v 1.5 2010/06/05 07:11:43 espie Exp $ +.\" $OpenBSD: pkg.1,v 1.6 2010/06/05 12:30:36 espie Exp $ .\" .\" Copyright (c) 2010 Marc Espie <espie@openbsd.org> .\" diff --git a/usr.sbin/pkg_add/pkg_fsck.8 b/usr.sbin/pkg_add/pkg_fsck.8 new file mode 100644 index 00000000000..91660c214f9 --- /dev/null +++ b/usr.sbin/pkg_add/pkg_fsck.8 @@ -0,0 +1,90 @@ +.\" $OpenBSD: pkg_fsck.8,v 1.1 2010/06/05 12:30:36 espie Exp $ +.\" +.\" Copyright (c) 2010 Marc Espie <espie@openbsd.org> +.\" +.\" 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. +.\" +.Dd $Mdocdate: June 5 2010 $ +.Dt PKG_FSCK 1 +.Os +.Sh NAME +.Nm pkg_fsck +.Nd check consistency of installed packages +.Sh SYNOPSIS +.Nm pkg_fsck +.Bk -words +.Op Fl fimnqvx +.Oo Fl D Ar name +.Ns Oo Ns = Ns Ar value +.Oc +.Oc +.Ek +.Sh DESCRIPTION +.Nm +verifies as much information as it can about installed packages. +.Pp +.Nm +is not needed under normal circumstances, but it can be used to recover after +a catastrophic system failure in a middle of +.Xr pkg_add 1 , +.Xr pkg_delete 1 . +.Pp +.Nm +performs the following checks: +.Bl -tag -width small +.It Packing-list sanity +Checks that +.Pa /var/db/pkg +only contains directories, that each directory holds a packing-list, +and that said packing-list is an actual packing-list that matches the directory. +.It Files from packages +Checks that each file or directory in those packing-lists actually exist, +and that their checksum matches what's recorded in the packing-list. +.El +.Pp +Options are as follows: +.Bl -tag -width flagq +.It Xo +.Fl D +.Ar name Ns Op = Ns Ar value +.Xc +for consistency with other pkg commands. +No relevant defines so far. +.It Fl f +Force the removal of bogus package information. +.It Fl i +Ask user whether to irrevocably remove bogus package information. +.It Fl m +Causes +.Nm +to always display the progress meter in cases it would not do so by default. +.It Fl n +Don't actually modify packages, just perform checks. +.It Fl q +Don't verify checksums for files, just check for their existence. +.It Fl v +Turn on verbose output. +Several +.Fl v +may turn on more verbose output. +.It Fl x +Disable progress meter. +.El +.Sh SEE ALSO +.Xr fsck 8 +.Sh BUGS +Work in progress. +More checks to be added. +Use with caution. +.Sh AUTHORS +This program was written by Marc Espie. |