Skip to content

Instantly share code, notes, and snippets.

@s4y
Created March 7, 2019 08:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save s4y/725955949a4cefe01fb253b1ec1d6c6c to your computer and use it in GitHub Desktop.
Save s4y/725955949a4cefe01fb253b1ec1d6c6c to your computer and use it in GitHub Desktop.
Recover data from Apple backup files
#!/usr/bin/env python3
# See https://www.downtowndougbrown.com/2013/06/legacy-apple-backup-file-format-on-floppy-disks/
import os
import pathlib
import struct
import sys
f = open(sys.argv[1], 'rb')
magic, disk_n, n_disks, _, _, volume_name, _, size = struct.unpack_from('>xx4sHHII32pII', f.read(0x200))
assert magic == b'CMWL'
# Skip boot blocks
f.read(0x400)
size -= 0x600
while size:
magic, _, _, _, filename, part_n, folder_flags, valid, created, modified, data_length, resource_length, data_length_this_disk, resource_length_this_disk, path_length = struct.unpack_from('>xx4sHII32pHBB34xIIIIIIH', f.read(0x70))
assert magic == b'RLDW'
is_folder = folder_flags & (1<<7) != 0
full_path = f.read(path_length)
data_fork = f.read(data_length_this_disk)
resource_fork = f.read(resource_length_this_disk)
total_size = 0x70 + path_length + data_length_this_disk + resource_length_this_disk
padding = 0x200 - (total_size % 0x200) if (total_size % 0x200) else 0
f.read(padding)
size -= total_size + padding
nix_path = pathlib.Path(*full_path.decode('macroman').split(':'))
if len(nix_path.parts) > 1:
os.makedirs(nix_path if is_folder else nix_path.parent, exist_ok=True)
print("writing to{} {}, part {}, df={} rf={}".format(" folder" if is_folder else "", nix_path, part_n, len(data_fork), len(resource_fork)))
open_flags = 'ab' if part_n > 1 else 'wb'
if not is_folder:
with open(nix_path, open_flags) as of:
of.write(data_fork)
if resource_fork:
with open(nix_path.joinpath('..namedfork', 'rsrc'), open_flags) as of:
of.write(resource_fork)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment