Another way to do this is to download demo versions of one of the Supertars
Path: border2.nntp.dca.giganews.com!nntp.giganews.com!peer01.cox.net!cox.net!antonio.escomposlinux.org!cernicalo.escomposlinux.org!escomposlinux.org!not-for-mail From: "David Serrano (Hue-Bond)" <responder_solo_en_el_grupo@yahoo.es> Newsgroups: comp.os.linux.misc,comp.unix.admin,comp.unix.shell Subject: Re: rescue damaged tar file Date: Thu, 2 Feb 2006 22:47:50 +0000 (UTC) Organization: I work for myself Lines: 153 Message-ID: <slrndu530m.1ss.responder_solo_en_el_grupo@genus.hue-bond.info> References: <u64pdnebu.fsf@trollope.org> NNTP-Posting-Host: 127.red-83-32-93.dynamicip.rima-tde.net X-Trace: cormoran.emeteo.local 1138920470 17678 83.32.93.127 (2 Feb 2006 22:47:50 GMT) X-Complaints-To: emeteo@escomposlinux.org NNTP-Posting-Date: Thu, 2 Feb 2006 22:47:50 +0000 (UTC) X-Message-Flag: Visit http://www.debian.org/ X-MSMail-Priority: High Mail-Copies-To: nobody User-Agent: slrn/0.9.8.1pl1 (Debian) Xref: number1.nntp.dca.giganews.com comp.os.linux.misc:628563 comp.unix.admin:120514 comp.unix.shell:178379 Michael Powe, dom20051225@20:53:25(CET): > Maybe I'm a bit late but anyway...
> This archive has bad data about 1/3 to 1/2 way through it. I'm trying > to find a way to get at the data below the damaged part. > I used the gzip recovery kit to unpack the file. This worked and gave > me the 2.5 GB uncompressed file. However, tar will only unpack up to > the damaged part, and even with --ignore-failed-read, blows up. I was once in the same problem and found a Perl script in the web that made my day. Let's reproduce a session: $ tar cf bin.tar /bin/ tar: Removing leading `/' from member names tar: Removing leading `/' from hard link targets $ ll bin.tar -rw------- 1 hue hue 2836480 20060202:233334+0100 bin.tar $ dd if=/dev/urandom of=bin.tar bs=1k seek=1k count=300 conv=notrunc 300+0 records in 300+0 records out 307200 bytes (307 kB) copied, 0,101178 seconds, 3,0 MB/s $ tar tf bin.tar bin/ bin/bash bin/rbash bin/sh bin/cat bin/chgrp bin/chmod bin/chown bin/cp bin/date bin/dd bin/df bin/dir tar: Skipping to next header tar: Archive contains obsolescent base-64 headers tar: Error exit delayed from previous errors $ perl ~hue/lang/perl/find_tar_headers.pl bin.tar bin.tar:0:bin/:0 bin.tar:512:bin/bash:2467624 bin.tar:685056:bin/rbash:0 bin.tar:685568:bin/sh:0 bin.tar:686080:bin/cat:40550 bin.tar:703488:bin/chgrp:100664 bin.tar:737280:bin/chmod:73560 bin.tar:768512:bin/chown:105250 bin.tar:804864:bin/cp:153524 bin.tar:860672:bin/date:126274 bin.tar:905728:bin/dd:113410 bin.tar:945152:bin/df:103344 bin.tar:980480:bin/dir:226110 bin.tar:1368064:bin/vdir:226110 bin.tar:1445888:bin/sleep:33104 bin.tar:1460736:bin/stty:110140 [...] $ _ We can see that the offset of the next tar header is that of vdir, at 1368064. In order to make dd fast, we obtain offset in Kb:
$ bc
[...]
scale=4
1368064/1024
1336.0000
$ dd if=bin.tar of=bin-tail.tar bs=1k skip=1336
1434+0 records in
1434+0 records out
1468416 bytes (1,5 MB) copied, 0,017176 seconds, 85,5 MB/s
$ file bin-tail.tar
bin-tail.tar: POSIX tar archive
$ tar xf bin.tar
tar: Skipping to next header
tar: Archive contains obsolescent base-64 headers
tar: Error exit delayed from previous errors
$ tar xf bin-tail.tar
$ rm -f bin/dir ## probably corrupted
And now we have everything recoverable:
$ ls bin|wc -l
83
$ ls /bin/|wc -l
95
$ _
This is find_tar_headers.pl:
-----------------------------
#!/usr/bin/perl -w
use strict;
# 99.9% of all credits for this script go
# to Tore Skjellnes <torsk@elkraft.ntnu.no>
# who is the originator.
my $tarfile;
my $c;
my $hit;
my $header;
# if you don't get any results, outcomment the line below and
# decomment the line below the it and retry
my @src = (ord('u'),ord('s'),ord('t'),ord('a'),ord('r'),ord(" "), ord(" "),0);
#my @src = (ord('u'),ord('s'),ord('t'),ord('a'),ord('r'),0,ord('0'),ord('0'));
die "No tar file given on command line" if $#ARGV != 0;
$tarfile = $ARGV[0];
open(IN,$tarfile) or die "Could not open `$tarfile': $!";
$hit = 0;
$| = 1;
seek(IN,257,0) or die "Could not seek forward 257 characters in `$tarfile': $!";
while (read(IN,$c,1) == 1)
{
($hit = 0, next) unless (ord($c) == $src[$hit]);
$hit = $hit + 1;
( print "hit: $hit", next ) unless $hit > $#src;
# we have a probable header at (pos - 265)!
my $pos = tell(IN) - 265;
seek(IN,$pos,0)
or (warn "Could not seek to position $pos in `$tarfile': $!", next);
(read(IN,$header,512) == 512)
or (warn "Could not read 512 byte header at position $pos in `$tarfile': $!", seek(IN,$pos+265,0),next);
my ($name, $mode, $uid, $gid, $size, $mtime, $chksum, $typeflag,
$linkname, $magic, $version, $uname, $gname,
$devmajor, $devminor, $prefix)
= unpack ("Z100a8a8a8Z12a12a8a1a100a6a2a32a32a8a8Z155", $header);
$size = int $size;
printf("%s:%s:%s:%s\n",$tarfile,$pos,$name,$size);
$hit = 0;
}
close(IN) or warn "Error closing `$tarfile': $!";
-----------------------------
Good luck.
--
David Serrano
------------------------
Comments are closed for this page. If you have something very important to add, contact me by email.