Recovering Deleted File Data on QNX4 FS

Hi Guys,

After many years away from working on QNX systems I have the joy of trying
to recover some deleted data from a QNX 4 based logging system that is
designed to only maintain 16 days of history. Each day cron executes a
cleanup script that goes around deleting various files that accumulate
over
time so the system never runs out of disk space.

The system is all working fine except due to human error the data that is
normally printed out and archived each day, was not printed for a few
weeks
and so they now would dearly love to recover any data that I can find. :slight_smile:)

So I’ve blown the dust off my old C manuals and started looking at the
problem and am wondering if anyone has any source code fragments that
would
give me a head start writing a custom utility to read the /.bitmap, work
out
which blocks on the disk are free so I can know which blocks to look at as
I
search for extent blocks that have recognizable (by my app) data in them?

Any help would be appreciated.

Cheers

Alex Shepherd

There is an application on QNX ftp site called diskraw. It can recover
deleted files.

“Alex Shepherd” <qnx@ajsystems.co.nz> wrote in message
news:cnrpbk$4ov$1@inn.qnx.com

Hi Guys,

After many years away from working on QNX systems I have the joy of trying
to recover some deleted data from a QNX 4 based logging system that is
designed to only maintain 16 days of history. Each day cron executes a
cleanup script that goes around deleting various files that accumulate
over
time so the system never runs out of disk space.

The system is all working fine except due to human error the data that is
normally printed out and archived each day, was not printed for a few
weeks
and so they now would dearly love to recover any data that I can find.
:slight_smile:> )

So I’ve blown the dust off my old C manuals and started looking at the
problem and am wondering if anyone has any source code fragments that
would
give me a head start writing a custom utility to read the /.bitmap, work
out
which blocks on the disk are free so I can know which blocks to look at as
I
search for extent blocks that have recognizable (by my app) data in them?

Any help would be appreciated.

Cheers

Alex Shepherd

Alex Shepherd wrote:

The system is all working fine except due to human error the data that is
normally printed out and archived each day, was not printed for a few
weeks and so they now would dearly love to recover any data that I can find.

I would not be optimistic that old data still exists if the system has
continued to log for a few weeks. Filesystem block allocation policy is
just to use any (not the oldest) available space, and makes no attempt
to avoid re-using recently-deleted file space. Or you may be lucky.

So I’ve blown the dust off my old C manuals and started looking at the
problem and am wondering if anyone has any source code fragments that
would give me a head start writing a custom utility to read the /.bitmap, work
out which blocks on the disk are free so I can know which blocks to look at as
I search for extent blocks that have recognizable (by my app) data in them?

“diskraw” has been mentioned, which may be useful. In terms of reading
the bitmap, you can simply open and read it as any file:

fd = open("/.bitmap", O_RDONLY);
while (read(fd, block, 512) == 512)
;

Bit N is clear if that block is unused (“block[N/8] & (1 << (N%8))”)

The other thing you might try is using “spatch -b /dev/hd0t77” to scan
through the disk (if there is a known data/signature to identify your
data, put that as the ‘Find’ data and let it search the disk for you).

I have a utility called “undel” that works quite well, but, is stated
elsewhere, it won’t help you if the deleted blocks have been reused. I don’t
know where I got it (probably from the QNX website, but I don’t recall for
sure), but here’s the copyright notice:


COPYRIGHT (C) 1999 Network Concepts, Inc, (NCI) ALL RIGHTS RESERVED

Contact:
Robert Nadler
Network Concepts, Inc. (NCI)
2135 W. Greenview Dr.
Middleton, WI 53562
Tel: (608) 836-9334
Fax: (608) 831-8333
bobn@nci.com

It has saved my behind a number of times.

  • Kevin

“Alex Shepherd” <qnx@ajsystems.co.nz> wrote in message
news:cnrpbk$4ov$1@inn.qnx.com

Hi Guys,

After many years away from working on QNX systems I have the joy of trying
to recover some deleted data from a QNX 4 based logging system that is
designed to only maintain 16 days of history. Each day cron executes a
cleanup script that goes around deleting various files that accumulate
over
time so the system never runs out of disk space.

The system is all working fine except due to human error the data that is
normally printed out and archived each day, was not printed for a few
weeks
and so they now would dearly love to recover any data that I can find.
:slight_smile:> )

So I’ve blown the dust off my old C manuals and started looking at the
problem and am wondering if anyone has any source code fragments that
would
give me a head start writing a custom utility to read the /.bitmap, work
out
which blocks on the disk are free so I can know which blocks to look at as
I
search for extent blocks that have recognizable (by my app) data in them?

Any help would be appreciated.

Cheers

Alex Shepherd

Thanks for all the responses guys - good to see a few familiar names as
well!

I would not be optimistic that old data still exists if the system has
continued to log for a few weeks. Filesystem block allocation policy is
just to use any (not the oldest) available space, and makes no attempt
to avoid re-using recently-deleted file space. Or you may be lucky.

Yes, I tend to agree and have told the customer not to expect any success
but they want me to try anyway “just in case they are lucky”.

So I am now writing a utility that opens the bitmap file, finds the free
blocks and used the Block_Read() to search the free blocks looking for
records with certain data patterns that I can validate. With a bit of luck
I’ll have it cut out in a day or so…

The other thing you might try is using “spatch -b /dev/hd0t77” to scan
through the disk (if there is a known data/signature to identify your
data, put that as the ‘Find’ data and let it search the disk for you).

Unfortunately the data is binary and contains time stamps etc but I did
have the foresight to include a CRC in the last data field so I should be
able to validate the data patterns with a few sanity check rules

Cheers

Alex Shpepherd

Boy, would I like a copy. Can I have one?

kovacsbv <victor.kovacs@jci-dot-com.no-spam.invalid> wrote:

Boy, would I like a copy. Can I have one?

ftp.qnx.com:/usr/free/qnx4/os/utils/disk/undel.gz

Also useful:

ftp.qnx.com:/usr/free/qnx4/os/utils/disk/disk_raw.tgz

-David

David Gibbs
QNX Training Services
dagibbs@qnx.com

Six years seems like eons ago. I’m in the process of porting undel to
QNX 6.3 in my spare time (for fun … I’m such a nerd!).

Bob
rnadler@tds.net

Hey Bob,

You wouldn’t have managed to complete the port of undel by any chance?
:slight_smile:

Dave…

Nope. I started on it last month, then was distracted by other things.
I got a little way but now have two problems.

  1. For some unknown reason, when I try to read a directory directly,
    the read always fails after 48 bytes (a dir entry is 64 bytes).
    Strange. Example code below prints:

read error: got=48 get=16 errno=240 Message too long

Same code reading a regular file works fine. It’s probably something
simple, or a QNX6 thing I’m not aware of.

  1. I had a demo momentics license that expired at the beginning of
    May. Now I can’t compile… :frowning:

Bob


// Test direct QNX4 directory reading…
//
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/fs_qnx4.h>
#define d_inode_t d_inode
#define di_fname i_fname

int
read_buf(int fd, void * buf,int want) {
int rsz,got = 0,get = want;
while (got < want) {
if ((rsz = read(fd,(char *)buf +
got,get)) == -1) {
printf(“read error: got=%d get=%d errno=%d
%s\n”,got,get,errno,strerror(errno));
return -1;
}
if (rsz == 0) break;
got += rsz;
get -= rsz;
}
return got;
}

int
main(int argc, char *argv[]) {
int fd,i;
char *path;
char pbuf[PATH_MAX + 1];
int u_cnt = 0; // unused entries
qnx4fs_dir_entry_t de;

path = getcwd(pbuf,PATH_MAX + 1);

if ((fd = open(path,O_RDONLY)) == -1)
{
perror(path);
return 4;
}
i = 0;


while
(read_buf(fd,&de,sizeof(qnx4fs_dir_entry_t))
== sizeof(qnx4fs_dir_entry_t)) {
if (!*de.d_inode_t.di_fname) {
u_cnt++;
}
i++;
} // end while loop
close(fd);
printf(“readdir %s: complete [T=%d
U=%d]\n”,path,i,u_cnt);
return EXIT_SUCCESS;
}

rnadler wrote:

  1. For some unknown reason, when I try to read a directory directly,
    the read always fails after 48 bytes (a dir entry is 64 bytes).
    Strange. Example code below prints:

read error: got=48 get=16 errno=240 Message too long

Same code reading a regular file works fine. It’s probably something
simple, or a QNX6 thing I’m not aware of.

read() of a directory is readdir(); ie you get back formatted entries
as per <dirent.h>. EMSGSIZE because your buffer is not enough to
contain the struct dirent plus variable-length name. 64 was probably
enough to hold “.” (and maybe “…”?) items (for total of 48).

Basically you can’t read raw directory entries this way; you need to
read() the underlying partition (work out what that is, then work out
what the block offset and extents of the directory are, which involves
locating the inode for it from the root using the pathname, etc).

Wasn’t the “disk_raw” utility posted for QNX4 - that seems a better
starting point (think it actually it had an undelete facility too)?

John Garvey <jgarvey@qnx.com> wrote:

rnadler wrote:
Wasn’t the “disk_raw” utility posted for QNX4 - that seems a better
starting point (think it actually it had an undelete facility too)?

I don’t think disk_raw was ever posted in source, just as a binary.

And, I went looking for the source a while back, but couldn’t find
it.

-David

David Gibbs
QNX Training Services
dagibbs@qnx.com