summaryrefslogtreecommitdiff
path: root/usr.sbin/pkg_add/OpenBSD/PackageLocation.pm
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/pkg_add/OpenBSD/PackageLocation.pm')
-rw-r--r--usr.sbin/pkg_add/OpenBSD/PackageLocation.pm316
1 files changed, 316 insertions, 0 deletions
diff --git a/usr.sbin/pkg_add/OpenBSD/PackageLocation.pm b/usr.sbin/pkg_add/OpenBSD/PackageLocation.pm
new file mode 100644
index 00000000000..97920b98bfd
--- /dev/null
+++ b/usr.sbin/pkg_add/OpenBSD/PackageLocation.pm
@@ -0,0 +1,316 @@
+# ex:ts=8 sw=4:
+# $OpenBSD: PackageLocation.pm,v 1.1 2006/03/04 13:13:05 espie Exp $
+#
+# Copyright (c) 2003-2004 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;
+
+package OpenBSD::PackageLocation;
+
+use OpenBSD::PackageInfo;
+use OpenBSD::Temp;
+
+sub new
+{
+ my ($class, $repository, $name) = @_;
+ my $self = { repository => $repository, name => $name};
+ bless $self, $class;
+}
+
+sub openArchive
+{
+ my $self = shift;
+
+ my $fh = $self->{repository}->open($self);
+ if (!defined $fh) {
+ $self->{repository}->parse_problems($self->{errors})
+ if defined $self->{errors};
+ undef $self->{errors};
+ return undef;
+ }
+ require OpenBSD::Ustar;
+
+ my $archive = new OpenBSD::Ustar $fh;
+ $self->{_archive} = $archive;
+}
+
+sub grabInfoFiles
+{
+ my $self = shift;
+ my $dir = $self->{dir} = OpenBSD::Temp::dir();
+
+ if (defined $self->{contents} && ! -f $dir.CONTENTS) {
+ open my $fh, '>', $dir.CONTENTS or die "Permission denied";
+ print $fh $self->{contents};
+ close $fh;
+ }
+
+ while (my $e = $self->intNext()) {
+ if ($e->isFile() && is_info_name($e->{name})) {
+ $e->{name}=$dir.$e->{name};
+ eval { $e->create(); };
+ if ($@) {
+ unlink($e->{name});
+ $@ =~ s/\s+at.*//;
+ print STDERR $@;
+ return 0;
+ }
+ } else {
+ $self->unput();
+ last;
+ }
+ }
+ return 1;
+}
+
+sub scanPackage
+{
+ my $self = shift;
+ while (my $e = $self->intNext()) {
+ if ($e->isFile() && is_info_name($e->{name})) {
+ if ($e->{name} eq CONTENTS && !defined $self->{dir}) {
+ $self->{contents} = $e->contents();
+ last;
+ }
+ if (!defined $self->{dir}) {
+ $self->{dir} = OpenBSD::Temp::dir();
+ }
+ $e->{name}=$self->{dir}.$e->{name};
+ eval { $e->create(); };
+ if ($@) {
+ unlink($e->{name});
+ $@ =~ s/\s+at.*//;
+ print STDERR $@;
+ return 0;
+ }
+ } else {
+ $self->unput();
+ last;
+ }
+ }
+ return 1;
+}
+
+sub grabPlist
+{
+ my ($self, $pkgname, $arch, $code) = @_;
+
+ my $pkg = $self->openPackage($pkgname, $arch);
+ if (defined $pkg) {
+ my $plist = $self->plist($code);
+ $pkg->wipe_info();
+ $pkg->close_now();
+ return $plist;
+ } else {
+ return undef;
+ }
+}
+
+sub openPackage
+{
+ my ($self, $pkgname, $arch) = @_;
+ if (!$self->openArchive()) {
+ return undef;
+ }
+ $self->scanPackage();
+
+ if (defined $self->{contents}) {
+ return $self;
+ }
+
+ # maybe it's a fat package.
+ while (my $e = $self->intNext()) {
+ unless ($e->{name} =~ m/\/\+CONTENTS$/) {
+ last;
+ }
+ my $prefix = $`;
+ my $contents = $e->contents();
+ require OpenBSD::PackingList;
+
+ $pkgname =~ s/\.tgz$//;
+
+ my $plist = OpenBSD::PackingList->fromfile(\$contents,
+ \&OpenBSD::PackingList::FatOnly);
+ next if defined $pkgname and $plist->pkgname() ne $pkgname;
+ if ($plist->has('arch')) {
+ if ($plist->{arch}->check($arch)) {
+ $self->{filter} = $prefix;
+ bless $self, "OpenBSD::FatPackageLocation";
+ $self->{contents} = $contents;
+ return $self;
+ }
+ }
+ }
+ # hopeless
+ $self->close_with_client_error();
+ $self->wipe_info();
+ return undef;
+}
+
+sub wipe_info
+{
+ my $self = shift;
+ $self->{repository}->wipe_info($self);
+}
+
+sub info
+{
+ my $self = shift;
+ if (!defined $self->{dir}) {
+ $self->grabInfoFiles();
+ }
+ return $self->{dir};
+}
+
+sub plist
+{
+ my ($self, $code) = @_;
+
+ require OpenBSD::PackingList;
+
+ if (defined $self->{contents}) {
+ my $value = $self->{contents};
+ return OpenBSD::PackingList->fromfile(\$value, $code);
+ } elsif (defined $self->{dir} && -f $self->{dir}.CONTENTS) {
+ return OpenBSD::PackingList->fromfile($self->{dir}.CONTENTS,
+ $code);
+ }
+ # hopeless
+ $self->close_with_client_error();
+
+ return undef;
+}
+
+sub close
+{
+ my ($self, $hint) = @_;
+ $self->{repository}->close($self, $hint);
+}
+
+sub finish_and_close
+{
+ my $self = shift;
+ $self->{repository}->finish_and_close($self);
+}
+
+sub close_now
+{
+ my $self = shift;
+ $self->{repository}->close_now($self);
+}
+
+sub close_after_error
+{
+ my $self = shift;
+ $self->{repository}->close_after_error($self);
+}
+
+sub close_with_client_error
+{
+ my $self = shift;
+ $self->{repository}->close_with_client_error($self);
+}
+
+sub deref
+{
+ my $self = shift;
+ $self->{fh} = undef;
+ $self->{_archive} = undef;
+}
+
+sub reopen
+{
+ my $self = shift;
+ if (!$self->openArchive()) {
+ return undef;
+ }
+ while (my $e = $self->{_archive}->next()) {
+ if ($e->{name} eq $self->{_current}->{name}) {
+ $self->{_current} = $e;
+ return $self;
+ }
+ }
+ return undef;
+}
+
+# proxy for archive operations
+sub next
+{
+ my $self = shift;
+
+ if (!defined $self->{dir}) {
+ $self->grabInfoFiles();
+ }
+ return $self->intNext();
+}
+
+sub intNext
+{
+ my $self = shift;
+
+ if (!defined $self->{fh}) {
+ if (!$self->reopen()) {
+ return undef;
+ }
+ }
+ if (!$self->{_unput}) {
+ $self->{_current} = $self->getNext();
+ }
+ $self->{_unput} = 0;
+ return $self->{_current};
+}
+
+sub unput
+{
+ my $self = shift;
+ $self->{_unput} = 1;
+}
+
+sub getNext
+{
+ my $self = shift;
+
+ return $self->{_archive}->next();
+}
+
+sub skip
+{
+ my $self = shift;
+ return $self->{_archive}->skip();
+}
+
+package OpenBSD::FatPackageLocation;
+our @ISA=qw(OpenBSD::PackageLocation);
+
+sub getNext
+{
+ my $self = shift;
+
+ my $e = $self->SUPER::getNext();
+ if ($e->{name} =~ m/^(.*?)\/(.*)$/) {
+ my ($beg, $name) = ($1, $2);
+ if (index($beg, $self->{filter}) == -1) {
+ return $self->next();
+ }
+ $e->{name} = $name;
+ if ($e->isHardLink()) {
+ $e->{linkname} =~ s/^(.*?)\///;
+ }
+ }
+ return $e;
+}
+
+1;