import struct

with open('/tmp/fs_meta.img', 'r+b') as f:
    # Patch primary superblock at byte 1024
    f.seek(1024)
    sb = bytearray(f.read(1024))
    
    ro_compat = struct.unpack_from('<I', sb, 100)[0]
    incompat  = struct.unpack_from('<I', sb, 96)[0]
    print(f'ro_compat before: 0x{ro_compat:08x}')
    print(f'incompat  before: 0x{incompat:08x}')
    
    ro_compat &= ~0x400  # clear metadata_csum
    ro_compat &= ~0x010  # clear gdt_csum
    incompat  &= ~0x004  # clear has_journal
    
    struct.pack_into('<I', sb, 100, ro_compat)
    struct.pack_into('<I', sb,  96, incompat)
    struct.pack_into('<I', sb, 1020, 0)  # clear sb checksum
    
    f.seek(1024)
    f.write(bytes(sb))
    print(f'ro_compat after:  0x{ro_compat:08x}')
    print(f'incompat  after:  0x{incompat:08x}')

    # Also patch every GDT entry checksum to 0
    # GDT starts at byte 4096, each entry is 64 bytes
    # checksum is at offset 30 within each entry
    NUM_GROUPS = 35728
    f.seek(4096)
    gdt = bytearray(f.read(NUM_GROUPS * 64))
    for g in range(NUM_GROUPS):
        struct.pack_into('<H', gdt, g*64+30, 0)
    f.seek(4096)
    f.write(bytes(gdt))
    print(f'Zeroed checksums for {NUM_GROUPS} GDT entries')
    
print('Done')
