#! /usr/local/bin/perl

if(($#ARGV < 0 && -t STDIN) || $#ARGV > 0) {
	print STDERR "Usage: $0  [tarfile]  > newtarfile
Edits headers in a tar package, ensuring that all files are
writable by the owner.
";
	exit(1);
}

if($#ARGV == 0) {
    die "Can't open $ARGV[0], giving up" unless open(STDIN, $ARGV[0]);
}

$TBLOCK = 512;

$modeat = 100;
sub getheader {
	return undef unless read(STDIN, $block, $TBLOCK) == $TBLOCK;
	$mode = substr($block, $modeat, 8);
	return undef if $mode eq ("\0" x 8);
	$mode = oct($mode);
	return $mode;
}

$lenat = 100+8+8+8;
sub passfile {
	$length = oct(substr($block, $lenat, 12));
	print $block;
	$nblocks = int(($length + $TBLOCK - 1) / $TBLOCK);
	while($nblocks-- > 0 && read(STDIN, $_, $TBLOCK) == $TBLOCK) {
		print $_;
	}
	die "Unexpected end-of-file, quitting" if $nblocks > 0;
}

$ckat = 100+8+8+8+12+12;
sub cksum {
	# Patch $block to have correct checksum.
	# Checksum's offset is 100+8+8+8+12+12
	substr($block, $ckat, 8) = ' 'x8;
	$cksum = unpack("%8C*", $block);
	substr($block, $ckat, 8) = sprintf("%06o%c ", $cksum, 0);
}

while(&getheader) {
	if(! ($mode & 0200)) {
	    $cksum = oct(substr($block, $ckat, 6));
	    substr($block, $modeat+3, 1) =~ tr/0145/2367/;
	    $cksum += 2;
	    substr($block, $ckat, 6)  = sprintf("%06o", $cksum);
	}
	&passfile;
}

print "\0" x (2*$TBLOCK);
