# Use debufs to prowl around a file system. > debugfs /dev/hda6 debugfs 1.19, 13-Jul-2000 for EXT2 FS 0.5b, 95/08/09 # list files debugfs: ls 2790777 (12) . 32641 (12) .. 2790778 (12) dir1 2790781 (16) file1 2790782 (4044) file2 # List the files with a long listing # Format is: # Field 1: Inode number. # Field 2: First one or two digits is the type of node: # 2 = Character device # 4 = Directory # 6 = Block device # 10 = Regular file # 12 = Symbolic link # # The Last four digits are the Linux permissions # 3. Owner uid # 4. Group gid # 5. Size in bytes. # 6. Date # 7. Time of last creation. # 8. Filename. debugfs: ls -l 2790777 40700 2605 2601 4096 5-Nov-2001 15:30 . 32641 40755 2605 2601 4096 5-Nov-2001 14:25 .. 2790778 40700 2605 2601 4096 5-Nov-2001 12:43 dir1 2790781 100600 2605 2601 14 5-Nov-2001 15:29 file1 2790782 100600 2605 2601 14 5-Nov-2001 15:30 file2 # dump the contents of file1 debugfs: cat file1 This is file1 # dump an inode to a file (same as cat, but to a file) and using #instead of the file name. debugfs: dump <2790782> file1-debugfs # dump the contents of an inode debugfs: stat file1 Inode: 2790782 Type: regular Mode: 0600 Flags: 0x0 Generation: 46520506 User: 2605 Group: 2601 Size: 14 File ACL: 0 Directory ACL: 0 Links: 1 Blockcount: 8 Fragment: Address: 0 Number: 0 Size: 0 ctime: 0x3be712ea -- Mon Nov 5 15:30:02 2001 atime: 0x3be712ea -- Mon Nov 5 15:30:02 2001 mtime: 0x3be712ea -- Mon Nov 5 15:30:02 2001 BLOCKS: 5603924 TOTAL: 1 # Dump an directory inode and look at it. debugfs: dump dir1 dir1-debugfs # Leave debugfs or use another xterm to look at the contents # using od or xxd. The format of a directory (ext2 version 2.0) is: # Field 1. Four byte inode number. # Field 2. Two byte directory entry length. # Field 3. Two byte file name length. # Field 5. Filename (1-255 characters). # Pad. The filename is padded to be a multiple of 4 bytes long. # use -c to see the file names and single byte values # You can see the file names and identify the locatin of # the other fields. Of importance, the length of the # entries (octal); . (4-5), .. (20-21), file3 (34-35), # file4 (54-55), .file4.swp (74-75), ... > od -c dir1-dump 0000000 z 225 * \0 \f \0 001 002 . \0 \0 \0 y 225 * \0 0000020 \f \0 002 002 . . \0 \0 202 225 * \0 020 \0 005 001 0000040 f i l e 3 \0 \0 \0 201 225 * \0 Ø 017 005 001 0000060 f i l e 4 \0 \0 \0 177 225 * \0 È 017 \n 001 0000100 . f i l e 4 . s w p \0 \0 200 225 * \0 0000120 ´ 017 006 001 f i l e 4 ~ . s w p x \0 0000140 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 * 0010000 # use -d to see the two byte values > od -d dir1-dump 0000000 38266 42 12 513 46 0 38265 42 0000020 12 514 11822 0 38274 42 16 261 0000040 26982 25964 51 0 38273 42 4056 261 0000060 26982 25964 52 0 38271 42 4040 266 0000100 26158 27753 13413 29486 28791 0 38272 42 0000120 4020 262 26982 25964 32308 29486 28791 120 0000140 0 0 0 0 0 0 0 0 * 0010000 # You can see that the lengths of the entries are: # . = 12, .. = 12, file3 = 16, file4 = 4096 # Whoa! what happened there. The file .file4.swp # and any other files in the directory have been deleted, # so the length of the entry goes to the end of the block # # use -l to see the four byte values. We can see the inode # values of the files. > od -l dir1-dump 0000000 2790778 33619980 46 2790777 0000020 33685516 11822 2790786 17104912 0000040 1701603686 51 2790785 17108952 0000060 1701603686 52 2790783 17436616 0000100 1818846766 1932407909 28791 2790784 0000120 17174452 1701603686 1932426804 7893111 0000140 0 0 0 0 * 0010000 -------------------------------------------------------------------<
# # You inadvertently delete a file you want back. The file was named # /home/harkin/test/file2. Immediately do the following. # > umount /home # so that you don't create a new file that overwrites the inode # or use one of the file blocks. # Execute df to find out what partition /home is on >df Filesystem 1k-blocks Used Available Use% Mounted on /dev/hda1 1011928 507860 452664 53% / /dev/hda8 27364092 1890176 24083896 8% /home /dev/hda5 8064272 3492760 4161860 46% /usr /dev/hda7 1011928 87956 872568 10% /var clowns:/db/boze 17783240 10494056 7183568 60% /home/bozo/db # Get the data on the /home filesystem tune2fs -l /dev/hda8 | grep "Block size" Block size: 4096 # So the block size is 4096 bytes. # Create a file system to duplicate the /home file system in case # you screw up royally. This disk should be exactly the same size # as the file system you are backing up. Fortunately there is an # unused disk /dev/hdb. > fdisk /dev/hdb Command (m for help): n Command action l logical (5 or over) p primary partition (1-4) p
+27364092K w # copy /home to the backup location dd if=/dev/hda8 of=/dev/hdb1 bs=4096 # Now use debugfs to try to fix things. We need to try to # find the inode of the deleted file. Use lsdel to # list all of the deleted inodes on the file system. debugfs -w # to allow writing debugfs: lsdel 3061 deleted inodes found. Inode Owner Mode Size Blocks Time deleted . . 3296723 2605 100600 652 1/ 1 Fri Nov 2 07:30:33 2001 3296724 2605 100600 1545 1/ 1 Fri Nov 2 07:30:33 2001 3296725 2605 100600 355 1/ 1 Fri Nov 2 07:30:33 2001 3296731 2605 100600 440 1/ 1 Fri Nov 2 07:30:33 2001 3296732 2605 100600 3536 1/ 1 Fri Nov 2 07:30:33 2001 3296733 2605 100600 2365 1/ 1 Fri Nov 2 07:30:33 2001 3296734 2605 100600 443 1/ 1 Fri Nov 2 07:30:33 2001 3296850 2605 100600 2046 1/ 1 Fri Nov 2 07:30:33 2001 3296851 2605 100600 729 1/ 1 Fri Nov 2 07:30:33 2001 3296852 2605 100600 850 1/ 1 Fri Nov 2 07:30:33 2001 3296853 2605 100600 3251 1/ 1 Fri Nov 2 07:30:33 2001 3296854 2605 100600 3733 1/ 1 Fri Nov 2 07:30:33 2001 3296855 2605 100600 3109 1/ 1 Fri Nov 2 07:30:33 2001 3296856 2605 100600 3211 1/ 1 Fri Nov 2 07:30:33 2001 652818 2605 100600 171791 43/ 43 Fri Nov 2 16:07:33 2001 897613 2605 100600 2096 1/ 1 Mon Nov 5 07:49:28 2001 979218 2605 100600 3797 1/ 1 Mon Nov 5 07:49:29 2001 979219 2605 100600 4096 1/ 1 Mon Nov 5 07:49:29 2001 179573 2605 100600 9113 3/ 3 Mon Nov 5 12:41:16 2001 636513 2605 100600 1327 1/ 1 Mon Nov 5 12:41:16 2001 636520 2605 100600 20 1/ 1 Mon Nov 5 12:41:16 2001 1338319 2605 100600 6998 2/ 2 Mon Nov 5 12:48:55 2001 # Based on the time and date, the inode to restore is 179573, 636513 # or 636520. Try to figure out which one. debugfs:cat <179573> . . debugfs:cat <636513> . # This is rather inconvenient. If the directory where the files were # deleted from still exists, use the cd command to get there and then # use ls -d which lists the files in the directory only, including # those with the deleted flag set. 1566721 (12) . 32641 (12) .. 1566788 (60) 530 1566790 (48) file1 1566791 (24) file2 <1566747> (20) file3 The inode numbers in brackets are deleted files. A better looking display comes with ls -ld. # So now you know which inode you need to restore. # To restore the file, you need to modify the inode, not the # directory entry. This can be done with the modify_inode (mi) # command. Specifically, change the deletion time to zero # and the link count to 1. debugfs: mi <636513> debugfs: mi <148003> Mode [0100644] User ID [510] Group ID [510] Size [8123] Creation time [904216575] Modification time [904234782] Access time [904234782] Deletion time [904236721] 0 Link count [0] 1 Block count [16] File flags [0x0] Reserved1 [0] File acl [0] Directory acl [0] Fragment address [0] Fragment number [0] Fragment size [0] Direct Block #0 [100321] Direct Block #1 [100322] Direct Block #2 [100323] Direct Block #3 [100324] Direct Block #4 [200456] Direct Block #5 [200457] Direct Block #6 [200675] Direct Block #7 [200675] Direct Block #8 [304568] Direct Block #9 [0] Direct Block #10 [0] Direct Block #11 [0] Indirect Block [0] Double Indirect Block [0] Triple Indirect Block [0] # It has been recovered. # This won't work for files with indirect blocks and you might find that # one or more blocks have been reused already. If so, you can # recover as much data as possible by dumping the blocks to a file. debugfs: dump <100321> /tmp > file1.000 debugfs: dump <100322> /tmp >> file1.000 # and so on. For files that are longer than 12 blocks, you have to # trace the indirect, double-indirect and triple-indirect blocks.