Files
ext4recovery/misc_tools/inspect_chunk.py
2026-04-30 11:04:05 +00:00

67 lines
2.3 KiB
Python

CHUNK = 128*512
LV_START = 5120000*512
BSIZE = 4096
# Block 5251104 falls in:
# virt_byte = 5251104 * 4096 = 21508521984
# group=65638, chunk_idx=4, intra=0
# The physical location of this metadata chunk:
group = 65638
phys_meta = LV_START + group*5*CHUNK + 4*CHUNK
print(f'Metadata chunk physical byte: {phys_meta}')
# Read the full 64KB metadata chunk
with open('/dev/md0','rb') as f:
f.seek(phys_meta)
meta = f.read(CHUNK)
nonzero = sum(1 for b in meta if b != 0)
print(f'Nonzero bytes: {nonzero}/{CHUNK}')
print()
# Earlier we found that metadata chunks store 512 bytes per sector
# of the 4 adjacent data chunks = 128 sectors * 4 chunks = 512 entries
# But what if SOME of those 512-byte slots contain filesystem data
# instead of PERC metadata?
# The /var dir block should be 4096 bytes
# Could it be stored in 8 consecutive 512-byte slots?
# Let's look for directory signatures in the metadata chunk
import struct
# Search for directory entry signature: valid inode + rec_len + name_len
print('Searching for directory entries in metadata chunk...')
for off in range(0, CHUNK-8, 4):
ino = struct.unpack_from('<I', meta, off)[0]
rec_len = struct.unpack_from('<H', meta, off+4)[0]
name_len= meta[off+6]
ftype = meta[off+7]
if (10 < ino < 500_000_000 and
8 <= rec_len <= 256 and
0 < name_len <= rec_len-8 and
ftype in (1,2,7) and
rec_len % 4 == 0):
name = meta[off+8:off+8+name_len].decode('utf-8',errors='replace')
if name.isprintable() and len(name) == name_len:
print(f' offset {off}: inode={ino} rec_len={rec_len} '
f'name={name!r} ftype={ftype}')
# Also check: does the metadata chunk contain the filesystem data
# at a fixed offset? e.g. first 4096 bytes = filesystem data block?
print()
print('First 4096 bytes as directory:')
off = 0
while off < 4096-8:
ino = struct.unpack_from('<I', meta, off)[0]
rec_len = struct.unpack_from('<H', meta, off+4)[0]
name_len= meta[off+6]
ftype = meta[off+7]
if rec_len < 8: break
if ino > 0 and name_len > 0:
name = meta[off+8:off+8+name_len].decode('utf-8',errors='replace')
tname = {1:'file',2:'dir',7:'link'}.get(ftype,'?')
print(f' {tname} inode={ino} {name!r}')
off += rec_len