#
# this program converts tar formats from old par to ustar on the fly.
# old tar is read from stdin and then, in ustar format, written to
# stdout.
#
# author: Dmitri
#
# $Id: tar2ustar,v 1.2 2001/03/15 13:19:39 dmitri Exp $
#
# $Log: tar2ustar,v $
# Revision 1.2 2001/03/15 13:19:39 dmitri
# Little clean-up.
#
# Revision 1.1 2001/03/14 17:33:53 dmitri
# Filter to conver tar archives from old format to the ustar format
# (POSIX 1003.1).
#
use integer;
use strict;
my $block;
my $blocksize = 512;
my $blknum = 0;
my @tar_field = (100, 8, 8, 8, 12, 12, 8, 1, 100);
my @tar_name = ('name', 'mode', 'uid', 'gid', 'size', 'mtime', 'chksum
+',
'link', 'linkname');
sub checksum {
my ($block) = @_;
my $chksum = 0;
substr $block, 148, 8, ' ';
for (split '', $block) { $chksum += ord }
$chksum = sprintf("%o%c ", $chksum, 0);
$chksum = ' 'x(8 - length($chksum)) . $chksum;
substr $block, 148, 8, $chksum;
return $block;
}
sub parse_block {
my ($block, $filename, $prefix) = @_;
my %tar;
my $off = 0;
for (my $i = 0; $i < scalar @tar_field; ++$i) {
($tar{$tar_name[$i]} = substr $block, $off, $tar_field
+[$i]) =~
s/\000//g;
$off += $tar_field[$i];
}
# this condition probably only applies at the end, where there
+'s a
# trailer (don't feel like detecting it).
++$blknum && return $block unless $tar{name};
if ($tar{'name'} =~ m|^\./\./\@LongLink| && $tar{'link'} eq "L
+") {
read(STDIN, $block, $blocksize);
$block =~ s/\000.*$//;
print STDERR $block, "\n";
my ($filename, $prefix, $index);
$index = index $block, "/", length($block) - 100;
$filename = substr $block, $index + 1;
$prefix = substr $block, 0, $index;
read(STDIN, $block, $blocksize);
return parse_block($block, $filename, $prefix);
}
if ($filename && $prefix) {
substr $block, 0, 100, sprintf("%c", 0) x 100;
substr $block, 0, length $filename, $filename;
substr $block, 345, length $prefix, $prefix;
}
# mode
substr $block, 100, 7, " ";
substr $block, 101, length $tar{'mode'}, $tar{'mode'};
substr $block, 108, 7, " 0 "; # uid
substr $block, 116, 7, " 0 "; # gid
# size
$tar{'size'} =~ s/^0+//;
substr $block, 124, 12, " ";
substr $block,
135 - length $tar{'size'},
length $tar{'size'},
$tar{'size'};
# mtime
$tar{'mtime'} =~ s/^0+//;
substr $block, 136, 12, " ";
substr $block,
147 - length $tar{'mtime'},
length $tar{'mtime'},
$tar{'mtime'};
substr $block, 257, 5, "ustar"; # magic
substr $block, 329, 7, " 0 "; # devmajor
substr $block, 337, 7, " 0 "; # devminor
if (oct $tar{'size'} != 0) {
$blknum += (oct $tar{'size'}) / $blocksize;
++$blknum if (oct $tar{'size'}) % $blocksize;
}
++$blknum;
return checksum $block;
}
for (my $i = 0; read(STDIN, $block, $blocksize); ++$i) {
if ($blknum == $i) {
# if header block, convert.
print parse_block $block;
} else {
print $block;
}
}
|