SUMMARY: recovering an UNREF FILE [Success story]

From: Claude Scarpelli (claude@genethon.genethon.fr)
Date: Sat Feb 15 1992 - 15:12:58 CST


In a previous mail, I've asked Sun Managers how to reconnect an
opened but removed file :

One of my users has removed an important file. By chance, this file
was opened by a running program and then the file was not
REALLY removed : The blocks containing data and the inode were
still allocated. The only missing thing was a directory entry
referencing that inode.

I've ran fsck on the file system, and it reports an UNREF FILE. fsck
asked me if I was agree to CLEAR the inode. I answered NO, because
in this case I would have lost the file. (Remember that a running
program has the file open).

In such case, fsck DOES NOT ask me to RECONNECT the file. With
RECONNECT, fsck creates an entry in lost+found, and all is ok. As the file
was removed, its link count in the inode is zero. I think that's why
fsck ask me to CLEAR and not to RECONNECT.

At this point, it is clear that I must find a way to either
        - put 1 in the link count of the inode, then run fsck (it is
          the way I have choose)
or - create a directory entry, then, by hacking the disk, changing
          the i-number of the entry (Ted Nolan [ted@usasoc.soc.mil] -
          see his mail at the end of this mail).

I will now describe how I have worked with the first way.

WAY 1
-----

The problem is to find the inode (remember that we know the inode number).
I've tried adb on /vmunix and /dev/mem, starting by the rootvfs
symbol, following the vfs structure. I have found the vfs structure
of the disk containing the file (the id of the disk is in /etc/mtab),
but I was unable to find the vnode/inode of the file (I was unable
to walk in the vnode set of the disk). All the informations to
do that were found in /usr/include and in the Sun Software Technical
Bulletin of December 91 [the rootvfs symbol, which is the starting
point of all the disk subsystem].

I have gave up with adb !

Then, I have found a program called ofiles, which (as fuser) reports
some informations about the open files of a program. I've found
ofiles in ftp.inria.fr/system/admin. I've take the version
modified by Robert Erlich (ofiles-erlich).

As far as I know, there are only to way to find a file in UNIX kernel:
        - take the rootvfs and walk through the mounted file systems.
or - take the proc table, then the file table and then the inode
          of the open files (ofiles, fusers).

I ran ofiles on my system, and it reports the inode of the lost file.
I've then modified the code (very easy) in order to write in
the inode of the lost file (the link count field). After doing
that, I ran fsck which then reports an UNREF FILE and asked me
to RECONNECT it ! I won ! Saying YES, fsck puts an entry in
lost+found. The running program continue and update the content
of the file at this moment.

I now think that system administrator needs a program to walk
through the various file systems (well, there is adb !), in
order to correct (as fsck, but in memory, on a running system)
file systems. Robert Dal Santo (robert@psych.psy.uq.oz.au)
has a program called ipeek that given an inode will do various
things. Robert still search for the source file. I think its
best place is an ftp anonymous site !

and now the
WAY 2
-----

I just enclose the mail from Ted Nolan (ted@usasoc.soc.mil). I think
it is more simple than the WAY 1, but his mail arrived too late !

I would like to thanks all who replied (and even those who says me
to answer YES at the CLEAR question :-), and especially

Ted Nolan SRI Ft Bragg <ted@usasoc.soc.mil> (WAY 2) and
Rober Dal Santo <robert@psych.psy.uq.oz.au> for the ipeek program
(I'm still waiting for it Robert !)

------------------------------------------------------------------------------
Claude Scarpelli Internet : claude@genethon.fr
Human Polymorphism Study Center or : claude@cephb.fr

----- Begin Included Message -----
From: Ted Nolan SRI Ft Bragg <ted@usasoc.soc.mil>
Hello,

The following strategy occurs to me. It's certainly not pretty,
and I haven't ever tried it, but...

Essentially, you need to get a directory entry which corresponds to
your inode, which would be easy enough if directories were directly
writable, but they aren't. So:

1) Create a new directory in the same file system as the unreferenced file.
   Create 1 file in it and give it a really odd name, which exists nowhere
   else in the filesystem (even as text in another file). Hardlink another
   file to this file.

2) Learn to understand the BSD file system, or write a little program that
   reads the (block) disk device directly and looks for your odd file name as
   a text string. When you find the name, print out the byte offset of its
   start and save it for future reference. Seek backwards 8 bytes from here and
   read 4 bytes into an unsigned long (see man 5 dir). Print this value
   also. If it does not agree with the inode number for the oddly named file,
   I'm obviously wrong, and you shouldn't pay any more attention to me.

3) If it does agree with the inumber of your oddly named file, write
   another program to seek back to these 4 bytes, and write out 4 bytes
   from an unsigned long holding the inumber of your unreferenced file.

4) At this point, your oddly named file should reference the deleted file.
   If this is true, you should immediately copy (not mv!) it to another file,
   as none of this has changed the reference count of the inode, and fsck
   will still want to remove it. (Also the reference count for the file you
   hardlinked to the oddly named file will be wrong too).

Will any of this actually work? Don't know, but it seems reasonable. If you
have the disk space, you might consider "dd"ing the subject filesystem to
another disk and playing with the copy, since playing around with the
disk device behind Unix's back is obviously fraught with peril..

                                Ted Nolan
                                ted@usasoc.soc.mil

----- End Included Message -----



This archive was generated by hypermail 2.1.2 : Fri Sep 28 2001 - 23:06:36 CDT