96 lines
3.1 KiB
Python
96 lines
3.1 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_phys(phys, length):
|
|
with open('/dev/sda','rb') as f:
|
|
f.seek(phys)
|
|
return f.read(length)
|
|
|
|
def read_virt(virt, length):
|
|
phys = phys_from_virt(virt)
|
|
if phys is None: return b'\x00'*length
|
|
return read_phys(phys, length)
|
|
|
|
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
|
|
phys = phys_from_virt(virt)
|
|
if phys is None: return None
|
|
return read_phys(phys, INODE_SZ)
|
|
|
|
def get_extents(inode_data):
|
|
blocks = []
|
|
if struct.unpack_from('<H', inode_data, 40)[0] != 0xf30a:
|
|
return blocks
|
|
entries = 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,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]
|
|
start = (ee_hi<<32)|ee_lo
|
|
for b in range(min(ee_len,8)):
|
|
blocks.append(start+b)
|
|
return blocks
|
|
|
|
def list_dir(inode_num):
|
|
data = read_inode(inode_num)
|
|
if not data: return []
|
|
entries = []
|
|
for blk in get_extents(data):
|
|
blk_data = read_virt(blk*BSIZE, BSIZE)
|
|
off = 0
|
|
while off < BSIZE-8:
|
|
ino = struct.unpack_from('<I', blk_data, off)[0]
|
|
rec_len = struct.unpack_from('<H', blk_data, off+4)[0]
|
|
name_len= blk_data[off+6]
|
|
ftype = blk_data[off+7]
|
|
if rec_len < 8: break
|
|
if ino > 0 and name_len > 0:
|
|
name = blk_data[off+8:off+8+name_len].decode('utf-8',errors='replace')
|
|
entries.append((ino, name, ftype))
|
|
off += rec_len
|
|
return entries
|
|
|
|
# List root directory
|
|
print('Root directory (inode 2):')
|
|
for ino, name, ftype in list_dir(2):
|
|
tname = {1:'file',2:'dir',7:'link'}.get(ftype,'?')
|
|
print(f' {tname:4s} {name:20s} inode={ino}')
|
|
|
|
# Find var
|
|
print()
|
|
for ino, name, ftype in list_dir(2):
|
|
if name == 'var':
|
|
print(f'Found /var at inode {ino}')
|
|
print('Contents of /var:')
|
|
for i2, n2, f2 in list_dir(ino):
|
|
tname = {1:'file',2:'dir',7:'link'}.get(f2,'?')
|
|
print(f' {tname:4s} {n2:20s} inode={i2}')
|
|
|
|
# Find var/lib
|
|
for i2, n2, f2 in list_dir(ino):
|
|
if n2 == 'lib':
|
|
print(f'\nFound /var/lib at inode {i2}')
|
|
print('Contents of /var/lib:')
|
|
for i3, n3, f3 in list_dir(i2):
|
|
tname = {1:'file',2:'dir',7:'link'}.get(f3,'?')
|
|
print(f' {tname:4s} {n3:20s} inode={i3}')
|