Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Cdrom data recovery script

by bitshiftleft (Sexton)
on Oct 29, 2007 at 04:55 UTC ( [id://647787]=sourcecode: print w/replies, xml ) Need Help??
Category: Utility Scripts
Author/Contact Info
Description: If you are something of a code collector(like code off this website), you are probably putting it on CD's. Under Win32 everytime you drag files to the CD window you create a new session on it, and doing so that new seesion is supposed to copy the session before it. As it happens it doesn't do it reliably. Have you ever noticed dissapearing files you swore you put on it ? They are still there in the previous sessions. You only get to view the last session with the Windows Explorer. I bought a used copy of Kaspersky's book($5 with CD) "CD Cracking Uncovered". I used two utilities from it to recover two of my CD's. The last chapter deals with CD recovery . These utilities read the CD at the raw sector level. The script below uses the SPTI interface(Admin) , but can easily be changed to the ASPI interface(non-Admin). Yes, there are utilities out there you can buy, but when you realize that recovery is an art(one size does not fit all), its nice to have a freebie you can modify to your own needs that comes with source code.
#  ---- iso9660recover.pl - Win32 version 
# Written by bitshiftleft for perlmonks.org
# Automate recovery of an entire data cdrom
# using Kris Kaspersky's RAW_TOC_READ.exe and ISO9660.dir.exe utility.
# Written for personal use and to answer the challenge on page 399 of 
+the
# book "CD Cracking Uncovered", ISBN:1-931769-33-8 
# BUGS: 1)Some recovered files belong to to parent directory - might c
+ross ref Joliet with iso9660 to verify 
#       2)Extra character on subdirectory names 
# ------- -----
use File::Path;

my @TOC;
my @TOCJoliet;
my $NS =0;
my %fileexists;
open(RAW_TOC,"RAW_TOC_READ.exe \\\\.\\D: 0|") || die "RAW_TOC_READ.exe
+ $!";
@TOC = <RAW_TOC>;
close RAW_TOC;
for ($i = 0; $i < 2; ++$i){ shift @TOC }; # trim header info
print " ------ TOC ------\n";
print @TOC;
foreach $session (@TOC){
 last if $session eq "\n";
 (undef, undef, $track,undef,$LBA1,$LBA2,$LBA3,$LBA4)=split(" ",$sessi
+on);
 $StartLBA = hex($LBA1 .$LBA2 . $LBA3 .$LBA4);
 chomp $StartLBA;
 printf "Reading track %02X",hex($track);
 open(ISODIR,"ISO9660.dir.exe \\\\.\\D: $StartLBA -Joliet|") || die "I
+SO9660.dir.exe $StartLBA -Joliet \n$!";
 my @filenames = <ISODIR>;
 for ($i = 0; $i < 6; ++$i){$l = shift @filenames; if ($l =~ /NOT/){ $
+NS = 1;} }; # trim header info
 push @TOCJoliet, \@filenames; 
 close ISODIR;
 print " Dirs/Files found: ",scalar(@filenames),":$NS\n";
 if($NS){$NS = 0;};
# print @filenames; 
# last if hex($track) == 3; for debugging this code
}
print "Retreiving files and directories....\n\n";

#   ------- first reconstruct the directory tree --- 
foreach $index (0 .. $#TOCJoliet){
 my @files = @{$TOCJoliet[$index]};
 next if $#files == -1; 
 foreach $ii (0 .. $#files){
   ($lba1,$size1,$name1 ) = split(" ", $files[$ii]);
   $name1 = substr ($files[$ii],22);  # in case there are spaces in th
+e subdir name
   chomp $name1;
  if ($ii == 0){
   ($lba2,$size2,$name2 ) = split(" ", $files[$ii+1]);
   $name2 = substr ($files[$ii+1],22);  # in case there are spaces in 
+the subdir name
   chomp $name2;
   if ($lba1 == $lba2  && $name1 eq '.' && $name2 eq '..'){$dirtree{$l
+ba1} = 'root/'};
   $activedir = $dirtree{$lba1}; 
   if (! -d "$activedir"){mkpath($activedir,0,0777) ;}
  }
   next if ($name1 eq '.' or $name1 eq '..');
  ($lba2,$size2,$name2 ) = split(" ", $files[$ii+1]);
  $name2 = substr ($files[$ii+1],22,);  # in case there are spaces in 
+the subdir name
  chomp $name2;
  if($name2 eq '.') { # ----- we have a subdirectory
   ($lba3,$size3,$name3 ) = split(" ", $files[$ii+2]); # get parent di
+r
# ---- now remove filename special characters, - needed for wprintf bu
+g ----
    $name1 =~ s/(\=|\/|\[|\]|\"|\:|\;|\,|\?|\*|\<|\>|\|)$//g; 
    $dirtree{$lba1} = $dirtree{$lba3} . $name1 . '/';
    $activedir = $dirtree{$lba1};
    if (! -d "$activedir"){ mkpath("$activedir",0,0777) ;}
    substr $files[$ii],22,0,$dirtree{$lba3}    
  } else { # ----- we have a file
    substr $files[$ii],22,0,$activedir;     # prepend full path
    $files[$ii] =~ s/\;.*$//;               # trim the filename ending
+s
  }
 }
 push @cddirtree, \@files;
# print  @files; 
}

@TOCJoliet = ();  # memory management - cleanup

foreach $index (0 .. $#cddirtree){
#    next unless $index > 0x26;
    my @files = @{$cddirtree[$index]};
 foreach $ii (0 .. $#files){  
    ($lba1,$size1,$name1 ) = split(" ", $files[$ii]);
    ($lba2,$size2,$name2 ) = split(" ", $files[$ii+1]);
    next if $name2 eq '|.';
    next if ($name1 eq '|.' or $name1 eq '|..');
    $f = substr ($files[$ii],22);
    chomp $f;
    $size = substr($size1,1);
    if (! exists($filexists{$lba1})){  # no need to recover same file 
+from previous session
     ++$filexists{$lba1};
     print "Recovering: \"$f\" \n";
     # might need line continuations here very for long command lines 
+(xargs for windows?)
     system("ISO9660.dir.exe \\\\.\\D: \"$f\" $lba1 $size") && die "IS
+O9660.dir.exe: $!";
    }
 }
}
Replies are listed 'Best First'.
Re: Cdrom data recovery script
by Anonymous Monk on Oct 29, 2007 at 06:40 UTC
    comment out the line : next unless $index > 0x26; this was to trim what you need fom the cd.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: sourcecode [id://647787]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (5)
As of 2024-04-24 08:16 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found