On 4/13/05, John W. Krahn <[EMAIL PROTECTED]> wrote:
> Jay Savage wrote:
[snip]
> I haven't used DOS in a while so I may be a little fuzzy on some of the
> details.
> 
> Sector size is based on the media, be it hard disk, floppy disk or whatever,
> and is not carved in stone although most hard disk manufacturers have
> standardised on (IIRC) 512 bytes.
> 
> Cluster size is set when the media is formatted and is recorded in the boot
> sector and is based on the total size of the media.
>

Right.  Which is why working with sectors is safe: Cluster size varies
by media capacity, but always as a multiple of sectors.  And since I'm
limited here to machines that read exclusively FAT16, the sector size
is almost certain to be 512 bytes.  If cameras ever start using FAT32,
I'll have to rethink things.  One bridge at a time.
 
> The EOF byte was used in CP/M (because CP/M didn't store the file size
> anywhere) and IIRC initial versions of DOS but all later versions of DOS store
> the file size with the directory entry along with the file name and all other
> file meta-data.
> 

Ah.  For some reason, I thought EOF continued to be embedded...

> The DOS file system is subject to fragmentation so files may not be in
> contiguous clusters.  The File Allocation Table determines the order of the
> clusters for each file and is located just after the boot sector.
> 
> If the files are using a proprietary format then there is no guarantee that
> the SOI is at the start of the cluster.
> 

This is theoretically true, but none of the cameras I've tested have
stored header information before SOI.  And that makes sense: with
almost any digital camera, you can remove the media, mount it using a
card reader, and have the files recognized as jpegs.  The file still
has to start at the sector boundary, and as long as I'm confident that
the jpeg stream SOI is at the start of the file...

> Have you tried mounting the file as a file system?  Easy enough on Linux using
> a loopback device and I think it is even possible on some versions of Windows.
> 

Sure.  But it doesn't really gain me much.  The idea here is to
recover files from a card I know has incorrect FAT info, either
because of a dirty unmount, or because I accidentally deleted files I
didn't mean to (it's so easy to hit that delete button accidentally). 
Either way, I'm explicitly looking for files that that the FAT thinks
don't exist, and therefore, files the OS won't see.  On my sample
image, for instance, there are 15 files with directory entries, but I
can recover a total of 134.  And so far, so good; the recovery works
fine right up to the end, where the last file recovered slurps
everything up to the end of the image.

I could mount the image--or just mount the card itself -ro--and
operate on the raw device, but I don't think that would gain me much
except another layer of complexity and another chance to corrupt the
data with a dirty unmount.

We've wandered a ways away from actual code, though, so here is some
working code to recover files from digital camera removable media
(<2GB, see comments on FAT32 above).  It produceas usable, although by
no means clean, jpegs.  I've just given up EOI.

Thanks again,

--jay


#!/usr/bin/perl

use warnings;
use strict;

my $image = shift @ARGV;
my $file = 0;
my $dir = "lost+found";
my $name;
my $sector;
my $seclen = 512;
my $fileeof = 0;
my $magic = qr/^\xff\xd8\xff(?:\xe1|\xe0)/;
     # \xe0 is JFIF standard, although nothing seen yet uses it

mkdir $dir or die "Couldn't create directory: $!" unless -d $dir;
open(IMG, "< :raw", $image)
    or die "Couldn't open $image for reading: $!\n";
seek(IMG, 0, 0);

until (eof IMG) {     # explicit FH is probably best
    read(IMG, $sector, $seclen)
        or die "Couldn't read from $name: $!\n";
    next if $file == 0 and $sector !~ $magic;
    if ($sector =~ $magic) {
        close(SAVE);
        print "Recoverd image to $name\n" if $file != 0;
        $name = sprintf("%s/flash_%3.3d.jpg", $dir, ++$file);
        open(SAVE, "> :raw", $name)
            or die "Couldn't open $name for writing: $!\n";
    }
    print SAVE $sector or die "Couldn't write to $name:$!\n";
}
close(SAVE);
print "Recoverd image to $name\n";
print "\nRecovered $file files to $dir\n\n";
__END__

--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>


Reply via email to