summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/pkg_add/OpenBSD/Ustar.pm120
1 files changed, 97 insertions, 23 deletions
diff --git a/usr.sbin/pkg_add/OpenBSD/Ustar.pm b/usr.sbin/pkg_add/OpenBSD/Ustar.pm
index 628e61bc97f..9621c652364 100644
--- a/usr.sbin/pkg_add/OpenBSD/Ustar.pm
+++ b/usr.sbin/pkg_add/OpenBSD/Ustar.pm
@@ -1,5 +1,5 @@
# ex:ts=8 sw=4:
-# $OpenBSD: Ustar.pm,v 1.14 2004/12/13 18:50:23 espie Exp $
+# $OpenBSD: Ustar.pm,v 1.15 2004/12/26 15:18:51 espie Exp $
#
# Copyright (c) 2002-2004 Marc Espie <espie@openbsd.org>
#
@@ -21,16 +21,19 @@ use strict;
use warnings;
package OpenBSD::Ustar;
-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 constant USTAR_HEADER => 'a100a8a8a8a12a12a8aa100a6a2a32a32a8a8a155';
+use constant {
+ FILE => "\0",
+ FILE1 => '0',
+ HARDLINK => '1',
+ SOFTLINK => '2',
+ CHARDEVICE => '3',
+ BLOCKDEVICE => '4',
+ DIR => '5',
+ FIFO => '6',
+ CONTFILE => '7',
+ USTAR_HEADER => 'a100a8a8a8a12a12a8aa100a6a2a32a32a8a8a155',
+};
+
use File::Path ();
use File::Basename ();
use OpenBSD::IdCache;
@@ -140,6 +143,44 @@ sub next
return $result;
}
+sub mkheader
+{
+ my ($entry, $type) = @_;
+ my ($name, $prefix);
+ if (length($name) < 100) {
+ $prefix = '';
+ } elsif (length($name) > 255) {
+ die "Can't fit such a name $name\n";
+ } elsif ($name =~ m|^(.*)/(.{,100})$|) {
+ $prefix = $1;
+ $name = $2;
+ } else {
+ die "Can't fit such a name $name\n";
+ }
+ my $header;
+ my $cksum = ' 'x8;
+ for (1 .. 2) {
+ $header = pack(USTAR_HEADER,
+ $name,
+ sprintf("%o", $entry->{mode}),
+ sprintf("%o", $entry->{uid}),
+ sprintf("%o", $entry->{gid}),
+ sprintf("%o", $entry->{size}),
+ sprintf("%o", $entry->{mtime}),
+ $cksum,
+ $type,
+ $entry->{linkname},
+ 'ustar', '00',
+ $entry->{uname},
+ $entry->{gname},
+ '0', '0',
+ $prefix);
+ $cksum = unpack("%C*", $header);
+ }
+ return $header;
+}
+
+
package OpenBSD::Ustar::Object;
sub set_modes
{
@@ -206,19 +247,34 @@ sub create
sub isLink() { 1 }
sub isSymLink() { 1 }
-package OpenBSD::Ustar::File;
-our @ISA=qw(OpenBSD::Ustar::Object);
+package OpenBSD::CompactWriter;
-my $bs;
-my $zeroes;
-sub print_compact
+use constant {
+ FH => 0,
+ BS => 1,
+ ZEROES => 2,
+ UNFINISHED => 3,
+};
+
+sub new
{
- my ($fh, $buffer) = @_;
- my $newbs = (stat $fh)[11];
- if (!defined $bs or $newbs != $bs) {
- $bs = $newbs;
+ my ($class, $fname) = @_;
+ open (my $out, '>', $fname);
+ if (!defined $out) {
+ return undef;
+ }
+ my $bs = (stat $out)[11];
+ my $zeroes;
+ if (defined $bs) {
$zeroes = "\x00"x$bs;
}
+ bless [ $out, $bs, $zeroes, 0 ], $class;
+}
+
+sub write
+{
+ my ($self, $buffer) = @_;
+ my ($fh, $bs, $zeroes, $e) = @$self;
START:
if (defined $bs) {
for (my $i = 0; $i + $bs <= length($buffer); $i+= $bs) {
@@ -233,23 +289,41 @@ START:
defined(sysseek($fh, $seek_forward, 1))
or return 0;
$buffer = substr($buffer, $i);
+ if (length $buffer == 0) {
+ $self->[UNFINISHED] = 1;
+ return 1;
+ }
goto START;
}
}
}
+ $self->[UNFINISHED] = 0;
defined(syswrite($fh, $buffer)) or return 0;
return 1;
}
+sub close
+{
+ my ($self) = @_;
+ if ($self->[UNFINISHED]) {
+ defined(sysseek($self->[FH], -1, 1)) or return 0;
+ defined(syswrite($self->[FH], "\0")) or return 0;
+ }
+ return 1;
+}
+
+package OpenBSD::Ustar::File;
+our @ISA=qw(OpenBSD::Ustar::Object);
+
sub create
{
my $self = shift;
$self->make_basedir($self->{name});
- open (my $out, '>', $self->{destdir}.$self->{name});
+ my $buffer;
+ my $out = OpenBSD::CompactWriter->new($self->{destdir}.$self->{name});
if (!defined $out) {
die "Can't write to $self->{destdir}$self->{name}: $!";
}
- my $buffer;
my $toread = $self->{size};
while ($toread > 0) {
my $maxread = $buffsize;
@@ -258,7 +332,7 @@ sub create
die "Error reading from archive: $!";
}
$self->{archive}->{swallow} -= $maxread;
- unless (print_compact($out, $buffer)) {
+ unless ($out->write($buffer)) {
die "Error writing to $self->{destdir}$self->{name}: $!";
}