From: bzs@ussr.std.com (Barry Shein)
Subject: Re: DAMN: deleted all my files; saved partition tho'
Organization: The World
Date: Sat, 10 Oct 1992 02:18:58 GMT


>> ... each cylinder group should have a bit map or something to indicate
>> which blocks are free.  Only examine those.
>
>Eh?  If the partition was completely wiped, then _all_ the blocks should
>be on the free list and the bit map should show all 1's.  How can this help
>to figure out which blocks were once allocated, but have since been freed?

I don't think the orginal poster said the entire partition was wiped
out, only the entire directory, in which case limiting examination to
free blocks is an optimization.

I have played with this problem (recovering deleted files from a SunOS
partition) and the original suggestions all made sense.

Two more suggestions:

Write a heuristic tool similar to the "file" command which "guesses"
whether or not a file system block appears to be human-readable text
(assuming most of what you hope to recover is human-readable text.)

One good way to do this is just look at the characters in the block
and ignore all printables and common controls (LF, CR perhaps, ^L) and
play around with a weighting for how good the block is (like add 1 for
every unlikely control, 2 for every character >0176, etc.) The gotcha
here is half-ascii files like from WYSIWYGs where they might begin
with a hunk of binary but thereafter have good hunks of readable text
worth recovering (or even pasting back together into the format), they
can fool a program like that. Tempts one to distance-weight readable
text (e.g. by run-length etc), but it can get pretty crazy pretty
fast.

Similarly, look at /etc/magic if you use certain tools like a WYSIWYG
to see if you can figure out a distinctive header for files you are
interested in, and files you aren't (eg. ignore a.out headers if
you're pretty sure you don't care about such blocks.) Remember that
other than frags files start at block boundaries so their distinctive
headers (where they exist) will be at the beginning of the block.

Hell, if you're patient you could write each block to a tmp file and
run "file" on it and see what it comes up with and grep through the
output for obvious good hits (e.g. sparc executable, GIF file,
compressed, etc.)

Also, directory blocks, if they were wiped out, will start with the
stuff described in /usr/include/sys/dir.h and the first two names will
be . and .. (ok, in theory that's not absolutely necessary, though it
will be true unless something weird is going on.) So suck back two
struct direct's of stuff from the top and check d_name[]:

	struct direct d[2];

	read(fd,d,sizeof(d));

	if((d[0].d_name[0] == '.') && !strncmp(d[1].d_name,"..",2))
	   probably_a_directory.

Locality is very important, keep an eye on cylinder groups as the
Rollow mentioned, bunches of readable-text in the same cylinder group
tend to be from the same file.

It's probably worth building a little yes/no previewer front end which
shows some stuff (a block), what the program thinks it likely is, and
offers to save it away easily so you can rebuild files on the fly from
blocks with a few keystrokes.



--
        -Barry Shein

Software Tool & Die    | bzs@world.std.com          | uunet!world!bzs
Purveyors to the Trade | Voice: 617-739-0202        | Login: 617-739-WRLD