python3 -c "
import struct

CHUNK = 128*512
LV_START = 5120000*512
BSIZE = 4096
GDT_ENTRY = 64
BPG = 32768
NUM_GROUPS = 35728

def raw_read(virt_offset, length):
    result = bytearray(length)
    pos = virt_offset
    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_offset
            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 full backup GDT from group 1 (block 32769)
backup_start_virt = (BPG + 1) * BSIZE
gdt_size = NUM_GROUPS * GDT_ENTRY
print(f'Reading backup GDT: {gdt_size//1024}KB from virtual byte {backup_start_virt}')
backup_gdt = raw_read(backup_start_virt, gdt_size)

# Verify it looks sane
for i in [0,1,2,100,1000,10000]:
    e = backup_gdt[i*GDT_ENTRY:(i+1)*GDT_ENTRY]
    bb = struct.unpack_from('<I',e,0)[0]
    ib = struct.unpack_from('<I',e,4)[0]
    it = struct.unpack_from('<I',e,8)[0]
    cs = struct.unpack_from('<H',e,30)[0]
    print(f'  Backup group {i}: bb={bb} ib={ib} it={it} csum=0x{cs:04x}')

# Save it
with open('/tmp/backup_gdt.bin','wb') as f:
    f.write(backup_gdt)
print(f'Saved {len(backup_gdt)} bytes to /tmp/backup_gdt.bin')
"
