home *** CD-ROM | disk | FTP | other *** search
/ Freelog Special Edition 1: Linux / CD1.iso / doc / HOWTO / mini / Ext2fs-Undeletion < prev    next >
Text File  |  1998-10-14  |  42KB  |  1,189 lines

  1.   Linux Ext2fs Undeletion mini-HOWTO
  2.   Aaron Crane, <aaronc@pobox.com>
  3.   v1.2, 4 August 1997
  4.  
  5.   Picture this.  You've spent the last three days with no sleep, no
  6.   food, not even a shower.  Your hacking compulsion has at last paid
  7.   off: you've finished that program that will bring you world-wide fame
  8.   and recognition.  All that you still need to do is tar it up and put
  9.   it on Sunsite.  Oh, and delete all those Emacs backup files.  So you
  10.   say rm * ~.  And too late, you notice the extra space in that command.
  11.   You've just deleted your magnum opus!  But help is at hand.  This doc-
  12.   ument presents a discussion of how to retrieve deleted files from a
  13.   Second Extended File System.  Just maybe, you'll be able to release
  14.   that program after all...
  15.   ______________________________________________________________________
  16.  
  17.   Table of Contents
  18.  
  19.  
  20.   1. Introduction
  21.  
  22.      1.1 Revision history
  23.         1.1.1 Changes in version 1.1
  24.         1.1.2 Changes in v1.2
  25.      1.2 Canonical locations of this document
  26.  
  27.   2. How not to delete files
  28.  
  29.   3. What recovery rate can I expect?
  30.  
  31.   4. So, how do I undelete a file?
  32.  
  33.   5. Unmounting the filesystem
  34.  
  35.   6. Preparing to change inodes directly
  36.  
  37.   7. Preparing to write data elsewhere
  38.  
  39.   8. Finding the deleted inodes
  40.  
  41.   9. Obtaining the details of the inodes
  42.  
  43.   10. Recovering data blocks
  44.  
  45.      10.1 Short files
  46.      10.2 Longer files
  47.  
  48.   11. Modifying inodes directly
  49.  
  50.   12. Will this get easier in future?
  51.  
  52.   13. Are there any tools to automate this process?
  53.  
  54.   14. Colophon
  55.  
  56.   15. Credits and Bibliography
  57.  
  58.   16. Legalities
  59.  
  60.  
  61.  
  62.   ______________________________________________________________________
  63.  
  64.  
  65.  
  66.  
  67.   1.  Introduction
  68.  
  69.   This mini-Howto attempts to provide hints on how to retrieve deleted
  70.   files from an ext2 filesystem.  It also contains a limited amount of
  71.   discussion of how to avoid deleting files in the first place.
  72.  
  73.   I intend it to be useful certainly for people who have just had, shall
  74.   we say, a little accident with rm; however, I also hope that people
  75.   read it anyway.  You never know: one day, some of the information in
  76.   here could save your bacon.
  77.  
  78.   The text assumes a little background knowledge about UNIX filesystems
  79.   in general; however, I hope that it will be accessible to most Linux
  80.   users.  If you are an outright beginner, I'm afraid that undeleting
  81.   files under Linux does require a certain amount of technical knowledge
  82.   and persistence, at least for the time being.
  83.  
  84.   You will be unable to recover deleted files from an ext2 filesystem
  85.   without at least read access to the raw device on which the file was
  86.   stored.  In general, this means that you must be root.  You also need
  87.   debugfs from the e2fsprogs package.  This should have been installed
  88.   by your distribution.
  89.  
  90.   Why have I written this?  It stems largely from my own experiences
  91.   with a particularly foolish and disastrous rm -r command as root.  I
  92.   deleted about 97 JPEG files which I needed and could almost certainly
  93.   not recover from other sources.  Using some helpful tips (see section
  94.   ``Credits and Bibliography'') and a great deal of persistence, I
  95.   recovered 91 files undamaged.  I managed to retrieve at least parts of
  96.   five of the rest (enough to see what the picture was in each case).
  97.   Only one was undisplayable, and even for this one, I am fairly sure
  98.   that no more than 1024 bytes were lost (though unfortunately from the
  99.   beginning of the file; given that I know nothing about the JFIF file
  100.   format I had done as much as I could).
  101.  
  102.   I shall discuss further below what sort of recovery rate you can
  103.   expect for deleted files.
  104.  
  105.  
  106.   1.1.  Revision history
  107.  
  108.   The various publicly-released revisions of this document (and their
  109.   publication dates) are as follows:
  110.  
  111.  
  112.   o  v1.0 on 18 January 1997
  113.  
  114.   o  v1.1 on 23 July 1997 (see section ``Changes in v1.1'')
  115.  
  116.   o  v1.2 on 4 August 1997 (see section ``Changes in v1.2'')
  117.  
  118.  
  119.   1.1.1.  Changes in version 1.1
  120.  
  121.   What changes have been made in this version?  First of all, the thinko
  122.   in the example of file recovery has been fixed.  Thankyou to all those
  123.   who wrote to point out my mistaek; I hope I've learned to be more
  124.   careful when making up program interaction.
  125.  
  126.   Secondly, the discussion of UNIX filesystem layout has been rewritten
  127.   to be, I hope, more understandable.  I wasn't entirely happy with it
  128.   in the first place, and some people's comments indicated that it
  129.   wasn't clear.
  130.  
  131.   Thirdly, the vast uuencoded gzipped tarball of fsgrab in the middle of
  132.   the file has been removed.  The program is now available on my website
  133.   <http://pobox.com/~aaronc/tech/fsgrab-1.0.tar.gz> and it should soon
  134.   make its way onto Sunsite
  135.   <http://sunsite.unc.edu/pub/Linux/utils/disk-management/> (and
  136.   mirrors).
  137.  
  138.   Fourthly, the document has been translated into the Linux
  139.   Documentation Project SGML Tools content markup language.  This markup
  140.   language can be easily converted to any of a number of other markup
  141.   languages (including HTML and LaTeX) for convenient display and
  142.   printing.  One benefit of this is that beautiful typography in paper
  143.   editions is a much more achievable goal; another is that the document
  144.   has cross-references and hyperlinks when viewed on the Web.
  145.  
  146.  
  147.   1.1.2.  Changes in v1.2
  148.  
  149.   This revision is very much an incremental change.  It's here mainly to
  150.   include changes suggested by readers, one of which is particularly
  151.   important.
  152.  
  153.   The first change was suggested by Egil Kvaleberg <egil@kvaleberg.no>,
  154.   who pointed out the dump command in debugfs.  Thanks again, Egil.
  155.  
  156.   The second change is to mention the use of chattr for avoiding
  157.   deleting important files.  Thanks to Herman Suijs <H.P.M.Suijs@kub.nl>
  158.   for mentioning this one.
  159.  
  160.   The abstract has been revised.  URLs have been added for organisations
  161.   and software.  Various other minor changes have been made (including
  162.   fixing typos and so on).
  163.  
  164.  
  165.   1.2.  Canonical locations of this document
  166.  
  167.   The latest public release of this document should always be available
  168.   in plain text format on the Linux Documentation Project site
  169.   <http://sunsite.unc.edu/LDP/> (and mirrors).
  170.  
  171.   The latest release is also kept on my website
  172.   <http://pobox.com/~aaronc/> in several formats:
  173.  
  174.  
  175.   o  SGML source <http://pobox.com/~aaronc/tech/e2-undel/howto.sgml>.
  176.      This is the source as I have written it, using the SGML Tools
  177.      package.
  178.  
  179.   o  HTML <http://pobox.com/~aaronc/tech/e2-undel/html/>.  This is HTML,
  180.      automatically generated from the SGML source.
  181.  
  182.   o  Plain text <http://pobox.com/~aaronc/tech/e2-undel/howto.txt>.
  183.      This is plain text, which is also automatically generated from the
  184.      SGML source.  Note that this file is identical to the one on
  185.      Sunsite, so if you want the plain text, you are recommended to get
  186.      it from your favourite LDP mirror (as it will probably be much
  187.      faster).
  188.  
  189.  
  190.   2.  How not to delete files
  191.  
  192.   It is vital to remember that Linux is unlike MS-DOS when it comes to
  193.   undeletion.  For MS-DOS (and its bastard progeny Windows 95), it is
  194.   generally fairly straightforward to undelete a file - the `operating
  195.   system' (I use the term loosely) even comes with a utility which
  196.   automates much of the process.  For Linux, this is not the case.
  197.  
  198.  
  199.   So.  Rule number one (the prime directive, if you will) is:
  200.  
  201.  
  202.        KEEP BACKUPS
  203.  
  204.  
  205.   no matter what.  I know, I'm a fine one to talk.  I shall merely plead
  206.   impoverishment (being a student must have some perks) and exhort all
  207.   right-thinking Linux users to go out and buy a useful backup device,
  208.   work out a decent backup schedule, and to stick to it.  For more
  209.   information on this, read Frisch (1995) (see section ``Bibliography
  210.   and Credits'').
  211.  
  212.   In the absence of backups, what then?  (Or even in the presence of
  213.   backups: belt and braces is no bad policy where important data is
  214.   concerned.)
  215.  
  216.   Try to set the permissions for important files to 440 (or less):
  217.   denying yourself write access to them means that rm requires an
  218.   explicit confirmation before deleting.  (I find, however, that if I'm
  219.   recursively deleting a directory with rm -r, I'll interrupt the
  220.   program on the first or second confirmation request and reissue the
  221.   command as rm -rf.)
  222.  
  223.   A good trick for selected files is to create a hard link to them in a
  224.   hidden directory.  I heard a story once about a sysadmin who
  225.   repeatedly deleted /etc/passwd by accident (thereby half-destroying
  226.   the system).  One of the fixes for this was to do something like the
  227.   following (as root):
  228.  
  229.  
  230.  
  231.        # mkdir /.backup
  232.        # ln /etc/passwd /.backup
  233.  
  234.  
  235.  
  236.  
  237.   It requires quite some effort to delete the file contents completely:
  238.   if you say
  239.  
  240.  
  241.  
  242.        # rm /etc/passwd
  243.  
  244.  
  245.  
  246.  
  247.   then
  248.  
  249.  
  250.  
  251.        # ln /.backup/passwd /etc
  252.  
  253.  
  254.  
  255.  
  256.   will retrieve it.  Of course, this does not help in the event that you
  257.   overwrite the file, so keep backups anyway.
  258.  
  259.   On an ext2 filesystem, it is possible to use ext2 attributes to
  260.   protect things.  These attributes are manipulated with the chattr
  261.   command.  There is an `append-only' attribute: a file with this
  262.   attribute may be appended to, but may not be deleted, and the existing
  263.   contents of the file may not be overwritten.  If a directory has this
  264.   attribute, any files or directories within it may be modified as
  265.   normal, but no files may be deleted.  The `append-only' attribute is
  266.   set with
  267.  
  268.  
  269.  
  270.        $ chattr +a FILE...
  271.  
  272.  
  273.  
  274.  
  275.   There is also an `immutable' attribute, which can only be set or
  276.   cleared by root.  A file or directory with this attribute may not be
  277.   modified, deleted, renamed, or (hard) linked.  It may be set as
  278.   follows:
  279.  
  280.  
  281.  
  282.        # chattr +i FILE...
  283.  
  284.  
  285.  
  286.  
  287.   The ext2fs also provides the `undeletable' attribute (+u in chattr).
  288.   The intention is that if a file with that attribute is deleted,
  289.   instead of actually being reused, it is merely moved to a `safe
  290.   location' for deletion at a later date.  Unfortunately this feature
  291.   has not yet been implemented in mainstream kernels.  However, various
  292.   kernel patches exist which provide the ability to do reversible
  293.   deletion; see <http://www.linuxhq.com/> if you're interested in
  294.   patching this facility into your kernel.  The most recent patch I know
  295.   of is by Rogier Wolff <R.E.Wolff@BitWizard.nl>, Darren J Moffat
  296.   <darren@xarius.demon.co.uk> and Kurt Huwig <kurt@huwig.de>.  I would
  297.   point out though that while this patch implements the feature, it is
  298.   not an `undeletion solution' at the moment.  Undeletable files are
  299.   merely moved into another directory; there should be a daemon to
  300.   periodically clean up that directory.
  301.  
  302.   Some people advocate making rm a shell alias or function for rm -i
  303.   (which asks for confirmation on every file you delete).  Indeed,
  304.   recent versions of the Red Hat distribution <http://www.redhat.com/>
  305.   do this by default for all users, including root.  Personally, I
  306.   cannot stand software which won't run unattended, so I don't do that.
  307.   There is also the problem that sooner or later, you'll be running in
  308.   single-user mode, or using a different shell, or even a different
  309.   machine, where your rm function doesn't exist.  If you expect to be
  310.   asked for confirmation, it is easy to forget where you are and to
  311.   specify too many files for deletion.  Likewise, the various scripts
  312.   and programs that replace rm are, IMHO, very dangerous.
  313.  
  314.   A slightly better solution is to start using a package which handles
  315.   `recyclable' deletion by providing a command not named rm.  For
  316.   details on these, see Peek, et al (1993) (see section ``Bibliography
  317.   and Credits'').
  318.  
  319.  
  320.   3.  What recovery rate can I expect?
  321.  
  322.   That depends.  Among the problems with recovering files on a high-
  323.   quality, multi-tasking, multi-user operating system like Linux is that
  324.   you never know when someone wants to write to the disk.  So when the
  325.   operating system is told to delete a file, it assumes that the blocks
  326.   used by that file are fair game when it wants to allocate space for a
  327.   new file.  (This is a specific example of a general principle for
  328.   Linux: the kernel and the associated tools assume that the users
  329.   aren't idiots.)  In general, the more usage your machine gets, the
  330.   less likely you are to be able to recover files successfully.
  331.   Also, disk fragmentation can affect the ease of recovering files.  If
  332.   the partition containing the deleted files is very fragmented, you are
  333.   unlikely to be able to read a whole file.
  334.  
  335.   If your machine, like mine, is effectively a single-user workstation
  336.   (mine doesn't even have a net connection yet; maybe next year), and
  337.   you weren't doing anything disk-intensive at the fatal moment of
  338.   deleting those files, I would expect a recovery rate in the same ball-
  339.   park as detailed above.  I retrieved nearly 94% of the files (and
  340.   these were binary files, please note) undamaged.  If you get 80% or
  341.   better, you can feel pretty pleased with yourself, I should think.
  342.  
  343.  
  344.   4.  So, how do I undelete a file?
  345.  
  346.   The procedure principally involves finding the data on the raw
  347.   partition device and making it visible again to the operating system.
  348.   There are basically two ways of doing this: one is to modify the
  349.   existing filesystem such that the deleted inodes have their `deleted'
  350.   flag removed, and hope that the data just magically falls back into
  351.   place.  The other method, which is safer but slower, is to work out
  352.   where the data lies in the partition and write it out into a new file.
  353.  
  354.   There are some steps you need to take before beginning to attempt your
  355.   data recovery; see sections ``Unmounting the filesystem'', ``Preparing
  356.   to change inodes directly'' and ``Preparing to write data elsewhere''
  357.   for details.  To find out how to actually retrieve your files, see
  358.   sections ``Finding the deleted inodes'', ``Obtaining the details of
  359.   the inodes'', ``Recovering data blocks'' and ``Modifying inodes
  360.   directly''.
  361.  
  362.  
  363.   5.  Unmounting the filesystem
  364.  
  365.   Regardless of which method you choose, the first step is to unmount
  366.   the filesystem containing the deleted files.  I strongly discourage
  367.   any urges you may have to mess around on a mounted filesystem.  This
  368.   step should be performed as soon as possible after you realise that
  369.   the files have been deleted.
  370.  
  371.   The simplest method is as follows: assuming the deleted files were in
  372.   the /usr partition, say:
  373.  
  374.  
  375.  
  376.        # umount /usr
  377.  
  378.  
  379.  
  380.  
  381.   You may, however, want to keep some things in /usr available.  So
  382.   remount it read-only:
  383.  
  384.  
  385.  
  386.        # mount -o ro,remount /usr
  387.  
  388.  
  389.  
  390.  
  391.   If the deleted files were on the root partition, you'll need to add a
  392.   -n option to prevent mount from trying to write to /etc/mtab:
  393.  
  394.  
  395.  
  396.  
  397.   # mount -n -o ro,remount /
  398.  
  399.  
  400.  
  401.  
  402.   Regardless of all this, it is possible that there will be another
  403.   process using that filesystem (which will cause the unmount to fail
  404.   with an error such as `Resource busy').  There is a program which will
  405.   send a signal to any process using a given file or mount point: fuser.
  406.   Try this for the /usr partition:
  407.  
  408.  
  409.  
  410.        # fuser -v -m /usr
  411.  
  412.  
  413.  
  414.  
  415.   This lists the processes involved.  Assuming none of them are vital,
  416.   you can say
  417.  
  418.  
  419.  
  420.        # fuser -k -v -m /usr
  421.  
  422.  
  423.  
  424.  
  425.   to send each process a SIGKILL (which is guaranteed to kill it), or
  426.   for example,
  427.  
  428.  
  429.  
  430.        # fuser -k -TERM -v -m /usr
  431.  
  432.  
  433.  
  434.  
  435.   to give each one a SIGTERM (which will normally make the process exit
  436.   cleanly).
  437.  
  438.  
  439.   6.  Preparing to change inodes directly
  440.  
  441.   My advice?  Don't do it this way.  I really don't think it's wise to
  442.   play with a filesystem at a low enough level for this to work.  There
  443.   are also has problems in that you can only reliably recover the first
  444.   12 blocks of each file.  So if you have any long files to recover,
  445.   you'll have to use the other method anyway.  (Although see section
  446.   ``Will this get easier in future?'' for additional information.)
  447.  
  448.   If you feel you must do it this way, my advice is to copy the raw
  449.   partition data to an image on a different partition, and then mount
  450.   this using loopback:
  451.  
  452.  
  453.  
  454.        # cp /dev/hda5 /root/working
  455.        # mount -t ext2 -o loop /root/working /mnt
  456.  
  457.  
  458.  
  459.  
  460.   This does, however, require a recent version of mount.  (Although you
  461.   should get version 2.6 or newer anyway, as all earlier versions have a
  462.   major security bug which allows peons to get root access.  The major
  463.   distributions, that is, Debian, RedHat and Slackware, have all been
  464.   updated with version 2.6 of mount.)
  465.  
  466.   Using loopback means that when you completely destroy the filesystem
  467.   (as you quite possibly will), all you have to do is copy the raw
  468.   partition back and start again.
  469.  
  470.  
  471.   7.  Preparing to write data elsewhere
  472.  
  473.   You need to make sure you have a rescue partition somewhere.
  474.   Hopefully, your system has several partitions on it: perhaps a root, a
  475.   /usr, and a /home.  With all these to choose from, you should have no
  476.   problem: just create a new directory on one of these.
  477.  
  478.   If you have only a root partition, and store everything on that (like
  479.   me, until I can get around to repartitioning), things are slightly
  480.   more awkward.  Perhaps you have an MS-DOS or Windows partition you
  481.   could use?  Or you have the ramdisk driver in your kernel, maybe as a
  482.   module?  To use the ramdisk (assuming a kernel more recent than
  483.   1.3.48), say the following:
  484.  
  485.  
  486.  
  487.        # dd if=/dev/zero of=/dev/ram0 bs=1k count=2048
  488.        # mke2fs -v -m 0 /dev/ram0 2048
  489.        # mount -t ext2 /dev/ram0 /mnt
  490.  
  491.  
  492.  
  493.  
  494.   This creates a 2MB ramdisk volume, and mounts it on /mnt.
  495.  
  496.   A short word of warning: if you use kerneld to automatically load and
  497.   unload kernel modules, then don't unmount the ramdisk until you've
  498.   copied any files from it onto non-volatile storage.  Once you unmount
  499.   it, kerneld assumes it can unload the module (after the usual waiting
  500.   period), and once this happens, the memory gets re-used by other parts
  501.   of the kernel, losing all the painstaking hours you just spent
  502.   recovering your data.
  503.  
  504.   If you have any of the new `superfloppy' removable devices, they're
  505.   probably a good choice for a rescue partition location.  Otherwise,
  506.   you'll just have to stick with floppies.
  507.  
  508.   The other thing you're likely to need is a program which can read the
  509.   necessary data from the middle of the partition device.  At a pinch,
  510.   dd will do the job, but to read from, say, 600 MB into an 800 MB
  511.   partition, dd insists on reading but ignoring the first 600 MB.  This
  512.   takes a not inconsiderable amount of time.  My way round this was to
  513.   write a program which will seek to the middle of the partition.  It's
  514.   called fsgrab; you can find the source package on my website
  515.   <http://pobox.com/~aaronc/tech/fsgrab-1.0.tar.gz> and it should soon
  516.   make its way onto Sunsite
  517.   <http://sunsite.unc.edu/pub/Linux/utils/disk-management/> (and
  518.   mirrors).  If you want to use this method, the rest of this mini-Howto
  519.   assumes that you have fsgrab.
  520.  
  521.   If none of the files you are trying to recover were more than 12
  522.   blocks long (where a block is usually one kilobyte), then you won't
  523.   need fsgrab.
  524.  
  525.   If you need to use fsgrab but don't want to, it is fairly
  526.   straightforward to translate an fsgrab command-line to one for dd.  If
  527.   we have
  528.  
  529.        fsgrab -c count -s skip device
  530.  
  531.  
  532.   then the corresponding dd command is
  533.  
  534.  
  535.        dd bs=1k if=device count=count skip=skip
  536.  
  537.  
  538.   I must warn you that, although fsgrab functioned perfectly for me, I
  539.   can take no responsibility for how it performs.  It was really a very
  540.   quick and dirty kludge just to get things to work.  For more details
  541.   on the lack of warranty, see the `No Warranty' section in the COPYING
  542.   file included with it (the GNU General Public Licence).
  543.  
  544.  
  545.   8.  Finding the deleted inodes
  546.  
  547.   The next step is to ask the filesystem which inodes have recently been
  548.   freed.  This is a task you can accomplish with debugfs.  Start debugfs
  549.   with the name of the device on which the filesystem is stored:
  550.  
  551.  
  552.  
  553.        # debugfs /dev/hda5
  554.  
  555.  
  556.  
  557.  
  558.   If you want to modify the inodes directly, add a -w option to enable
  559.   writing to the filesystem:
  560.  
  561.  
  562.  
  563.        # debugfs -w /dev/hda5
  564.  
  565.  
  566.  
  567.  
  568.   The debugfs command to find the deleted inodes is lsdel.  So, type the
  569.   command at the prompt:
  570.  
  571.  
  572.  
  573.        debugfs:  lsdel
  574.  
  575.  
  576.  
  577.  
  578.   After much wailing and grinding of disk mechanisms, a long list is
  579.   piped into your favourite pager (the value of $PAGER).  Now you'll
  580.   want to save a copy of this somewhere else.  If you have less, you can
  581.   type -o followed by the name of an output file.  Otherwise, you'll
  582.   have to arrange to send the output elsewhere.  Try this:
  583.  
  584.  
  585.  
  586.        debugfs:  quit
  587.        # echo lsdel | debugfs /dev/hda5 > lsdel.out
  588.  
  589.  
  590.  
  591.  
  592.   Now, based only on the deletion time, the size, the type, and the
  593.   numerical permissions and owner, you must work out which of these
  594.   deleted inodes are the ones you want.  With luck, you'll be able to
  595.   spot them because they're the big bunch you deleted about five minutes
  596.   ago.  Otherwise, trawl through that list carefully.
  597.  
  598.   I suggest that if possible, you print out the list of the inodes you
  599.   want to recover.  It will make life a lot easier.
  600.  
  601.  
  602.   9.  Obtaining the details of the inodes
  603.  
  604.   debugfs has a stat command which prints details about an inode.  Issue
  605.   the command for each inode in your recovery list.  For example, if
  606.   you're interested in inode number 148003, try this:
  607.  
  608.  
  609.  
  610.        debugfs:  stat <148003>
  611.        Inode: 148003   Type: regular    Mode:  0644   Flags: 0x0   Version: 1
  612.        User:   503   Group:   100   Size: 6065
  613.        File ACL: 0    Directory ACL: 0
  614.        Links: 0   Blockcount: 12
  615.        Fragment:  Address: 0    Number: 0    Size: 0
  616.        ctime: 0x31a9a574 -- Mon May 27 13:52:04 1996
  617.        atime: 0x31a21dd1 -- Tue May 21 20:47:29 1996
  618.        mtime: 0x313bf4d7 -- Tue Mar  5 08:01:27 1996
  619.        dtime: 0x31a9a574 -- Mon May 27 13:52:04 1996
  620.        BLOCKS:
  621.        594810 594811 594814 594815 594816 594817
  622.        TOTAL: 6
  623.  
  624.  
  625.  
  626.  
  627.   If you have a lot of files to recover, you'll want to automate this.
  628.   Assuming that your lsdel list of inodes to recover in is in lsdel.out,
  629.   try this:
  630.  
  631.  
  632.  
  633.        # cut -c1-6 lsdel.out | grep "[0-9]" | tr -d " " > inodes
  634.  
  635.  
  636.  
  637.  
  638.   This new file inodes contains just the numbers of the inodes to
  639.   recover, one per line.  We save it because it will very likely come in
  640.   handy later on.  Then you just say:
  641.  
  642.  
  643.  
  644.        # sed 's/^.*$/stat <\0>/' inodes | debugfs /dev/hda5 > stats
  645.  
  646.  
  647.  
  648.  
  649.   and stats contains the output of all the stat commands.
  650.  
  651.  
  652.   10.  Recovering data blocks
  653.  
  654.   This part is either very easy or distinctly less so, depending on
  655.   whether the file you are trying to recover is more than 12 blocks
  656.   long.
  657.  
  658.  
  659.  
  660.  
  661.   10.1.  Short files
  662.  
  663.   If the file was no more than 12 blocks long, then the block numbers of
  664.   all its data are stored in the inode: you can read them directly out
  665.   of the stat output for the inode.  Moreover, debugfs has a command
  666.   which performs this task automatically.  To take the example we had
  667.   before, repeated here:
  668.  
  669.  
  670.  
  671.        debugfs:  stat <148003>
  672.        Inode: 148003   Type: regular    Mode:  0644   Flags: 0x0   Version: 1
  673.        User:   503   Group:   100   Size: 6065
  674.        File ACL: 0    Directory ACL: 0
  675.        Links: 0   Blockcount: 12
  676.        Fragment:  Address: 0    Number: 0    Size: 0
  677.        ctime: 0x31a9a574 -- Mon May 27 13:52:04 1996
  678.        atime: 0x31a21dd1 -- Tue May 21 20:47:29 1996
  679.        mtime: 0x313bf4d7 -- Tue Mar  5 08:01:27 1996
  680.        dtime: 0x31a9a574 -- Mon May 27 13:52:04 1996
  681.        BLOCKS:
  682.        594810 594811 594814 594815 594816 594817
  683.        TOTAL: 6
  684.  
  685.  
  686.  
  687.  
  688.   This file has six blocks.  Since this is less than the limit of 12, we
  689.   get debugfs to write the file into a new location, such as
  690.   /mnt/recovered.000:
  691.  
  692.  
  693.  
  694.        debugfs:  dump <148003> /mnt/recovered.000
  695.  
  696.  
  697.  
  698.  
  699.   Of course, this can also be done with fsgrab; I'll present it here as
  700.   an example of using it:
  701.  
  702.  
  703.  
  704.        # fsgrab -c 2 -s 594810 /dev/hda5 > /mnt/recovered.000
  705.        # fsgrab -c 4 -s 594814 /dev/hda5 >> /mnt/recovered.000
  706.  
  707.  
  708.  
  709.  
  710.   With either debugfs or fsgrab, there will be some garbage at the end
  711.   of /mnt/recovered.000, but that's fairly unimportant.  If you want to
  712.   get rid of it, the simplest method is to take the Size field from the
  713.   inode, and plug it into the bs option in a dd command line:
  714.  
  715.  
  716.  
  717.        # dd count=1 if=/mnt/recovered.000 of=/mnt/resized.000 bs=6065
  718.  
  719.  
  720.  
  721.  
  722.   Of course, it is possible that one or more of the blocks that made up
  723.   your file has been overwritten.  If so, then you're out of luck: that
  724.   block is gone forever.  (But just imagine if you'd unmounted sooner!)
  725.  
  726.  
  727.   10.2.  Longer files
  728.  
  729.   The problems appear when the file has more than 12 data blocks.  It
  730.   pays here to know a little of how UNIX filesystems are structured.
  731.   The file's data is stored in units called `blocks'.  These blocks may
  732.   be numbered sequentially.  A file also has an `inode', which is the
  733.   place where information such as owner, permissions, and type are kept.
  734.   Like blocks, inodes are numbered sequentially, although they have a
  735.   different sequence.  A directory entry consists of the name of the
  736.   file and an inode number.
  737.  
  738.   But with this state of affairs, it is still impossible for the kernel
  739.   to find the data corresponding to a directory entry.  So the inode
  740.   also stores the location of the file's data blocks, as follows:
  741.  
  742.  
  743.   o  The block numbers of the first 12 data blocks are stored directly
  744.      in the inode; these are sometimes referred to as the direct blocks.
  745.  
  746.   o  The inode contains the block number of an indirect block.  An
  747.      indirect block contains the block numbers of 256 additional data
  748.      blocks.
  749.  
  750.   o  The inode contains the block number of a doubly indirect block.  A
  751.      doubly indirect block contains the block numbers of 256 additional
  752.      indirect blocks.
  753.  
  754.   o  The inode contains the block number of a triply indirect block.  A
  755.      triply indirect block contains the block numbers of 256 additional
  756.      doubly indirect blocks.
  757.  
  758.   Read that again: I know it's complex, but it's also important.
  759.  
  760.   Now, the current kernel implementation (certainly for all versions up
  761.   to and including 2.0.30) unfortunately zeroes all indirect blocks (and
  762.   doubly indirect blocks, and so on) when deleting a file.  So if your
  763.   file was longer than 12 blocks, you have no guarantee of being able to
  764.   find even the numbers of all the blocks you need, let alone their
  765.   contents.
  766.  
  767.   The only method I have been able to find thus far is to assume that
  768.   the file was not fragmented: if it was, then you're in trouble.
  769.   Assuming that the file was not fragmented, there are several layouts
  770.   of data blocks, according to how many data blocks the file used:
  771.  
  772.  
  773.      0 to 12
  774.         The block numbers are stored in the inode, as described above.
  775.  
  776.  
  777.      13 to 268
  778.         After the direct blocks, count one for the indirect block, and
  779.         then there are 256 data blocks.
  780.  
  781.  
  782.      269 to 65804
  783.         As before, there are 12 direct blocks, a (useless) indirect
  784.         block, and 256 blocks.  These are followed by one (useless)
  785.         doubly indirect block, and 256 repetitions of one (useless)
  786.         indirect block and 256 data blocks.
  787.  
  788.  
  789.      65805 or more
  790.         The layout of the first 65804 blocks is as above.  Then follow
  791.         one (useless) triply indirect block and 256 repetitions of a
  792.         `doubly indirect sequence'.  Each doubly indirect sequence
  793.         consists of a (useless) doubly indirect block, followed by 256
  794.         repetitions of one (useless) indirect block and 256 data blocks.
  795.  
  796.   Of course, even if these assumed data block numbers are correct, there
  797.   is no guarantee that the data in them is intact.  In addition, the
  798.   longer the file was, the less chance there is that it was written to
  799.   the filesystem without appreciable fragmentation (except in special
  800.   circumstances).
  801.  
  802.   You should note that I assume throughout that your blocksize is 1024
  803.   bytes, as this is the standard value.  If your blocks are bigger, some
  804.   of the numbers above will change.  Specifically: since each block
  805.   number is 4 bytes long, blocksize/4 is the number of block numbers
  806.   that can be stored in each indirect block.  So every time the number
  807.   256 appears in the discussion above, replace it with blocksize/4.  The
  808.   `number of blocks required' boundaries will also have to be changed.
  809.  
  810.   Let's look at an example of recovering a longer file.
  811.  
  812.  
  813.  
  814.        debugfs:  stat <1387>
  815.        Inode: 148004   Type: regular    Mode:  0644   Flags: 0x0   Version: 1
  816.        User:   503   Group:   100   Size: 1851347
  817.        File ACL: 0    Directory ACL: 0
  818.        Links: 0   Blockcount: 3616
  819.        Fragment:  Address: 0    Number: 0    Size: 0
  820.        ctime: 0x31a9a574 -- Mon May 27 13:52:04 1996
  821.        atime: 0x31a21dd1 -- Tue May 21 20:47:29 1996
  822.        mtime: 0x313bf4d7 -- Tue Mar  5 08:01:27 1996
  823.        dtime: 0x31a9a574 -- Mon May 27 13:52:04 1996
  824.        BLOCKS:
  825.        8314 8315 8316 8317 8318 8319 8320 8321 8322 8323 8324 8325 8326 8583
  826.        TOTAL: 14
  827.  
  828.  
  829.  
  830.  
  831.   There seems to be a reasonable chance that this file is not
  832.   fragmented: certainly, the first 12 blocks listed in the inode (which
  833.   are all data blocks) are contiguous.  So, we can start by retrieving
  834.   those blocks:
  835.  
  836.  
  837.  
  838.        # fsgrab -c 12 -s 8314 /dev/hda5 > /mnt/recovered.001
  839.  
  840.  
  841.  
  842.  
  843.   Now, the next block listed in the inode, 8326, is an indirect block,
  844.   which we can ignore.  But we trust that it will be followed by 256
  845.   data blocks (numbers 8327 through 8582).
  846.  
  847.  
  848.  
  849.        # fsgrab -c 256 -s 8327 /dev/hda5 >> /mnt/recovered.001
  850.  
  851.  
  852.  
  853.  
  854.   The final block listed in the inode is 8583.  Note that we're still
  855.   looking good in terms of the file being contiguous: the last data
  856.   block we wrote out was number 8582, which is 8327 + 255.  This block
  857.   8583 is a doubly indirect block, which we can ignore.  It is followed
  858.   by up to 256 repetitions of an indirect block (which is ignored)
  859.   followed by 256 data blocks.  So doing the arithmetic quickly, we
  860.   issue the following commands.  Notice that we skip the doubly indirect
  861.   block 8583, and the indirect block 8584 immediately (we hope)
  862.   following it, and start at block 8585 for data.
  863.  
  864.  
  865.  
  866.        # fsgrab -c 256 -s 8585 /dev/hda5 >> /mnt/recovered.001
  867.        # fsgrab -c 256 -s 8842 /dev/hda5 >> /mnt/recovered.001
  868.        # fsgrab -c 256 -s 9099 /dev/hda5 >> /mnt/recovered.001
  869.        # fsgrab -c 256 -s 9356 /dev/hda5 >> /mnt/recovered.001
  870.        # fsgrab -c 256 -s 9613 /dev/hda5 >> /mnt/recovered.001
  871.        # fsgrab -c 256 -s 9870 /dev/hda5 >> /mnt/recovered.001
  872.  
  873.  
  874.  
  875.  
  876.   Adding up, we see that so far we've written 12 + (7 * 256) blocks,
  877.   which is 1804.  The `stat' results for the inode gave us a
  878.   `blockcount' of 3616; unfortunately these blocks are 512 bytes long
  879.   (as a hangover from UNIX), so we really want 3616/2 = 1808 blocks of
  880.   1024 bytes.  That means we need only four more blocks.  The last data
  881.   block written was number 10125.  As we've been doing so far, we skip
  882.   an indirect block (number 10126); we can then write those last four
  883.   blocks.
  884.  
  885.  
  886.  
  887.        # fsgrab -c 4 -s 10127 /dev/hda5 >> /mnt/recovered.001
  888.  
  889.  
  890.  
  891.  
  892.   Now, with some luck the entire file has been recovered successfully.
  893.  
  894.  
  895.   11.  Modifying inodes directly
  896.  
  897.   This method is, on the surface, much easier.  However, as mentioned
  898.   above, it cannot cope with files longer than 12 blocks.
  899.  
  900.   For each inode you want to recover, you must set the usage count to
  901.   one, and set the deletion time to zero.  This is done with the mi
  902.   (modify inode) command in debugfs.  Some sample output, modifying
  903.   inode 148003 from above:
  904.  
  905.  
  906.  
  907.  
  908.  
  909.  
  910.  
  911.  
  912.  
  913.  
  914.  
  915.  
  916.  
  917.  
  918.  
  919.  
  920.  
  921.  
  922.  
  923.  
  924.  
  925.   debugfs:  mi <148003>
  926.                             Mode    [0100644]
  927.                          User ID    [503]
  928.                         Group ID    [100]
  929.                             Size    [6065]
  930.                    Creation time    [833201524]
  931.                Modification time    [832708049]
  932.                      Access time    [826012887]
  933.                    Deletion time    [833201524] 0
  934.                       Link count    [0] 1
  935.                      Block count    [12]
  936.                       File flags    [0x0]
  937.                        Reserved1    [0]
  938.                         File acl    [0]
  939.                    Directory acl    [0]
  940.                 Fragment address    [0]
  941.                  Fragment number    [0]
  942.                    Fragment size    [0]
  943.                  Direct Block #0    [594810]
  944.                  Direct Block #1    [594811]
  945.                  Direct Block #2    [594814]
  946.                  Direct Block #3    [594815]
  947.                  Direct Block #4    [594816]
  948.                  Direct Block #5    [594817]
  949.                  Direct Block #6    [0]
  950.                  Direct Block #7    [0]
  951.                  Direct Block #8    [0]
  952.                  Direct Block #9    [0]
  953.                 Direct Block #10    [0]
  954.                 Direct Block #11    [0]
  955.                   Indirect Block    [0]
  956.            Double Indirect Block    [0]
  957.            Triple Indirect Block    [0]
  958.  
  959.  
  960.  
  961.  
  962.   That is, I set the deletion time to 0 and the link count to 1 and just
  963.   pressed return for each of the other fields.  Granted, this is a
  964.   little unwieldy if you have a lot of files to recover, but I think you
  965.   can cope.  If you'd wanted chrome, you'd have used a graphical
  966.   `operating system' with a pretty `Recycle Bin'.
  967.  
  968.   By the way: the mi output refers to a `Creation time' field in the
  969.   inode.  This is a lie!  (Or misleading, anyway.)  The fact of the
  970.   matter is that you cannot tell on a UNIX filesystem when a file was
  971.   created.  The st_ctime member of a struct stat refers to the `inode
  972.   change time', that is, the last time when any inode details were
  973.   changed.  Here endeth today's lesson.
  974.  
  975.   Note that more recent versions of debugfs than the one I'm using
  976.   probably do not include some of the fields in the listing above
  977.   (specifically, Reserved1 and (some of?) the fragment fields).
  978.  
  979.   Once you've modified the inodes, you can quit debugfs and say:
  980.  
  981.  
  982.  
  983.        # e2fsck -f /dev/hda5
  984.  
  985.  
  986.  
  987.  
  988.   The idea is that each of the deleted files has been literally
  989.   undeleted, but none of them appear in any directory entries.  The
  990.   e2fsck program can detect this, and will add a directory entry for
  991.   each file in the /lost+found directory of the filesystem.  (So if the
  992.   partition is normally mounted on /usr, the files will now appear in
  993.   /usr/lost+found.)  All that still remains to be done is to work out
  994.   the name of each file from its contents, and return it to its correct
  995.   place in the filesystem tree.
  996.  
  997.   When you run e2fsck, you will get some informative output, and some
  998.   questions about what damage to repair.  Answer `yes' to everything
  999.   that refers to `summary information' or to the inodes you've changed.
  1000.   Anything else I leave up to you, although it's usually a good idea to
  1001.   say `yes' to all the questions.  When e2fsck finishes, you can remount
  1002.   the filesystem.
  1003.  
  1004.   Actually, there's an alternative to having e2fsck leave the files in
  1005.   /lost+found: you can use debugfs to create a link in the filesystem to
  1006.   the inode.  Use the link command in debugfs after you've modified the
  1007.   inode:
  1008.  
  1009.  
  1010.  
  1011.        debugfs:  link <148003> foo.txt
  1012.  
  1013.  
  1014.  
  1015.  
  1016.   This creates a file called foo.txt in what debugfs thinks is the
  1017.   current directory; foo.txt will be your file.  You'll still need to
  1018.   run e2fsck to fix the summary information and block counts and so on.
  1019.  
  1020.  
  1021.   12.  Will this get easier in future?
  1022.  
  1023.   Yes.  In fact, I believe it already has.  Kernels in the development
  1024.   2.1.x series have not zeroed indirect blocks since more than six
  1025.   months ago.  At the beginning of December 1996, there was some talk on
  1026.   the linux-kernel mailing-list of producing another 2.0.x production
  1027.   kernel that also leaves indirect blocks intact on deletion.  Although
  1028.   as of the pre-released versions of kernel 2.0.31 this has not
  1029.   happened, I suspect that it is feasible.  Once Linus and the other
  1030.   kernel hackers overcome this limitation in the production kernels, a
  1031.   lot of my objections to the technique of modifying inodes by hand will
  1032.   disappear.  At the very latest, this should happen on the release of
  1033.   the 2.2.x kernel series, which (according to historical kernel
  1034.   development time-scales) should happen some time in the first quarter
  1035.   of 1998.  When this wart is corrected, it will also be possible to use
  1036.   the dump command in debugfs on long files.
  1037.  
  1038.  
  1039.   13.  Are there any tools to automate this process?
  1040.  
  1041.   As it happens, there are.  Unfortunately, I believe that they suffer
  1042.   from the same problem as the manual inode modification technique:
  1043.   indirect blocks are unrecoverable.  However, given the likelihood that
  1044.   this will shortly no longer be a problem, it's well worth looking
  1045.   these programs out now.
  1046.  
  1047.   Someone on the net mentioned lde by Scott Heavner.  To be honest, I
  1048.   wouldn't recommend this as a tool for automating file recovery.  It's
  1049.   more like a full-screen debugfs than anything else, although it does
  1050.   have some features like the ability to scan for certain types of file
  1051.   or for certain file contents.  It also works with the xia (does anyone
  1052.   actually use this any more?)  and minix filesystems, which I guess is
  1053.   its major selling point these days.  Version 2.3.4 is available on
  1054.   Sunsite
  1055.   <ftp://sunsite.unc.edu/pub/Linux/system/Filesystems/lde-2.3.4.tar.gz>
  1056.   and mirrors (although it's possible there's a more recent version than
  1057.   this; I found that one on an 8-month-old CD-ROM archive).  lde does
  1058.   have some fairly useful documentation on basic filesystem concepts, as
  1059.   well as a document on how to use it for recovering deleted files.
  1060.   Although I haven't used it, I suspect that my method above is better.
  1061.  
  1062.   It sounds like the program that really works is the GNU Midnight
  1063.   Commander, mc.  This is a full-screen file management tool, based
  1064.   AFAIK on a certain MS-DOS program commonly known as `NC'.  mc supports
  1065.   the mouse on the Linux console and in an xterm, and provides virtual
  1066.   filesystems which allow tricks like cd-ing to a tarfile.  Among its
  1067.   virtual filesystems is one for ext2 undeletion.  It all sounds very
  1068.   handy, although I must admit I've never used the program myself -- I
  1069.   prefer good old-fashioned shell commands.  Apparently one must
  1070.   configure the program with the --with-ext2undel option; you'll also
  1071.   need the development libraries and include files that come with the
  1072.   e2fsprogs package.  I gather that once the program is built, you can
  1073.   tell it to cd undel:dev/hda5/, and get a `directory listing' of
  1074.   deleted files.
  1075.  
  1076.   The latest non-development version is probably 4.0; as with the kernel
  1077.   itself, development versions are not recommended to non-hackers.  The
  1078.   list of (over 70) download sites is available on the Midnight
  1079.   Commander 4 website <http://mc.blackdown.org/mc4/>, or try the
  1080.   official ftp site
  1081.   <ftp://ftp.nuclecu.unam.mx/linux/local/mc-4.0.tar.gz> (which if memory
  1082.   serves is rather slow).
  1083.  
  1084.  
  1085.   14.  Colophon
  1086.  
  1087.   I intend to produce regular updates to this document as long as I have
  1088.   both enough time to do it, and something interesting to say.  This
  1089.   means that I am eager to hear comments from readers.  Could my writing
  1090.   be clearer?.  Can you think of something that would make matters
  1091.   easier?  Is there some new tool that does it all automatically?  Who
  1092.   did kill JFK?
  1093.  
  1094.   Whatever.  If you have something to say, about this document or any
  1095.   other subject, drop me a line on <aaronc@pobox.com>.
  1096.  
  1097.  
  1098.   15.  Credits and Bibliography
  1099.  
  1100.  
  1101.        `If I have seen farther than others, it is because I was
  1102.        standing on the shoulders of giants.' (Isaac Newton)
  1103.  
  1104.  
  1105.   Much of this mini-Howto was derived from a posting in the
  1106.   comp.os.linux.misc newsgroup by Robin Glover <swrglovr@met.rdg.ac.uk>.
  1107.   I would like to thank Robin for graciously allowing me to rework his
  1108.   ideas into this mini-Howto.
  1109.  
  1110.   Some bibliographic references:
  1111.  
  1112.  
  1113.   o  Frisch, leen (1995), Essential System Administration, second
  1114.      edition, O'Reilly and Associates, Inc., ISBN: 1-56592-127-5.
  1115.  
  1116.   o  Glover, Robin (31 Jan 1996), HOW-TO : undelete linux files
  1117.      (ext2fs/debugfs), comp.os.linux.misc Usenet posting.
  1118.  
  1119.   o  Peek, Jerry, Tim O'Reilly, Mike Loukides et al (1993), UNIX Power
  1120.      Tools, O'Reilly and Associates, Inc./Random House, Inc., ISBN:
  1121.      0-679-79073-X.
  1122.  
  1123.   16.  Legalities
  1124.  
  1125.   All trademarks are the property of their respective owners.
  1126.   Specifically:
  1127.  
  1128.  
  1129.   o  MS-DOS and Windows are trademarks of Microsoft
  1130.      <http://www.microsoft.com/>.
  1131.  
  1132.   o  UNIX is a trademark of the Open Group <http://www.open.org/>.
  1133.  
  1134.   o  The trademark status of the name Linux is currently being contested
  1135.      by lawyers.  A certain Walter R. Della Croce has made an allegedly
  1136.      false trademark registration for the term.  Further information on
  1137.      the Linux trademark issue is available from the Linux Mall
  1138.      <http://www.linuxmall.com/announce/>.
  1139.  
  1140.   This document is Copyright  1997 Aaron Crane <aaronc@pobox.com>.  It
  1141.   may be freely redistributed in its entirety, including the whole of
  1142.   this copyright notice, but may not be changed without permission from
  1143.   either the author or the Linux Documentation Project Coordinator.
  1144.   Dispensation is granted for copying small verbatim portions for the
  1145.   purposes of reviews or for quoting; in these circumstances, sections
  1146.   may be reproduced in the presence of an appropriate citation but
  1147.   without this copyright notice.
  1148.  
  1149.   The author requests but does not require that parties intending to
  1150.   sell copies of this document, whether on computer-readable or human-
  1151.   readable media, inform either him or the Linux HOWTO Coordinator of
  1152.   their intentions.
  1153.  
  1154.   The Linux HOWTO Coordinator is Tim Bynum <linux-
  1155.   howto@sunsite.unc.edu>.
  1156.  
  1157.  
  1158.  
  1159.  
  1160.  
  1161.  
  1162.  
  1163.  
  1164.  
  1165.  
  1166.  
  1167.  
  1168.  
  1169.  
  1170.  
  1171.  
  1172.  
  1173.  
  1174.  
  1175.  
  1176.  
  1177.  
  1178.  
  1179.  
  1180.  
  1181.  
  1182.  
  1183.  
  1184.  
  1185.  
  1186.  
  1187.  
  1188.  
  1189.