summaryrefslogtreecommitdiff
path: root/usr.sbin/pkg_add/OpenBSD
diff options
context:
space:
mode:
authorMarc Espie <espie@cvs.openbsd.org>2003-10-16 17:43:35 +0000
committerMarc Espie <espie@cvs.openbsd.org>2003-10-16 17:43:35 +0000
commitf590f7679f0eb9b733faf2b7287dc4c6f250cdac (patch)
tree0782149036d61c04d496ff0698bf4e86ff8cc633 /usr.sbin/pkg_add/OpenBSD
parentb3fb36e241c10f88ff39c1fde2c2f0bfea706bea (diff)
new import of my pkgtools, after a slight naming disagreement with the
Upper Management...
Diffstat (limited to 'usr.sbin/pkg_add/OpenBSD')
-rw-r--r--usr.sbin/pkg_add/OpenBSD/PackageInfo.pm115
-rw-r--r--usr.sbin/pkg_add/OpenBSD/PackageLocator.pm268
-rw-r--r--usr.sbin/pkg_add/OpenBSD/PackageName.pm250
-rw-r--r--usr.sbin/pkg_add/OpenBSD/PackingElement.pm542
-rw-r--r--usr.sbin/pkg_add/OpenBSD/PackingList.pm142
-rw-r--r--usr.sbin/pkg_add/OpenBSD/PkgCfl.pm68
-rw-r--r--usr.sbin/pkg_add/OpenBSD/RequiredBy.pm81
-rw-r--r--usr.sbin/pkg_add/OpenBSD/Temp.pm44
-rw-r--r--usr.sbin/pkg_add/OpenBSD/Ustar.pm278
-rw-r--r--usr.sbin/pkg_add/OpenBSD/md5.pm43
10 files changed, 1831 insertions, 0 deletions
diff --git a/usr.sbin/pkg_add/OpenBSD/PackageInfo.pm b/usr.sbin/pkg_add/OpenBSD/PackageInfo.pm
new file mode 100644
index 00000000000..e562aa00450
--- /dev/null
+++ b/usr.sbin/pkg_add/OpenBSD/PackageInfo.pm
@@ -0,0 +1,115 @@
+# $OpenBSD: PackageInfo.pm,v 1.1 2003/10/16 17:43:34 espie Exp $
+#
+# Copyright (c) 2003 Marc Espie.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
+# PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+use strict;
+use warnings;
+package OpenBSD::PackageInfo;
+our @ISA=qw(Exporter);
+our @EXPORT=qw(installed_packages installed_info info_names is_info_name
+ add_installed is_installed CONTENTS COMMENT DESC INSTALL DEINSTALL REQUIRE
+ REQUIRED_BY DISPLAY MTREE_DIRS);
+
+use OpenBSD::PackageName;
+use constant {
+ CONTENTS => '+CONTENTS',
+ COMMENT => '+COMMENT',
+ DESC => '+DESC',
+ INSTALL => '+INSTALL',
+ DEINSTALL => '+DEINSTALL',
+ REQUIRE => '+REQUIRE',
+ REQUIRED_BY => '+REQUIRED_BY',
+ DISPLAY => '+DISPLAY',
+ MTREE_DIRS => '+MTREE_DIRS' };
+
+my $pkg_db = $ENV{"PKG_DBDIR"} || '/var/db/pkg';
+
+our @list;
+my $read_list;
+
+our @info = (CONTENTS, COMMENT, DESC, INSTALL, DEINSTALL, REQUIRE, REQUIRED_BY, DISPLAY, MTREE_DIRS);
+
+our %info = ();
+for my $i (@info) {
+ my $j = $i;
+ $j =~ s/\+/F/;
+ $info{$i} = $j;
+}
+
+sub add_installed
+{
+ if (!$read_list) {
+ installed_packages();
+ }
+ push(@list, @_);
+}
+
+sub installed_packages()
+{
+ if (!$read_list) {
+ @list = ();
+ $read_list = 1;
+
+ opendir(my $dir, $pkg_db) or die "Bad pkg_db";
+ while (my $e = readdir($dir)) {
+ next if $e eq '.' or $e eq '..';
+ next unless -d "$pkg_db/$e";
+ if (-f "$pkg_db/$e/+CONTENTS") {
+ add_installed($e);
+ } else {
+ print "Warning: $e is not really a package";
+ }
+ }
+ close($dir);
+ }
+ return @list;
+}
+
+sub installed_info($)
+{
+ my $name = shift;
+ return "$pkg_db/$name/";
+}
+
+sub is_installed($)
+{
+ my $name = shift;
+ my $dir = installed_info($name);
+ return unless -d $dir;
+ return unless -f $dir.CONTENTS;
+ return $dir;
+}
+
+sub info_names()
+{
+ return @info;
+}
+
+sub is_info_name($)
+{
+ my $name = shift;
+ return $info{$name};
+}
+
+1;
diff --git a/usr.sbin/pkg_add/OpenBSD/PackageLocator.pm b/usr.sbin/pkg_add/OpenBSD/PackageLocator.pm
new file mode 100644
index 00000000000..c195d3ca289
--- /dev/null
+++ b/usr.sbin/pkg_add/OpenBSD/PackageLocator.pm
@@ -0,0 +1,268 @@
+# $OpenBSD: PackageLocator.pm,v 1.1 2003/10/16 17:43:34 espie Exp $
+#
+# Copyright (c) 2003 Marc Espie.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
+# PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+use strict;
+use warnings;
+
+# XXX we don't want to load Ustar all the time
+package OpenBSD::Ustar;
+
+our $AUTOLOAD;
+
+sub AUTOLOAD {
+ eval { require OpenBSD::Ustar;
+ };
+ goto &$AUTOLOAD;
+}
+
+package OpenBSD::PackageLocation;
+
+sub _new
+{
+ my ($class, $location) = @_;
+ bless { location => $location }, $class;
+}
+
+sub new
+{
+ my ($class, $location) = @_;
+ if ($location =~ m/^ftp\:/i) {
+ return OpenBSD::PackageLocation::FTP->_new($location);
+ } elsif ($location =~ m/^http\:/i) {
+ return OpenBSD::PackageLocation::HTTP->_new($location);
+ } elsif ($location =~ m/^scp\:/i) {
+ return OpenBSD::PackageLocation::SCP->_new($location);
+ } else {
+ return OpenBSD::PackageLocation::Local->_new($location);
+ }
+}
+
+package OpenBSD::PackageLocation::SCP;
+our @ISA=qw(OpenBSD::PackageLocation OpenBSD::PackageLocation::FTPorSCP);
+
+sub _new
+{
+ my ($class, $location) = @_;
+ $location =~ s/scp\:\/\///i;
+ $location =~ m/\//;
+ bless { host => $`, path => "/$'" }, $class;
+}
+
+sub open
+{
+ my ($self, $name) = @_;
+ my $host = $self->{host};
+ my $path = $self->{path};
+ open(my $fh, '-|', "scp $host:$path$name /dev/stdout 2> /dev/null|gzip -d -c -q - 2> /dev/null") or return undef;
+ return $fh;
+}
+
+sub list
+{
+ my ($self) = @_;
+ my $host = $self->{host};
+ my $path = $self->{path};
+ return _list("ssh $host ls -l $path");
+}
+
+package OpenBSD::PackageLocation::Local;
+our @ISA=qw(OpenBSD::PackageLocation);
+
+sub open
+{
+ my ($self, $name) = @_;
+ my $fullname = $self->{location}.$name;
+ open(my $fh, '-|', "gzip -d -c -q 2>/dev/null $fullname") or return undef;
+ return $fh;
+}
+
+sub list
+{
+ my $self = shift;
+ my @l = ();
+ opendir(my $dir, $self->{location}) or return undef;
+ while (my $e = readdir $dir) {
+ next unless -f "$dir/$e";
+ next unless $e = ~ m/\.tgz$/;
+ push(@l, $`);
+ }
+ close($dir);
+ return @l;
+}
+
+package OpenBSD::PackageLocation::FTPorSCP;
+
+sub _list
+{
+ my ($self, $cmd) = @_;
+ my @l =();
+ local $_;
+ open(my $fh, '-|', "$cmd") or return undef;
+ while(<$fh>) {
+ chomp;
+ next if m/^d.*\s+\S/;
+ next unless m/([^\s]+)\.tgz\s*$/;
+ push(@l, $1);
+ }
+ close($fh);
+ return @l;
+}
+
+package OpenBSD::PackageLocation::HTTPorFTP;
+sub open
+{
+ my ($self, $name) = @_;
+ my $fullname = $self->{location}.$name;
+ open(my $fh, '-|', "ftp -o - $fullname 2>/dev/null|gzip -d -c -q - 2>/dev/null") or return undef;
+ return $fh;
+}
+
+package OpenBSD::PackageLocation::HTTP;
+our @ISA=qw(OpenBSD::PackageLocation::HTTPorFTP OpenBSD::PackageLocation);
+sub list
+{
+ my ($self) = @_;
+ my $fullname = $self->{location};
+ my @l =();
+ local $_;
+ open(my $fh, '-|', "echo ls|ftp -o - $fullname 2>/dev/null") or return undef;
+ # XXX assumes a pkg HREF won't cross a line. Is this the case ?
+ while(<$fh>) {
+ chomp;
+ for my $pkg (m/\<A\s+HREF=\"(.*?)\.tgz\"\>/gi) {
+ next if $pkg =~ m|/|;
+ push(@l, $pkg);
+ }
+ }
+ close($fh);
+ return @l;
+}
+
+package OpenBSD::PackageLocation::FTP;
+our @ISA=qw(OpenBSD::PackageLocation::HTTPorFTP OpenBSD::PackageLocation OpenBSD::PackageLocation::FTPorSCP);
+
+sub list
+{
+ my ($self) = @_;
+ my $fullname = $self->{location};
+ return _list("echo ls|ftp -o - $fullname 2>/dev/null");
+}
+
+
+package OpenBSD::PackageLocator;
+
+# this returns an archive handle from an uninstalled package name, currently
+# There is a cache available.
+
+use OpenBSD::PackageInfo;
+use OpenBSD::Temp;
+
+my %packages;
+my @pkgpath;
+
+if (defined $ENV{PKG_PATH}) {
+ my @tentative = split /\:/, $ENV{PKG_PATH};
+ @pkgpath = ();
+ while (my $i = shift @tentative) {
+ if ($i =~ m/^(?:ftp|http|scp)$/i) {
+ $i.= ":".(shift @tentative);
+ }
+ $i =~ m|/$| or $i.='/';
+ unshift @pkgpath, OpenBSD::PackageLocation->new($i);
+ }
+}
+
+sub find
+{
+ my $class = shift;
+ local $_ = shift;
+ $_.=".tgz" unless m/\.tgz$/;
+ if (exists $packages{$_}) {
+ return $packages{$_};
+ }
+ my $package;
+ if (m/\//) {
+ my $location = OpenBSD::PackageLocation->new($_);
+ $package = openAbsolute($location, '');
+ } else {
+ for my $p (@pkgpath) {
+ $package = openAbsolute($p, $_);
+ last if defined $package;
+ }
+ }
+ return $package unless defined $package;
+ $packages{$_} = $package;
+ bless $package, $class;
+}
+
+sub info
+{
+ my $self = shift;
+ return $self->{dir};
+}
+
+sub close
+{
+ my $self = shift;
+ close($self->{fh});
+ $self->{fh} = undef;
+ $self->{archive} = undef;
+}
+
+sub openAbsolute
+{
+ my ($location, $name) = @_;
+ my $fh = $location->open($name);
+ if (!defined $fh) {
+ return undef;
+ }
+ my $archive = new OpenBSD::Ustar $fh;
+ my $dir = OpenBSD::Temp::dir();
+
+ my $self = { name => $_, fh => $fh, archive => $archive, dir => $dir };
+ # check that Open worked
+ while (my $e = $archive->next()) {
+ if ($e->isFile() && is_info_name($e->{name})) {
+ $e->{name}=$dir.$e->{name};
+ $e->create();
+ } else {
+ $archive->unput();
+ last;
+ }
+ }
+ if (-f $dir.CONTENTS) {
+ return $self;
+ } else {
+ CORE::close($fh);
+ return undef;
+ }
+}
+
+# allows the autoloader to work correctly
+sub DESTROY
+{
+}
+
+1;
diff --git a/usr.sbin/pkg_add/OpenBSD/PackageName.pm b/usr.sbin/pkg_add/OpenBSD/PackageName.pm
new file mode 100644
index 00000000000..512a770b58d
--- /dev/null
+++ b/usr.sbin/pkg_add/OpenBSD/PackageName.pm
@@ -0,0 +1,250 @@
+# $OpenBSD: PackageName.pm,v 1.1 2003/10/16 17:43:34 espie Exp $
+#
+# Copyright (c) 2003 Marc Espie.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
+# PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+use strict;
+use warnings;
+package OpenBSD::PackageName;
+
+sub new
+{
+ my ($class, $name) = @_;
+ my $self = { name => $name };
+# remove irrelevant filesystem info
+ $name =~ s|.*/||;
+ $name =~ s|\.tgz||;
+ $self->{pkgname} = $name;
+# cut pkgname into pieces
+ my @list = splitname($name);
+ $self->{stem} = $list[0];
+ $self->{version} = $list[1];
+ $self->{flavors} = [];
+ push @{$self->{flavors}}, @list[2,];
+ bless $self, $class;
+}
+
+# see package-specs(7)
+sub splitname
+{
+ local $_ = shift;
+ if (/\-(?=\d)/) {
+ my $stem = $`;
+ my $rest = $';
+ my @all = split /\-/, $rest;
+ return ($stem, @all);
+ } else {
+ return ($_);
+ }
+}
+
+# all the shit that does handle package specifications
+sub compare_pseudo_numbers
+{
+ my ($n, $m) = @_;
+
+ my ($n1, $m1);
+
+ if ($n =~ m/^\d+/) {
+ $n1 = $&;
+ $n = $';
+ }
+ if ($m =~ m/^\d+/) {
+ $m1 = $&;
+ $m = $';
+ }
+
+ if ($n1 == $m1) {
+ return $n cmp $m;
+ } else {
+ return $n1 <=> $m1;
+ }
+}
+
+
+sub dewey_compare
+{
+ my ($a, $b) = @_;
+ my ($pa, $pb);
+
+ unless ($b =~ m/p\d+$/) { # does the Dewey hold a p<number> ?
+ $a =~ s/p\d+$//; # No -> strip it from version.
+ }
+
+ return 0 if $a =~ /^$b$/; # bare equality
+
+ if ($a =~ s/p(\d+)$//) { # extract patchlevels
+ $pa = $1;
+ }
+ if ($b =~ s/p(\d+)$//) {
+ $pb = $1;
+ }
+
+ my @a = split(/\./, $a);
+ push @a, $pa if defined $pa; # ... and restore them
+ my @b = split(/\\\./, $b);
+ push @b, $pb if defined $pb;
+ while (@a > 0 && @b > 0) {
+ my $va = shift @a;
+ my $vb = shift @b;
+ next if $va eq $vb;
+ return compare_pseudo_numbers($va, $vb);
+ }
+ if (@a > 0) {
+ return 1;
+ } else {
+ return -1;
+ }
+}
+
+sub check_version
+{
+ my ($v, $spec) = @_;
+ local $_;
+
+ # any version spec
+ return 1 if $spec eq '.*';
+
+ my @specs = split(/,/, $spec);
+ for (grep /^\d/, @specs) { # exact number: check match
+ return 1 if $v =~ /^$_$/;
+ return 1 if $v =~ /^${_}p\d+$/; # allows for recent patches
+ }
+
+ # Last chance: dewey specs ?
+ my @deweys = grep !/^\d/, @specs;
+ for (@deweys) {
+ if (m/^\<\=|\>\=|\<|\>/) {
+ my ($op, $dewey) = ($&, $');
+ my $compare = dewey_compare($v, $dewey);
+ return 0 if $op eq '<' && $compare >= 0;
+ return 0 if $op eq '<=' && $compare > 0;
+ return 0 if $op eq '>' && $compare <= 0;
+ return 0 if $op eq '>=' && $compare < 0;
+ } else {
+ return 0; # unknown spec type
+ }
+ }
+ return @deweys == 0 ? 0 : 1;
+}
+
+sub check_1flavor
+{
+ my ($f, $spec) = @_;
+ local $_;
+
+ for (split /-/, $spec) {
+ # must not be here
+ if (m/^\!/) {
+ return 0 if $f->{$'};
+ # must be here
+ } else {
+ return 0 unless $f->{$_};
+ }
+ }
+ return 1;
+}
+
+sub check_flavor
+{
+ my ($f, $spec) = @_;
+ local $_;
+ # no flavor constraints
+ return 1 if $spec eq '';
+
+ $spec =~ s/^-//;
+ # retrieve all flavors
+ my %f = map +($_, 1), split /\-/, $f;
+
+ # check each flavor constraint
+ for (split /,/, $spec) {
+ if (check_1flavor(\%f, $_)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+sub subpattern_match
+{
+ my ($p, $list) = @_;
+ local $_;
+
+ my ($stemspec, $vspec, $flavorspec);
+
+ # first, handle special characters (shell -> perl)
+ $p =~ s/\./\\\./g;
+ $p =~ s/\+/\\\+/g;
+ $p =~ s/\*/\.\*/g;
+ $p =~ s/\?/\./g;
+
+ # then, guess at where the version number is if any,
+
+ # this finds patterns like -<=2.3,>=3.4.p1-
+ # the only constraint is that the actual number
+ # - must start with a digit,
+ # - not contain - or ,
+ if ($p =~ m/\-((?:\>|\>\=|\<|\<\=)?\d[^-]*)/) {
+ ($stemspec, $vspec, $flavorspec) = ($`, $1, $');
+ # `any version' matcher
+ } elsif ($p =~ m/\-(\.\*)/) {
+ ($stemspec, $vspec, $flavorspec) = ($`, $1, $');
+ # okay, so no version marker. Assume no flavor spec.
+ } else {
+ ($stemspec, $vspec, $flavorspec) = ($p, '', '');
+ }
+
+ $p = "$stemspec-\.\*" if $vspec ne '';
+
+ # First trim down the list
+ my @l = grep {/^$p$/} @$list;
+
+ my @result = ();
+ # Now, have to extract the version number, and the flavor...
+ for (@l) {
+ my ($stem, $v, $flavor);
+ if (m/\-(\d[^-]*)/) {
+ ($stem, $v, $flavor) = ($`, $1, $');
+ if ($stem =~ m/^$stemspec$/ &&
+ check_version($v, $vspec) &&
+ check_flavor($flavor, $flavorspec)) {
+ push(@result, $_);
+ }
+ }
+ }
+
+ return @result;
+}
+
+sub pkgspec_match
+{
+ my ($pattern, @list) = @_;
+ my @l = ();
+
+ for my $subpattern (split /\|/, $pattern) {
+ push(@l, subpattern_match($subpattern, \@list));
+ }
+ return @l;
+}
+
+1;
diff --git a/usr.sbin/pkg_add/OpenBSD/PackingElement.pm b/usr.sbin/pkg_add/OpenBSD/PackingElement.pm
new file mode 100644
index 00000000000..e30a917ef28
--- /dev/null
+++ b/usr.sbin/pkg_add/OpenBSD/PackingElement.pm
@@ -0,0 +1,542 @@
+# $OpenBSD: PackingElement.pm,v 1.1 2003/10/16 17:43:34 espie Exp $
+#
+# Copyright (c) 2003 Marc Espie.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
+# PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# This is the basic class, which is mostly abstract, except for
+# setKeyword and Factory.
+# It does provide base methods for stuff under it, though.
+
+use strict;
+use warnings;
+use OpenBSD::PackageInfo;
+package OpenBSD::PackingElement;
+use File::Basename;
+our %keyword;
+
+sub Factory
+{
+ local $_ = shift;
+ if (m/^\@(\S+)\s*/) {
+ my $cmd = $1;
+ my $args = $';
+
+ if (defined $keyword{$cmd}) {
+ $keyword{$cmd}->add(@_, $args);
+ } else {
+ OpenBSD::PackingElement::Other->add(@_, "\@$cmd $args");
+ }
+ } else {
+ OpenBSD::PackingElement::File->add(@_, $_);
+ }
+}
+
+sub setKeyword {
+ my ($class, $k) = @_;
+ $keyword{$k} = $class;
+}
+
+sub category() { 'items' }
+
+sub new
+{
+ my ($class, $args) = @_;
+ bless { name => $args }, $class;
+}
+
+sub destate
+{
+}
+
+sub add
+{
+ my ($class, $plist, @args) = @_;
+
+ my $self = $class->new(@args);
+ $self->destate($plist->{state});
+ $plist->add2list($self);
+ return $self;
+}
+
+sub keyword() { return; }
+
+sub write
+{
+ my ($self, $fh) = @_;
+ print $fh "\@", $self->keyword()," ", $self->{name}, "\n";
+}
+
+sub compute_fullname
+{
+ my ($self, $state) = @_;
+
+ $self->{cwd} = $state->{cwd};
+ my $fullname = $self->{fullname} =
+ File::Spec->canonpath(File::Spec->catfile($state->{cwd}, $self->{name}));
+ $state->{lastfile} = $self;
+ return $fullname;
+}
+
+sub expand
+{
+ my $state = $_[2];
+ local $_ = $_[1];
+ if (m/\%F/) {
+ die "Bad expand" unless defined $state->{lastfile};
+ s/\%F/$state->{lastfile}->{name}/g;
+ }
+ if (m/\%D/) {
+ die "Bad expand" unless defined $state->{cwd};
+ s/\%D/$state->{cwd}/g;
+ }
+ if (m/\%B/) {
+ die "Bad expand" unless defined $state->{lastfile};
+ s/\%B/dirname($state->{lastfile}->fullname())/ge;
+ }
+ if (m/\%f/) {
+ die "Bad expand" unless defined $state->{lastfile};
+ s/\%f/basename($state->{lastfile}->fullname())/ge;
+ }
+ return $_;
+}
+sub IsFile() { 0 }
+
+sub fullname($)
+{
+ return $_[0]->{fullname};
+}
+
+package OpenBSD::PackingElement::File;
+our @ISA=qw(OpenBSD::PackingElement);
+use File::Spec;
+use OpenBSD::PackageInfo qw(is_info_name);
+__PACKAGE__->setKeyword('file');
+
+sub write
+{
+ my ($self, $fh) = @_;
+ print $fh "\@ignore\n" if defined $self->{ignore};
+ if ($self->{name} =~ m/^\@/) {
+ $self->SUPER::write($fh);
+ } else {
+ print $fh $self->{name}, "\n";
+ }
+ if (defined $self->{md5}) {
+ print $fh "\@comment MD5:", $self->{md5}, "\n";
+ }
+}
+
+sub destate
+{
+ my ($self, $state) = @_;
+ $self->compute_fullname($state);
+ if (defined $state->{mode}) {
+ $self->{mode} = $state->{mode};
+ }
+ if (defined $state->{owner}) {
+ $self->{owner} = $state->{owner};
+ }
+ if (defined $state->{group}) {
+ $self->{group} = $state->{group};
+ }
+ if (defined $state->{nochecksum}) {
+ $self->{nochecksum} = 1;
+ undef $state->{nochecksum};
+ }
+ if (defined $state->{ignore}) {
+ $self->{ignore} = 1;
+ undef $state->{ignore};
+ }
+}
+
+sub add
+{
+ my ($class, $plist, @args) = @_;
+
+ my $self = $class->new(@args);
+ $self->destate($plist->{state});
+ my $j = is_info_name($self->fullname());
+ if ($j) {
+ bless $self, "OpenBSD::PackingElement::$j";
+ $plist->addunique($self);
+ } else {
+ $plist->add2list($self);
+ }
+ return $self;
+}
+
+sub add_md5
+{
+ my ($self, $md5) = @_;
+ $self->{md5} = $md5;
+}
+
+sub IsFile() { 1 }
+
+package OpenBSD::PackingElement::Other;
+our @ISA=qw(OpenBSD::PackingElement);
+
+package OpenBSD::PackingElement::Ignore;
+our @ISA=qw(OpenBSD::PackingElement);
+__PACKAGE__->setKeyword('ignore');
+
+sub add
+{
+ my ($class, $plist, @args) = @_;
+ $plist->{state}->{ignore} = 1;
+ return undef;
+}
+
+# Comment is very special
+package OpenBSD::PackingElement::Comment;
+our @ISA=qw(OpenBSD::PackingElement);
+__PACKAGE__->setKeyword('comment');
+sub keyword() { "comment" }
+
+sub add
+{
+ my ($class, $plist, @args) = @_;
+
+ if ($args[0] =~ m/^MD5:\s*/) {
+ $plist->{state}->{lastfile}->add_md5($');
+ return undef;
+ } elsif ($args[0] =~ m/^subdir\=(.*?)\s+cdrom\=(.*?)\s+ftp\=(.*?)\s*$/) {
+ OpenBSD::PackingElement::ExtraInfo->add($plist, $1, $2, $3);
+ } elsif ($args[0] eq 'no checksum') {
+ $plist->{state}->{nochecksum} = 1;
+ return undef;
+ } else {
+ my $self = $class->new(@args);
+ $self->destate($plist->{state});
+ $plist->add2list($self);
+ return $self;
+ }
+}
+
+package OpenBSD::PackingElement::Option;
+our @ISA=qw(OpenBSD::PackingElement);
+__PACKAGE__->setKeyword('option');
+sub keyword() { 'option' }
+
+sub add
+{
+ my ($class, $plist, @args) = @_;
+ if ($args[0] eq 'no-default-conflict') {
+ shift;
+ return OpenBSD::PackingElement::NoDefaultConflict->add(@_);
+ } else {
+ die "Unknown option: $args[0]";
+ }
+}
+
+package OpenBSD::PackingElement::NoDefaultConflict;
+our @ISA=qw(OpenBSD::PackingElement::Unique);
+sub category() { 'no-default-conflict' }
+sub keyword() { 'option' }
+
+# The special elements that don't end in the right place
+package OpenBSD::PackingElement::ExtraInfo;
+our @ISA=qw(OpenBSD::PackingElement);
+
+sub category() { 'extrainfo' }
+
+
+sub new
+{
+ my ($class, $subdir, $cdrom, $ftp) = @_;
+ bless { subdir => $subdir, cdrom => $cdrom, ftp => $ftp}, $class;
+}
+
+sub add
+{
+ my ($class, $plist, @args) = @_;
+ my $self = $class->new(@args);
+ $plist->addunique($self);
+ return $self;
+}
+
+sub write
+{
+ my ($self, $fh) = @_;
+ print $fh "\@comment subdir=", $self->{subdir},
+ " cdrom=", $self->{cdrom},
+ " ftp=", $self->{ftp}, "\n";
+}
+
+package OpenBSD::PackingElement::PkgDep;
+our @ISA=qw(OpenBSD::PackingElement);
+
+__PACKAGE__->setKeyword('pkgdep');
+sub keyword() { "pkgdep" }
+sub category() { "pkgdep" }
+
+package OpenBSD::PackingElement::PkgConflict;
+our @ISA=qw(OpenBSD::PackingElement);
+
+__PACKAGE__->setKeyword('pkgcfl');
+sub keyword() { "pkgcfl" }
+sub category() { "pkgcfl" }
+
+
+package OpenBSD::PackingElement::NewDepend;
+
+our @ISA=qw(OpenBSD::PackingElement);
+
+__PACKAGE__->setKeyword('newdepend');
+sub category() { "newdepend" }
+
+sub new
+{
+ my ($class, $args) = @_;
+ my ($name, $pattern, $def) = split /\:/, $args;
+ bless { name => $name, pattern => $pattern, def => $def }, $class;
+}
+
+sub write
+{
+ my ($self, $fh) = @_;
+ print $fh "\@newdepend ", $self->{name}, ':',
+ $self->{pattern}, ':', $self->{def}, "\n";
+}
+
+package OpenBSD::PackingElement::LibDepend;
+
+our @ISA=qw(OpenBSD::PackingElement);
+
+__PACKAGE__->setKeyword('libdepend');
+sub category() { "libdepend" }
+
+sub new
+{
+ my ($class, $args) = @_;
+ my ($name, $libspec, $pattern, $def) = split /\:/, $args;
+ bless { name => $name, libspec => $libspec, pattern => $pattern,
+ def => $def }, $class;
+}
+
+sub write
+{
+ my ($self, $fh) = @_;
+ print $fh "\@libdepend ", $self->{name}, ':',
+ $self->{libspec}, ':',
+ $self->{pattern}, ':', $self->{def}, "\n";
+}
+
+package OpenBSD::PackingElement::Unique;
+our @ISA=qw(OpenBSD::PackingElement);
+
+sub add
+{
+ my ($class, $plist, @args) = @_;
+
+ my $self = $class->new(@args);
+ $self->destate($plist->{state});
+ $plist->addunique($self);
+ return $self;
+}
+
+package OpenBSD::PackingElement::Name;
+use File::Spec;
+our @ISA=qw(OpenBSD::PackingElement::Unique OpenBSD::PackingElement);
+
+__PACKAGE__->setKeyword('name');
+sub keyword() { "name" }
+sub category() { "name" }
+
+package OpenBSD::PackingElement::Cwd;
+use File::Spec;
+our @ISA=qw(OpenBSD::PackingElement);
+
+__PACKAGE__->setKeyword('cwd');
+
+sub keyword() { 'cwd' }
+
+sub destate
+{
+ my ($self, $state) = @_;
+ $state->{cwd} = $self->{name};
+}
+
+package OpenBSD::PackingElement::Owner;
+our @ISA=qw(OpenBSD::PackingElement);
+
+__PACKAGE__->setKeyword('owner');
+sub keyword() { 'owner' }
+
+sub destate
+{
+ my ($self, $state) = @_;
+
+ if ($self->{name} eq '') {
+ undef $state->{owner};
+ } else {
+ $state->{owner} = $self->{name};
+ }
+}
+
+package OpenBSD::PackingElement::Group;
+our @ISA=qw(OpenBSD::PackingElement);
+
+__PACKAGE__->setKeyword('group');
+sub keyword() { 'group' }
+
+sub destate
+{
+ my ($self, $state) = @_;
+
+ if ($self->{name} eq '') {
+ undef $state->{group};
+ } else {
+ $state->{group} = $self->{name};
+ }
+}
+
+package OpenBSD::PackingElement::Mode;
+our @ISA=qw(OpenBSD::PackingElement);
+
+__PACKAGE__->setKeyword('mode');
+sub keyword() { 'mode' }
+
+sub destate
+{
+ my ($self, $state) = @_;
+
+ if ($self->{name} eq '') {
+ undef $state->{mode};
+ } else {
+ $state->{mode} = $self->{name};
+ }
+}
+
+package OpenBSD::PackingElement::Exec;
+our @ISA=qw(OpenBSD::PackingElement);
+
+__PACKAGE__->setKeyword('exec');
+
+sub keyword() { "exec" }
+
+sub destate
+{
+ my ($self, $state) = @_;
+ $self->{expanded} = $self->expand($self->{name}, $state);
+}
+
+package OpenBSD::PackingElement::Unexec;
+our @ISA=qw(OpenBSD::PackingElement);
+
+__PACKAGE__->setKeyword('unexec');
+sub keyword() { "unexec" }
+
+sub destate
+{
+ my ($self, $state) = @_;
+ $self->{expanded} = $self->expand($self->{name}, $state);
+}
+
+package OpenBSD::PackingElement::ExtraUnexec;
+our @ISA=qw(OpenBSD::PackingElement);
+
+__PACKAGE__->setKeyword('extraunexec');
+sub keyword() { "extraunexec" }
+
+sub destate
+{
+ my ($self, $state) = @_;
+ $self->{expanded} = $self->expand($self->{name}, $state);
+}
+
+package OpenBSD::PackingElement::DirRm;
+our @ISA=qw(OpenBSD::PackingElement);
+
+__PACKAGE__->setKeyword('dirrm');
+sub keyword() { "dirrm" }
+
+sub destate
+{
+ my ($self, $state) = @_;
+ $self->compute_fullname($state);
+}
+
+package OpenBSD::PackingElement::Extra;
+our @ISA=qw(OpenBSD::PackingElement);
+
+__PACKAGE__->setKeyword('extra');
+sub keyword() { 'extra' }
+
+sub destate
+{
+ my ($self, $state) = @_;
+ $self->compute_fullname($state);
+}
+
+package OpenBSD::PackingElement::SpecialFile;
+our @ISA=qw(OpenBSD::PackingElement::Unique);
+
+sub add_md5
+{
+ my ($self, $md5) = @_;
+ $self->{md5} = $md5;
+}
+
+sub write
+{
+ &OpenBSD::PackingElement::File::write;
+}
+
+package OpenBSD::PackingElement::FCONTENTS;
+our @ISA=qw(OpenBSD::PackingElement::SpecialFile);
+sub category() { OpenBSD::PackageInfo::CONTENTS }
+
+package OpenBSD::PackingElement::FCOMMENT;
+our @ISA=qw(OpenBSD::PackingElement::SpecialFile);
+sub category() { OpenBSD::PackageInfo::COMMENT }
+
+package OpenBSD::PackingElement::FDESC;
+our @ISA=qw(OpenBSD::PackingElement::SpecialFile);
+sub category() { OpenBSD::PackageInfo::DESC }
+
+package OpenBSD::PackingElement::FINSTALL;
+our @ISA=qw(OpenBSD::PackingElement::SpecialFile);
+sub category() { OpenBSD::PackageInfo::INSTALL }
+
+package OpenBSD::PackingElement::FDEINSTALL;
+our @ISA=qw(OpenBSD::PackingElement::SpecialFile);
+sub category() { OpenBSD::PackageInfo::DEINSTALL }
+
+package OpenBSD::PackingElement::FREQUIRE;
+our @ISA=qw(OpenBSD::PackingElement::SpecialFile);
+sub category() { OpenBSD::PackageInfo::REQUIRE }
+
+package OpenBSD::PackingElement::FREQUIRED_BY;
+our @ISA=qw(OpenBSD::PackingElement::SpecialFile);
+sub category() { OpenBSD::PackageInfo::REQUIRED_BY }
+
+package OpenBSD::PackingElement::FDISPLAY;
+our @ISA=qw(OpenBSD::PackingElement::SpecialFile);
+sub category() { OpenBSD::PackageInfo::DISPLAY }
+
+package OpenBSD::PackingElement::FMTREE_DIRS;
+our @ISA=qw(OpenBSD::PackingElement::SpecialFile);
+sub category() { OpenBSD::PackageInfo::MTREE_DIRS }
+
+1;
diff --git a/usr.sbin/pkg_add/OpenBSD/PackingList.pm b/usr.sbin/pkg_add/OpenBSD/PackingList.pm
new file mode 100644
index 00000000000..24b3786a6e9
--- /dev/null
+++ b/usr.sbin/pkg_add/OpenBSD/PackingList.pm
@@ -0,0 +1,142 @@
+# $OpenBSD: PackingList.pm,v 1.1 2003/10/16 17:43:34 espie Exp $
+#
+# Copyright (c) 2003 Marc Espie.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
+# PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+use strict;
+use warnings;
+package OpenBSD::PackingList;
+
+use OpenBSD::PackingElement;
+use OpenBSD::PackageInfo;
+
+sub new
+{
+ my $class = shift;
+ bless {state =>
+ {default_owner=>'root',
+ default_group=>'bin',
+ default_mode=> 0444} }, $class;
+}
+
+sub read
+{
+ my ($a, $fh, $code) = @_;
+ my $plist;
+ if (ref $a) {
+ $plist = $a;
+ } else {
+ $plist = new $a;
+ }
+ while (<$fh>) {
+ next if m/^\s*$/;
+ next if defined $code and !&$code;
+ chomp;
+ OpenBSD::PackingElement::Factory($_, $plist);
+ }
+ return $plist;
+}
+
+sub OpenBSD::PackingList::DirrmOnly
+{
+ m/^\@cwd/ || m/^\@dirrm/ || m/^\@name/;
+}
+
+sub OpenBSD::PackingList::FilesOnly
+{
+ m/^\@cwd/ || m/^\@name/ || !m/^\@/;
+}
+
+sub OpenBSD::PackingList::ConflictOnly
+{
+ m/^\@pkgcfl/ || m/^\@option/ || m/^\@name/;
+}
+
+sub write
+{
+ my ($self, $fh) = @_;
+ $self->{name}->write($fh);
+ if (defined $self->{'no-default-conflict'}) {
+ $self->{'no-default-conflict'}->write($fh);
+ }
+ $self->{extrainfo}->write($fh);
+ for my $listname (qw(pkgcfl pkgdep newdepend libdepend items)) {
+ if (defined $self->{$listname}) {
+ for my $item (@{$self->{$listname}}) {
+ $item->write($fh);
+ }
+ }
+ }
+ for my $special (OpenBSD::PackageInfo::info_names()) {
+ $self->{$special}->write($fh) if defined $self->{$special};
+ }
+}
+
+sub fromfile
+{
+ my ($a, $fname, $code) = @_;
+ open(my $fh, '<', $fname) or return undef;
+ my $plist = $a->read($fh, $code);
+ close($fh);
+ return $plist;
+}
+
+sub tofile
+{
+ my ($self, $fname) = @_;
+ open(my $fh, '>', $fname) or return undef;
+ $self->write($fh);
+ close($fh) or return undef;
+ return 1;
+}
+
+sub add2list
+{
+ my ($plist, $object) = @_;
+ my $category = $object->category();
+ $plist->{$category} = [] unless defined $plist->{$category};
+ push @{$plist->{$category}}, $object;
+}
+
+sub addunique
+{
+ my ($plist, $object) = @_;
+ my $category = $object->category();
+ if (defined $plist->{$category}) {
+ die "Duplicate $category in plist\n";
+ }
+ $plist->{$category} = $object;
+}
+
+sub pkgname($)
+{
+ my $self = shift;
+ return $self->{name}->{name};
+}
+
+# allows the autoloader to work correctly
+sub DESTROY
+{
+}
+
+1;
diff --git a/usr.sbin/pkg_add/OpenBSD/PkgCfl.pm b/usr.sbin/pkg_add/OpenBSD/PkgCfl.pm
new file mode 100644
index 00000000000..a101e635b0f
--- /dev/null
+++ b/usr.sbin/pkg_add/OpenBSD/PkgCfl.pm
@@ -0,0 +1,68 @@
+# $OpenBSD: PkgCfl.pm,v 1.1 2003/10/16 17:43:34 espie Exp $
+#
+# Copyright (c) 2003 Marc Espie.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
+# PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+use strict;
+use warnings;
+package OpenBSD::PkgCfl;
+
+sub glob2re
+{
+ local $_ = shift;
+ s/\./\\\./g;
+ s/\+/\\\+/g;
+ s/\*/\.\*/g;
+ s/\?/\./g;
+ return "^$_\$";
+}
+
+sub make_conflict_list($)
+{
+ my ($class, $plist) = @_;
+ my $l = [];
+
+ unless (defined $plist->{'no-default-conflict'}) {
+ my $stem = (OpenBSD::PackageName::splitname$plist->pkgname())[0];
+ push(@$l, "^\Q$stem\E-\\d.*\$");
+ }
+ if (defined $plist->{pkgcfl}) {
+ for my $cfl (@{$plist->{pkgcfl}}) {
+ push(@$l, glob2re($cfl->{name}));
+ }
+ }
+ bless $l, $class;
+}
+
+sub conflicts_with
+{
+ my ($self, @pkgnames) = @_;
+ for my $cfl (@$self) {
+ if (grep { m/$cfl/ } @pkgnames) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+1;
diff --git a/usr.sbin/pkg_add/OpenBSD/RequiredBy.pm b/usr.sbin/pkg_add/OpenBSD/RequiredBy.pm
new file mode 100644
index 00000000000..0ac99cbd5f1
--- /dev/null
+++ b/usr.sbin/pkg_add/OpenBSD/RequiredBy.pm
@@ -0,0 +1,81 @@
+# ex:ts=8 sw=4:
+# $OpenBSD: RequiredBy.pm,v 1.1 2003/10/16 17:43:34 espie Exp $
+#
+# Copyright (c) 2003 Marc Espie.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
+# PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package OpenBSD::RequiredBy;
+use strict;
+use warnings;
+use OpenBSD::PackageInfo;
+
+sub new
+{
+ my ($class, $pkgname) = @_;
+ my $f = installed_info($pkgname).REQUIRED_BY;
+ bless \$f, $class;
+}
+
+sub list($)
+{
+ my $self = shift;
+
+ my $l = [];
+ return $l unless -f $$self;
+ open(my $fh, '<', $$self) or
+ die "Problem opening required list: $$self\n";
+ local $_;
+ while(<$fh>) {
+ chomp $_;
+ s/\s+$//;
+ next if /^$/;
+ push(@$l, $_);
+ }
+ close($fh);
+ return $l;
+}
+
+sub delete
+{
+ my ($self, $pkgname) = @_;
+ my @lines = grep { $_ ne $pkgname } @{$self->list()};
+ unlink($$self) or die "Can't erase $$self";
+ if (@lines > 0) {
+ $self->add(@lines);
+ }
+}
+
+sub add
+{
+ my ($self, @pkgnames) = @_;
+ open(my $fh, '>>', $$self) or
+ die "Can't add dependencies to $$self";
+ print $fh join("\n", @pkgnames), "\n";
+ close($fh);
+}
+
+sub DESTROY
+{
+}
+
+1;
diff --git a/usr.sbin/pkg_add/OpenBSD/Temp.pm b/usr.sbin/pkg_add/OpenBSD/Temp.pm
new file mode 100644
index 00000000000..8acd7c6bda0
--- /dev/null
+++ b/usr.sbin/pkg_add/OpenBSD/Temp.pm
@@ -0,0 +1,44 @@
+use strict;
+# $OpenBSD: Temp.pm,v 1.1 2003/10/16 17:43:34 espie Exp $
+#
+# Copyright (c) 2003 Marc Espie.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
+# PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+use warnings;
+package OpenBSD::Temp;
+
+use File::Temp;
+my $tempbase = $ENV{'PKG_TMPDIR'} || '/var/tmp';
+
+sub dir()
+{
+ return File::Temp::tempdir("pkginfo.XXXXXXXXXXX", DIR => $tempbase,
+ CLEANUP => 1).'/';
+}
+
+sub list($)
+{
+ return File::Temp::tempfile("list.XXXXXXXXXXX", DIR => shift);
+}
+
+1;
diff --git a/usr.sbin/pkg_add/OpenBSD/Ustar.pm b/usr.sbin/pkg_add/OpenBSD/Ustar.pm
new file mode 100644
index 00000000000..59c0365e946
--- /dev/null
+++ b/usr.sbin/pkg_add/OpenBSD/Ustar.pm
@@ -0,0 +1,278 @@
+# $OpenBSD: Ustar.pm,v 1.1 2003/10/16 17:43:34 espie Exp $
+#
+# Copyright (c) 2002 Marc Espie.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
+# PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Handle utar archives
+
+# Prototype of new pkg* implementation, tar module.
+# Interface is likely to change A LOT in the near future...
+
+use strict;
+use warnings;
+package OpenBSD::Ustar;
+# helps autoloader
+sub DESTROY
+{
+}
+
+use constant FILE => "\0";
+use constant FILE1 => '0';
+use constant HARDLINK => '1';
+use constant SOFTLINK => '2';
+use constant CHARDEVICE => '3';
+use constant BLOCKDEVICE => '4';
+use constant DIR => '5';
+use constant FIFO => '6';
+use constant CONTFILE => '7';
+use File::Path ();
+use File::Basename ();
+
+my $uidcache = {};
+my $gidcache = {};
+my $buffsize = 2 * 1024 * 1024;
+
+sub new
+{
+ my ($class, $fh) = @_;
+
+ return bless { fh => $fh, swallow => 0, unput => 0} , $class;
+}
+
+
+sub name2uid
+{
+ my $name = shift;
+ return $uidcache->{$name} if defined $uidcache->{$name};
+ my @entry = getpwnam($name);
+ if (@entry == 0) {
+ return $uidcache->{$name} = shift;
+ } else {
+ return $uidcache->{$name} = $entry[2];
+ }
+}
+
+sub name2gid
+{
+ my $name = shift;
+ return $gidcache->{$name} if defined $gidcache->{$name};
+ my @entry = getgrnam($name);
+ if (@entry == 0) {
+ return $gidcache->{$name} = shift;
+ } else {
+ return $gidcache->{$name} = $entry[2];
+ }
+}
+
+sub skip
+{
+ my $self = shift;
+ return if $self->{swallow} == 0;
+
+ my $temp;
+ while ($self->{swallow} > $buffsize) {
+ read($self->{fh}, $temp, $buffsize);
+ $self->{swallow} -= $buffsize;
+ }
+ read($self->{fh}, $temp, $self->{swallow});
+ $self->{swallow} = 0;
+}
+
+sub unput
+{
+ my $self = shift;
+ $self->{unput} = 1;
+}
+
+sub next
+{
+ my $self = shift;
+ if ($self->{unput}) {
+ $self->{unput} = 0;
+ return $self->{current};
+ }
+ # get rid of the current object
+ $self->skip();
+ my $header;
+ my $n = read $self->{fh}, $header, 512;
+ return undef if $n == 0;
+ die "Error while reading header"
+ unless defined $n and $n == 512;
+ if ($header eq "\0"x512) {
+ return $self->next();
+ }
+ # decode header
+ my ($name, $mode, $uid, $gid, $size, $mtime, $chksum, $type,
+ $linkname, $magic, $version, $uname, $gname, $major, $minor,
+ $prefix) = unpack('a100a8a8a8a12a12a8aa100a6a2a32a32a8a8a155', $header);
+ if ($magic ne "ustar\0" || $version ne '00') {
+ die "Not an ustar archive header";
+ }
+ # verify checksum
+ my $value = $header;
+ substr($value, 148, 8) = " "x8;
+ my $ck2 = unpack("%C*", $value);
+ if ($ck2 != oct($chksum)) {
+ die "Bad archive checksum";
+ }
+ $name =~ s/\0*$//;
+ $mode = oct($mode) & 0xfff;
+ $uname =~ s/\0*$//;
+ $gname =~ s/\0*$//;
+ $uid = oct($uid);
+ $gid = oct($gid);
+ $uid = name2uid($uname, $uid);
+ $gid = name2gid($uname, $gid);
+ $mtime = oct($mtime);
+ unless ($prefix =~ m/^\0/) {
+ $prefix =~ s/\0*$//;
+ $name = "$prefix/$name";
+ }
+
+ $size = oct($size);
+ my $result= {
+ name => $name,
+ mode => $mode,
+ mtime=> $mtime,
+ linkname=> $linkname,
+ uname => $uname,
+ uid => $uid,
+ gname => $gname,
+ gid => $gid,
+ size => $size,
+ archive => $self
+ };
+ # adjust swallow
+ $self->{swallow} = $size;
+ if ($size % 512) {
+ $self->{swallow} += 512 - $size % 512;
+ }
+ if ($type eq DIR) {
+ bless $result, 'OpenBSD::Ustar::Dir';
+ } elsif ($type eq HARDLINK) {
+ bless $result, 'OpenBSD::Ustar::HardLink';
+ } elsif ($type eq SOFTLINK) {
+ bless $result, 'OpenBSD::Ustar::SoftLink';
+ } elsif ($type eq FILE || $type eq FILE1) {
+ bless $result, 'OpenBSD::Ustar::File';
+ } else {
+ die "Unsupported type";
+ }
+ $self->{current} = $result;
+ return $result;
+}
+
+package OpenBSD::Ustar::Object;
+sub set_modes
+{
+ my $self = shift;
+ chmod $self->{mode}, $self->{name};
+ chown $self->{uid}, $self->{gid}, $self->{name};
+}
+
+sub make_basedir
+{
+ my $self = shift;
+ my $dir = File::Basename::dirname($self->{name});
+ File::Path::mkpath($dir) unless -d $dir;
+}
+
+sub isDir() { 0 }
+sub isFile() { 0 }
+sub isLink() { 0 }
+sub isSymLink() { 0 }
+sub isHardLink() { 0 }
+
+package OpenBSD::Ustar::Dir;
+our @ISA=qw(OpenBSD::Ustar::Object);
+
+sub create
+{
+ my $self = shift;
+ File::Path::mkpath($self->{name});
+ $self->SUPER::set_modes();
+}
+
+sub isDir() { 1 }
+
+package OpenBSD::Ustar::HardLink;
+our @ISA=qw(OpenBSD::Ustar::Object);
+
+sub create
+{
+ my $self = shift;
+ $self->make_basedir($self->{name});
+ if (defined $self->{cwd}) {
+ link $self->{cwd}."/".$self->{linkname}, $self->{name};
+ } else {
+ link $self->{linkname}, $self->{name};
+ }
+}
+
+sub isLink() { 1 }
+sub isHardLink() { 1 }
+
+package OpenBSD::Ustar::SoftLink;
+our @ISA=qw(OpenBSD::Ustar::Object);
+
+sub create
+{
+ my $self = shift;
+ $self->make_basedir($self->{name});
+ symlink $self->{linkname}, $self->{name};
+}
+
+sub isLink() { 1 }
+sub isHardLink() { 1 }
+
+package OpenBSD::Ustar::File;
+our @ISA=qw(OpenBSD::Ustar::Object);
+
+use IO::File;
+
+sub create
+{
+ my $self = shift;
+ $self->make_basedir($self->{name});
+ my $out = new IO::File $self->{name}, "w";
+ if (!defined $out) {
+ print "Can't write to ", $self->{name}, "\n";
+ return;
+ }
+ $self->SUPER::set_modes();
+ my $buffer;
+ my $toread = $self->{size};
+ while ($toread > 0) {
+ my $maxread = $buffsize;
+ $maxread = $toread if $maxread > $toread;
+ read($self->{archive}->{fh}, $buffer, $maxread);
+ $self->{archive}->{swallow} -= $maxread;
+ print $out $buffer;
+ $toread -= $maxread;
+ }
+ $out->close();
+}
+
+sub isFile() { 1 }
+
+1;
diff --git a/usr.sbin/pkg_add/OpenBSD/md5.pm b/usr.sbin/pkg_add/OpenBSD/md5.pm
new file mode 100644
index 00000000000..478d735e5b1
--- /dev/null
+++ b/usr.sbin/pkg_add/OpenBSD/md5.pm
@@ -0,0 +1,43 @@
+# $OpenBSD: md5.pm,v 1.1 2003/10/16 17:43:34 espie Exp $
+#
+# Copyright (c) 2003 Marc Espie.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD
+# PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+use strict;
+use warnings;
+
+package OpenBSD::md5;
+use Digest::MD5;
+
+sub fromfile
+{
+ my $fname = shift;
+ die "No such file: \"$fname\"\n" unless -f $fname;
+ open(my $file, '<', $fname) or return;
+ my $md5 = new Digest::MD5;
+
+ $md5->addfile($file);
+ close($file);
+ return $md5->hexdigest();
+}
+1;