CHUNK    = 128*512  # 64KB
LV_START = 5120000*512
BSIZE    = 4096

# Block 5251104, virtual byte = 5251104 * 4096 = 21508521984
# group=65638, chunk_idx=4, intra=0

# Physical layout: each group of 5 virtual chunks occupies
# 5*CHUNK bytes on the physical disk (md0)
# group 65638 starts at:
group = 65638
group_phys_start = LV_START + group * 5 * CHUNK
print(f'Group {group} physical start: {group_phys_start}')
print()

import struct

with open('/dev/md0','rb') as f:
    # Read all 5 chunks of this group
    f.seek(group_phys_start)
    all_chunks = f.read(5*CHUNK)

for ci in range(5):
    chunk = all_chunks[ci*CHUNK:(ci+1)*CHUNK]
    nonzero = sum(1 for b in chunk if b != 0)
    # Try first 32 bytes as directory
    ino = struct.unpack_from('<I', chunk, 0)[0]
    rec = struct.unpack_from('<H', chunk, 4)[0]
    nl  = chunk[6]
    ft  = chunk[7]
    print(f'Chunk {ci}: nonzero={nonzero}/{CHUNK}', end='')
    if 10 < ino < 500_000_000 and 8 <= rec <= 256 and 0 < nl < 32 and ft in (1,2,7):
        name = chunk[8:8+nl].decode('utf-8',errors='replace')
        print(f' POSSIBLE DIR: inode={ino} name={name!r}', end='')
    print()

# The data chunks (0-3) map to virtual chunks as follows:
# Our translation: virtual chunk N -> physical chunk N (for N<4)
# So physical chunks 0,1,2,3 = virtual chunks 0,1,2,3
# And physical chunk 4 = the metadata chunk we skip

# But what if our anchor points were right (FAT32 and LV)
# yet the internal mapping within the LV is different?
# What if the PERC uses a different chunk as metadata inside the LV?

# Our two anchors:
# FAT32 VBR at PERC virtual 2048 -> md0 sector 1664
# LV start at PERC virtual 6400000 -> md0 sector 5120000

# These are BEFORE the LV. Inside the LV, could the chunk order differ?
# What if inside the LV the metadata chunk is chunk 0, not chunk 4?

# Test: read chunk 0 of group 65638 as directory
chunk0 = all_chunks[0:CHUNK]
print()
print('Chunk 0 as directory:')
off = 0
while off < BSIZE-8:
    ino     = struct.unpack_from('<I', chunk0, off)[0]
    rec_len = struct.unpack_from('<H', chunk0, off+4)[0]
    name_len= chunk0[off+6]
    ftype   = chunk0[off+7]
    if rec_len < 8: break
    if ino > 0 and name_len > 0:
        name = chunk0[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

# Test each chunk as potential /var directory
print()
for ci in range(5):
    chunk = all_chunks[ci*CHUNK:(ci+1)*CHUNK]
    off = 0
    entries = []
    while off < BSIZE-8:
        ino     = struct.unpack_from('<I', chunk, off)[0]
        rec_len = struct.unpack_from('<H', chunk, off+4)[0]
        name_len= chunk[off+6]
        ftype   = chunk[off+7]
        if rec_len < 8: break
        if 10 < ino < 500_000_000 and name_len > 0 and ftype in (1,2,7):
            name = chunk[off+8:off+8+name_len].decode('utf-8',errors='replace')
            if name.isprintable():
                entries.append((ino, name, ftype))
        off += rec_len
    if entries:
        print(f'Chunk {ci} has {len(entries)} directory entries:')
        for ino, name, ftype in entries[:5]:
            tname = {1:'file',2:'dir',7:'link'}.get(ftype,'?')
            print(f'  {tname} inode={ino} {name!r}')
