94 lines
3.5 KiB
Python
94 lines
3.5 KiB
Python
import struct
|
|
|
|
CHUNK = 128*512
|
|
LV_START = 5120000*512
|
|
BSIZE = 4096
|
|
IPG = 8192
|
|
|
|
def read_virt(virt_byte, length):
|
|
result = bytearray(length)
|
|
pos = virt_byte
|
|
remaining = length
|
|
with open('/dev/md0','rb') as f:
|
|
while remaining > 0:
|
|
group = pos // (5*CHUNK)
|
|
in_group = pos % (5*CHUNK)
|
|
chunk_idx = in_group // CHUNK
|
|
intra = in_group % CHUNK
|
|
seg_len = min(CHUNK-intra, remaining)
|
|
dst_off = pos - virt_byte
|
|
if chunk_idx != 4:
|
|
phys = LV_START + group*4*CHUNK + chunk_idx*CHUNK + intra
|
|
f.seek(phys)
|
|
data = f.read(seg_len)
|
|
result[dst_off:dst_off+len(data)] = data
|
|
pos += seg_len
|
|
remaining -= seg_len
|
|
return bytes(result)
|
|
|
|
# Read GDT from md0
|
|
print('Reading GDT from /dev/md0...')
|
|
gdt_data = read_virt(BSIZE, 20*64)
|
|
|
|
for g in range(20):
|
|
entry = gdt_data[g*64:(g+1)*64]
|
|
it_lo = struct.unpack_from('<I', entry, 8)[0]
|
|
it_hi = struct.unpack_from('<I', entry, 40)[0]
|
|
it_block = (it_hi<<32)|it_lo
|
|
flags = struct.unpack_from('<H', entry, 18)[0]
|
|
print(f' Group {g:3d}: it_block={it_block:10d} '
|
|
f'formula={1070+g*512} '
|
|
f'match={it_block==1070+g*512} '
|
|
f'flags=0x{flags:04x}')
|
|
|
|
# Read /var inode
|
|
var_inode = 1310721
|
|
var_group = (var_inode-1)//IPG
|
|
var_idx = (var_inode-1)%IPG
|
|
print(f'\n/var inode {var_inode}: group={var_group} idx={var_idx}')
|
|
|
|
gdt_entry = read_virt(BSIZE + var_group*64, 64)
|
|
it_lo = struct.unpack_from('<I', gdt_entry, 8)[0]
|
|
it_hi = struct.unpack_from('<I', gdt_entry, 40)[0]
|
|
it_block = (it_hi<<32)|it_lo
|
|
print(f'GDT it_block: {it_block}')
|
|
|
|
inode_virt = it_block*BSIZE + var_idx*256
|
|
inode_data = read_virt(inode_virt, 256)
|
|
mode = struct.unpack_from('<H', inode_data, 0)[0]
|
|
size = struct.unpack_from('<I', inode_data, 4)[0]
|
|
links = struct.unpack_from('<H', inode_data, 26)[0]
|
|
mtime = struct.unpack_from('<I', inode_data, 16)[0]
|
|
ext_magic = struct.unpack_from('<H', inode_data, 40)[0]
|
|
print(f'mode=0x{mode:04x} size={size} links={links} '
|
|
f'mtime={mtime} ext_magic=0x{ext_magic:04x}')
|
|
print(f'Valid dir: {(mode&0xf000)==0x4000 and ext_magic==0xf30a}')
|
|
|
|
# If valid, list directory contents
|
|
if (mode&0xf000)==0x4000 and ext_magic==0xf30a:
|
|
print()
|
|
print('Directory contents:')
|
|
entries_raw = struct.unpack_from('<H', inode_data, 42)[0]
|
|
depth = struct.unpack_from('<H', inode_data, 46)[0]
|
|
if depth == 0:
|
|
for i in range(min(entries_raw,4)):
|
|
off = 52+i*12
|
|
ee_len = struct.unpack_from('<H', inode_data, off+4)[0]
|
|
ee_hi = struct.unpack_from('<H', inode_data, off+6)[0]
|
|
ee_lo = struct.unpack_from('<I', inode_data, off+8)[0]
|
|
blk = (ee_hi<<32)|ee_lo
|
|
blk_data = read_virt(blk*BSIZE, BSIZE)
|
|
off2 = 0
|
|
while off2 < BSIZE-8:
|
|
ino = struct.unpack_from('<I', blk_data, off2)[0]
|
|
rec_len = struct.unpack_from('<H', blk_data, off2+4)[0]
|
|
name_len= blk_data[off2+6]
|
|
ftype = blk_data[off2+7]
|
|
if rec_len < 8: break
|
|
if ino > 0 and name_len > 0:
|
|
name = blk_data[off2+8:off2+8+name_len].decode('utf-8',errors='replace')
|
|
if name not in ('.','..'):
|
|
tname = {1:'file',2:'dir',7:'link'}.get(ftype,'?')
|
|
print(f' {tname:4s} inode={ino:10d} {name!r}')
|
|
off2 += rec_len
|