diff options
-rw-r--r-- | usr.sbin/pkg_add/OpenBSD/AddDelete.pm | 50 | ||||
-rw-r--r-- | usr.sbin/pkg_add/OpenBSD/Vstat.pm | 319 | ||||
-rw-r--r-- | usr.sbin/pkg_add/pod/OpenBSD::Vstat.pod | 42 |
3 files changed, 210 insertions, 201 deletions
diff --git a/usr.sbin/pkg_add/OpenBSD/AddDelete.pm b/usr.sbin/pkg_add/OpenBSD/AddDelete.pm index ab7ec61c0c8..c4614db449e 100644 --- a/usr.sbin/pkg_add/OpenBSD/AddDelete.pm +++ b/usr.sbin/pkg_add/OpenBSD/AddDelete.pm @@ -1,5 +1,5 @@ # ex:ts=8 sw=4: -# $OpenBSD: AddDelete.pm,v 1.13 2009/12/28 14:46:48 espie Exp $ +# $OpenBSD: AddDelete.pm,v 1.14 2010/01/02 14:13:02 espie Exp $ # # Copyright (c) 2007-2009 Marc Espie <espie@openbsd.org> # @@ -47,7 +47,6 @@ sub handle_options $opt_n = 1; } $state->{not} = $opt_n; - $state->vstat->{not} = $opt_n; # XXX RequiredBy $main::not = $opt_n; $state->{defines} = \%defines; @@ -142,50 +141,6 @@ sub cleanup OpenBSD::SharedItems::cleanup($self, $state); } -package OpenBSD::MyStat; -use OpenBSD::Vstat; -sub new -{ - my $class = shift; - bless {}, $class -} - -sub add -{ - shift; - &OpenBSD::Vstat::add; -} - -sub remove -{ - shift; - &OpenBSD::Vstat::remove; -} - -sub exists -{ - shift; - &OpenBSD::Vstat::vexists; -} - -sub stat -{ - shift; - &OpenBSD::Vstat::filestat; -} - -sub tally -{ - shift; - &OpenBSD::Vstat::tally; -} - -sub synchronize -{ - my $self = shift; - OpenBSD::Vstat::synchronize($self->{not}); -} - package OpenBSD::Log; use OpenBSD::Error; our @ISA = qw(OpenBSD::Error); @@ -203,6 +158,7 @@ sub dump package OpenBSD::UI; use OpenBSD::Error; +use OpenBSD::Vstat; sub new { @@ -216,7 +172,7 @@ sub init { my $self = shift; $self->{l} = OpenBSD::Log->new; - $self->{vstat} = OpenBSD::MyStat->new; + $self->{vstat} = OpenBSD::Vstat->new($self); $self->{progressmeter} = bless {}, "OpenBSD::StubProgress"; $self->{status} = OpenBSD::Status->new; $self->{recorder} = OpenBSD::SharedItemsRecorder->new; diff --git a/usr.sbin/pkg_add/OpenBSD/Vstat.pm b/usr.sbin/pkg_add/OpenBSD/Vstat.pm index 109fc56b38f..f24868582ac 100644 --- a/usr.sbin/pkg_add/OpenBSD/Vstat.pm +++ b/usr.sbin/pkg_add/OpenBSD/Vstat.pm @@ -1,5 +1,5 @@ # ex:ts=8 sw=4: -# $OpenBSD: Vstat.pm,v 1.47 2010/01/02 12:59:45 espie Exp $ +# $OpenBSD: Vstat.pm,v 1.48 2010/01/02 14:13:02 espie Exp $ # # Copyright (c) 2003-2007 Marc Espie <espie@openbsd.org> # @@ -28,63 +28,192 @@ package OpenBSD::Vstat; use File::Basename; use OpenBSD::Paths; -my $devinfo = {}; -my $devinfo2 = {}; -our $virtual = {}; +sub stat +{ + my ($self, $fname) = @_; + my $dev = (stat $fname)[0]; + + if (!defined $dev && $fname ne '/') { + return $self->stat(dirname($fname)); + } + return OpenBSD::MountPoint->find($dev, $fname, $self->{state}); +} + +sub account_for +{ + my ($self, $name, $size) = @_; + my $e = $self->stat($name); + $e->{used} += $size; + return $e; +} + +sub account_later +{ + my ($self, $name, $size) = @_; + my $e = $self->stat($name); + $e->{delayed} += $size; + return $e; +} + +sub new +{ + my ($class, $state) = @_; + + bless {v => [{}], state => $state}, $class; +} + +sub exists +{ + my ($self, $name) = @_; + for my $v (@{$self->{v}}) { + if (defined $v->{$name}) { + return $v->{$name}; + } + } + return -e $name; +} + +sub synchronize +{ + my ($self) = @_; + OpenBSD::MountPoint->synchronize; + return if $self->{state}->{not}; + $self->{v} = [{}]; +} + +sub add +{ + my ($self, $name, $size, $value) = @_; + if (defined $value) { + $self->{v}[0]->{$name} = $value; + } else { + $self->{v}[0]->{$name} = 1; + } + return defined($size) ? $self->account_for($name, $size) : undef; +} + +sub remove +{ + my ($self, $name, $size) = @_; + $self->{v}[0]->{$name} = 0; + return defined($size) ? $self->account_later($name, -$size) : undef; +} + +sub tally +{ + OpenBSD::MountPoint->tally; +} + +package OpenBSD::MountPoint; + +my $devinfo; my $giveup; -sub create_device($) +sub parse_opts { - my $dev = shift; - my $n = $devinfo->{$dev}; - if (!defined $n) { - $n = { dev => $dev, used => 0, delayed => 0, problems => 0 }; - bless $n, "OpenBSD::Vstat::MountPoint"; - $devinfo->{$dev} = $n; + my ($self, $opts) = @_; + for my $o (split /\,\s*/o, $opts) { + if ($o eq 'read-only') { + $self->{ro} = 1; + } elsif ($o eq 'nodev') { + $self->{nodev} = 1; + } elsif ($o eq 'nosuid') { + $self->{nosuid} = 1; + } elsif ($o eq 'noexec') { + $self->{noexec} = 1; + } + } +} + +sub ro +{ + return shift->{ro}; +} + +sub nodev +{ + return shift->{nodev}; +} + +sub nosuid +{ + return shift->{nosuid}; +} + +sub noexec +{ + return shift->{noexec}; +} + +sub create +{ + my ($class, $dev, $opts) = @_; + my $n = bless + { dev => $dev, used => 0, delayed => 0, problems => 0 }, + $class; + if (defined $opts) { + $n->parse_opts($opts); } return $n; } -sub init_devices() +sub new +{ + my ($class, $dev, $opts) = @_; + + if (!defined $devinfo->{$dev}) { + $devinfo->{$dev} = $class->create($dev, $opts); + } + return $devinfo->{$dev}; +} + +sub run { + my $state = shift; + my $code = pop; + open(my $cmd, "-|", @_) or + $state->errsay("Can't run ",join(' ', @_)) + and return; + my $_; + while (<$cmd>) { + &$code($_); + } + if (!close($cmd)) { + if ($!) { + $state->errsay("Error running ", join(' ', @_),": $!"); + } else { + $state->errsay("Exit status $? from ", join(' ', @_)); + } + } +} + +sub ask_mount +{ + my $state = shift; + + $giveup = OpenBSD::MountPoint::Fail->new; delete $ENV{'BLOCKSIZE'}; - open(my $cmd1, "-|", OpenBSD::Paths->mount) or print STDERR "Can't run mount\n"; - while (<$cmd1>) { + run($state, OpenBSD::Paths->mount, sub { + my $_ = shift; chomp; if (m/^(.*?)\s+on\s+\/.*?\s+type\s+.*?(?:\s+\((.*?)\))?$/o) { my ($dev, $opts) = ($1, $2); - my $i = create_device($dev); - next unless defined $i; - next unless defined $opts; - for my $o (split /\,\s*/o, $opts) { - if ($o eq 'read-only') { - $i->{ro} = 1; - } elsif ($o eq 'nodev') { - $i->{nodev} = 1; - } elsif ($o eq 'nosuid') { - $i->{nosuid} = 1; - } elsif ($o eq 'noexec') { - $i->{noexec} = 1; - } - } + OpenBSD::MountPoint->new($dev, $opts); } else { - print STDERR "Can't parse mount line: $_\n"; + $state->errsay("Can't parse mount line: $_"); } - } - close($cmd1) or print STDERR "Error running mount: $!\n"; - $giveup = { used => 0, dev => '???' }; - bless $giveup, "OpenBSD::Vstat::Failsafe"; + }); } -sub ask_df($) +sub ask_df { - my $fname = shift; - my $info = $giveup; + my ($fname, $state) = @_; - open(my $cmd2, "-|", OpenBSD::Paths->df, $fname) - or print STDERR "Can't run df\n"; + my $info = $giveup; my $blocksize = 512; - while (<$cmd2>) { + + run($state, OpenBSD::Paths->df, "--", $fname, sub { + my $_ = shift; chomp; if (m/^Filesystem\s+(\d+)\-blocks/o) { $blocksize = $1; @@ -92,96 +221,39 @@ sub ask_df($) my ($dev, $avail) = ($1, $2); $info = $devinfo->{$dev}; if (!defined $info) { - $info = create_device($dev); + $info = OpenBSD::MountPoint->new($dev); } $info->{avail} = $avail; $info->{blocksize} = $blocksize; } - } + }); - close($cmd2) or print STDERR "Error running df: $!\n"; return $info; } -init_devices(); - -sub filestat($); - -sub filestat($) +sub find { - my $fname = shift; - my $dev = (stat $fname)[0]; - - if (!defined $dev && $fname ne '/') { - return filestat(dirname($fname)); - } + my ($class, $dev, $fname, $state) = @_; + ask_mount($state) if !defined $devinfo; if (!defined $dev) { return $giveup; - } else { - if (!defined $devinfo2->{$dev}) { - return $devinfo2->{$dev} = ask_df($fname); - } else { - return $devinfo2->{$dev}; - } } -} - -sub vexists($) -{ - my $name = shift; - if (defined $virtual->{$name}) { - return $virtual->{$name}; - } else { - return -e $name; + my $info = $devinfo->{$dev}; + if (!defined $info->{avail}) { + $info = ask_df($fname, $state); } -} - -sub account_for($$) -{ - my ($name, $size) = @_; - my $e = filestat($name); - $e->{used} += $size; - return $e; -} - -sub account_later($$) -{ - my ($name, $size) = @_; - my $e = filestat($name); - $e->{delayed} += $size; - return $e; + return $info; } sub synchronize { - my $not = shift; while (my ($k, $v) = each %$devinfo) { $v->{used} += $v->{delayed}; $v->{delayed} = 0; } - # Grab back all memory if we can ! - $virtual = {} unless $not; } -sub add($$;$) -{ - my ($name, $size, $value) = @_; - if (defined $value) { - $virtual->{$name} = $value; - } else { - $virtual->{$name} = 1; - } - return defined($size) ? account_for($name, $size) : undef; -} - -sub remove($$) -{ - my ($name, $size) = @_; - $virtual->{$name} = 0; - return defined($size) ? account_later($name, -$size) : undef; -} - -sub tally() +sub tally { while (my ($device, $data) = each %$devinfo) { if ($data->{used} != 0) { @@ -195,7 +267,6 @@ sub tally() } } -package OpenBSD::Vstat::MountPoint; sub avail { my $self = shift; @@ -203,30 +274,6 @@ sub avail return $self->{avail} - $self->{used}/$self->{blocksize}; } -sub ro -{ - my $self = shift; - return $self->{ro}; -} - -sub noexec -{ - my $self = shift; - return $self->{noexec}; -} - -sub nosuid -{ - my $self = shift; - return $self->{nosuid}; -} - -sub nodev -{ - my $self = shift; - return $self->{nodev}; -} - sub report_ro { my ($s, $state, $fname) = @_; @@ -262,8 +309,14 @@ sub report_noexec $state->{problems}++; } -package OpenBSD::Vstat::Failsafe; -our @ISA=(qw(OpenBSD::Vstat::MountPoint)); +package OpenBSD::MountPoint::Fail; +our @ISA=qw(OpenBSD::MountPoint); + +sub new +{ + my $class = shift; + bless { avail => 0, used => 0, dev => '???' }, $class; +} sub avail { diff --git a/usr.sbin/pkg_add/pod/OpenBSD::Vstat.pod b/usr.sbin/pkg_add/pod/OpenBSD::Vstat.pod index 60e9e9d5dd4..3e7c0d2b39d 100644 --- a/usr.sbin/pkg_add/pod/OpenBSD::Vstat.pod +++ b/usr.sbin/pkg_add/pod/OpenBSD::Vstat.pod @@ -1,4 +1,4 @@ -$OpenBSD: OpenBSD::Vstat.pod,v 1.4 2009/12/17 11:41:30 espie Exp $ +$OpenBSD: OpenBSD::Vstat.pod,v 1.5 2010/01/02 14:13:02 espie Exp $ =head1 NAME @@ -8,29 +8,33 @@ OpenBSD::Vstat - virtual filesystem for C<pkg_add(1)> simulations use OpenBSD::Vstat; - $h = OpenBSD::Vstat::add($filename, $size, $tag); - OpenBSD::Vstat::remove($filename, $size); - $e = OpenBSD::Vstat::vexists($filename); - OpenBSD::Vstat::tally(); + my $v = OpenBSD::Vstat->new($state); + + $h = $v->add($filename, $size, $tag); + $v->remove($filename, $size); + $e = $v->exists($filename); + $v->tally; =head1 DESCRIPTION -C<OpenBSD::Vstat> provides functions to layout a virtual file system on top +C<OpenBSD::Vstat> provides methods to layout a virtual file system on top of the real one. This is generally used to simulate file system manipulations before doing them for real. -The functions C<OpenBSD::Vstat::add> (respectively -C<OpenBSD::Vstat::remove>) can be used to add a filename to +The constructor C<new> expect a C<$state> object, that is, an object with +C<$state-E<gt>{not}> and C<$state-E<gt>errsay> defined. + +The method C<add> (respectively C<remove>) can be used to add a filename to the file system (resp. remove a filename from the file system). -The function C<OpenBSD::Vstat:vexists> looks for +The method C<exists> looks for a given filename: first it checks if it has been added or removed in the virtual filesystem. Failing that, it looks into the real file system using C<-e>. -Both C<OpenBSD::Vstat::add> and C<OpenBSD::Vstat::remove> also know about +Both C<add> and C<remove> also know about Unix filesystem semantics, namely C<mount(8)> points and disk usage. They return a small object corresponding to the filename's file system with -the following fields +the following methods =over 8 @@ -50,29 +54,25 @@ defined if the filesystem forbids execution. defined if the filesystem forbids SUID files. -=item avail() +=item avail returns the number of bytes still available on the filesystem. =back -C<OpenBSD::Vstat::vexists> returns a true value if the filename exists. -If it is a virtual name added through C<OpenBSD::Vstat::add>, it returns +C<exists> returns a true value if the filename exists. +If it is a virtual name added through C<add>, it returns the C<$tag> specified as an optional argument. Otherwise, it returns 1. -C<OpenBSD::Vstat:tally> displays a summary of filesystem manipulations +C<tally> displays a summary of filesystem manipulations after a series of additions and removals. Due to the way packages get updated, size modifications through -C<OpenBSD::Vstat::remove> are delayed until the next call to -C<OpenBSD::Vstat::synchronize>: old files must be removed before +C<remove> are delayed until the next call to +C<synchronize>: old files must be removed before adding the new files in order to properly account for collisions, but the old files occupy disk space while the new package gets extracted. -=head1 CAVEATS - -The API to this module may change. - =head1 BUGS AND LIMITATIONS C<OpenBSD::Vstat> now handles C<chroot(8)> situations gracefully, but |