This question is a spinoff from the following: How to extract raw ext3 inode data from disk?
I have a file /tmp/foo, whose contents are a simple text string "AAA". I would like to locate the disk block # this data resides on, extract the data in this block and make sure it indeed contains "AAA". So I do the following:
stat foo
which tells me its inode number is 318903debugfs -R 'imap <318903>' /dev/vda3
which tells me that this inode is located at block 1277956, offset 0x0600dumpe2fs /dev/vda3
which tells that the block size is 4096 (bytes) and the inode size is 256 (bytes)- calculate offset of inode from start of disk in 256-byte chunks (makes it simpler to use dd to extract one 256-byte chunk): (1277956 x 4096) + (1536) / 256 = 20447302
- extract the inode from disk (raw data): dd if=/dev/sda3 of=/tmp/inode.0 bs=256 count=1 skip=20447302
- Look at the structure of the ext2 inode table (the ext3 inode has identical structure): http://www.nongnu.org/ext2-doc/ext2.html#INODE-TABLE
- Perform some tests to determine whether I have extracted the correct inode block:
chgrp 1 /tmp/foo; dd if=/dev/sda3 of=/tmp/inode.1 bs=256 count=1 skip=20447302; cmp -l /tmp/inode.1 /tmp/inode.0
. The output from cmp is the following:
13 217 362 14 225 222 25 1 0
Referencing the inode structure, we see that byte 25 corresponds to i_gid, so this confirms that we truly have extracted the correct inode block from disk (previous group was 0, now it is 1). Can also perform similar tests like changing ownership, changing file size by adding data, re-extract the inode from disk, and these tests continue to confirm we have the right inode block.
- Now, according to the documentation, bytes 41-44 of the inode table contains a pointer to the data block (the block # of the actual contents of the file - the file's data). If we do a byte-by-byte compare of our inode with a zero file, we can see the value of bytes 41-44:
cmp -l /tmp/inode.1 /tmp/zero.256
25 1 0 27 1 0 29 10 0 41 56 0 42 220 0 43 23 0 101 275 0 102 53 0 103 240 0 104 374 0
"cmp" gives values in octal. So, assuming byte 44 is the high-order byte, then the value of the pointer in octal is 23 | 220 | 56. converting this to binary = 10011 | 10010000 | 00101110, or 100111001000000101110. Converting this to decimal = 1282094
- now, is "1282094" a reasonable block number for our data? If we look again at the output from dumpefs, we see that both our inode (block 1277956) and our data (block 1282094) fall within the range covered within block group 39, so it would seem we have a reasonable number:
Group 39: (Blocks 1277952-1310719) Inode table at 1277954-1278464 (+2)
- So, we should be able to use dd to extract the data block from disk, examine its contents and they should match the contents our file ("AAA"). But this is not what happens. What happens is the data block contains other stuff, and there is no "AAA" anywhere:
dd if=/dev/vda3 of=/tmp/data bs=4096 count=1 skip=1282094; cmp -l /tmp/data /tmp/zero.4096
1 333 0 2 335 0 3 4 0 5 14 0 7 1 0 8 2 0 9 56 0 13 221 0 14 335 0 15 4 0 17 364 0 18 17 0 19 2 0 20 2 0 21 56 0 22 56 0
This doesn't look like the contents of /tmp/foo. I was thinking maybe I was off by one block, so I also extracted the surrounding blocks (1282093 and 1282095), but still did not find what I was looking for.
What's going on here? What is this extra stuff, and why is there no "AAA"?
11/14. SOLVED. turns out the filesystem had some issues (orphaned inodes and whatnot) which I fixed with fsck and now all is behaving as expected. I want to say thanks a bunch to both Wumpus and derobert (see comments) who offered a lot of invaluable insight and suggestions. Awesome.
stat
. It will tell you immediately if 1282094 is correct. – Nov 12 '14 at 18:35filefrag -v your-file
useful, as it'll tell you which blocks. Also, you did runsync
, right? To make sure its actually written to disk. – derobert Nov 12 '14 at 18:37cmp -l
numbers bytes from 1 instead of 0. – Nov 12 '14 at 18:54cat <318903>
to check the contents? Are you sure you're on the right device? (Maybe your/tmp
is a tmpfs? If so you won't find it on/dev/vda3
or any other device except maybe a swap device) – Nov 12 '14 at 20:48chgrp
experiment seems to confirm you have the right device, but it does change fromvda3
tosda3
in the middle of your story so still I wonder about that. It's hard to say what else could be wrong, once you have confirmed the data block number – Nov 12 '14 at 20:55sync
... – derobert Nov 12 '14 at 21:46sync
on ext3 only writes to the journal if you're indata=journal
mode. In which case time and/or further writes would force it out. So would unmounting the filesystem, I think. – derobert Nov 12 '14 at 21:48sync
notion is still a possibility, because as you said it doesn't make a lot of sense that absence of a sticky bit would cause this. I'd like to test it by disabling journaling, unfortunately I can't shut this system down to single user to do that. – Michael Martinez Nov 12 '14 at 22:00