74 lines
2.4 KiB
Python
74 lines
2.4 KiB
Python
import struct
|
|
|
|
CHUNK = 128*512
|
|
LV_START = 5120000*512
|
|
BSIZE = 4096
|
|
IPG = 8192
|
|
INODE_SZ = 256
|
|
|
|
def phys_from_virt(virt):
|
|
grp = virt//(5*CHUNK)
|
|
in_group = virt%(5*CHUNK)
|
|
chunk_idx= in_group//CHUNK
|
|
intra = in_group%CHUNK
|
|
if chunk_idx == 4: return None
|
|
return LV_START + grp*4*CHUNK + chunk_idx*CHUNK + intra
|
|
|
|
def read_inode(inode_num):
|
|
group = (inode_num-1)//IPG
|
|
idx = (inode_num-1)%IPG
|
|
it_block = 1070 + group*512
|
|
virt = it_block*BSIZE + idx*INODE_SZ
|
|
print(f' inode {inode_num}: group={group} idx={idx}')
|
|
print(f' inode table block: {it_block}')
|
|
print(f' virtual byte: {virt}')
|
|
phys = phys_from_virt(virt)
|
|
print(f' physical byte: {phys}')
|
|
if phys is None:
|
|
print(f' IN METADATA CHUNK')
|
|
return None
|
|
with open('/dev/sda','rb') as f:
|
|
f.seek(phys)
|
|
return f.read(INODE_SZ)
|
|
|
|
# Check known good inode - volumes directory
|
|
print('=== Inode 1585918 (volumes dir) ===')
|
|
data = read_inode(1585918)
|
|
if data:
|
|
mode = struct.unpack_from('<H', data, 0)[0]
|
|
size = struct.unpack_from('<I', data, 4)[0]
|
|
links = struct.unpack_from('<H', data, 26)[0]
|
|
mtime = struct.unpack_from('<I', data, 16)[0]
|
|
ext_magic = struct.unpack_from('<H', data, 40)[0]
|
|
print(f' mode=0x{mode:04x} size={size} links={links}')
|
|
print(f' mtime={mtime} ext_magic=0x{ext_magic:04x}')
|
|
print(f' valid dir: {(mode&0xf000)==0x4000 and ext_magic==0xf30a}')
|
|
|
|
# Now check inode 2 via NBD (which applies translation correctly)
|
|
print()
|
|
print('=== Inode 2 via NBD device ===')
|
|
group = (2-1)//IPG
|
|
idx = (2-1)%IPG
|
|
it_block = 1070 + group*512
|
|
virt = it_block*BSIZE + idx*INODE_SZ
|
|
print(f' virtual byte: {virt}')
|
|
with open('/dev/nbd0','rb') as f:
|
|
f.seek(virt)
|
|
data = f.read(INODE_SZ)
|
|
mode = struct.unpack_from('<H', data, 0)[0]
|
|
links = struct.unpack_from('<H', data, 26)[0]
|
|
mtime = struct.unpack_from('<I', data, 16)[0]
|
|
ext_magic = struct.unpack_from('<H', data, 40)[0]
|
|
print(f' mode=0x{mode:04x} links={links} mtime={mtime}')
|
|
print(f' ext_magic=0x{ext_magic:04x}')
|
|
print(f' first 32 bytes: {data[:32].hex()}')
|
|
|
|
# Compare: what does debugfs think inode 2 contains?
|
|
print()
|
|
print('=== What istat says about inode 2 ===')
|
|
import subprocess
|
|
r = subprocess.run(['istat', '/dev/nbd0', '2'],
|
|
capture_output=True, text=True)
|
|
print(r.stdout[:500])
|
|
print(r.stderr[:200])
|