#
# 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;
}
}
In reply to tar2ustar
by dmitri
Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
Read Where should I post X? if you're not absolutely sure you're posting in the right place.
Please read these before you post! —
Posts may use any of the Perl Monks Approved HTML tags:
- a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
| |
For: |
|
Use: |
| & | | & |
| < | | < |
| > | | > |
| [ | | [ |
| ] | | ] |
Link using PerlMonks shortcuts! What shortcuts can I use for linking?
See Writeup Formatting Tips and other pages linked from there for more info.