Initial remote commit
This commit is contained in:
66
misc_tools/inspect_chunk.py
Normal file
66
misc_tools/inspect_chunk.py
Normal file
@@ -0,0 +1,66 @@
|
||||
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
|
||||
Reference in New Issue
Block a user