]> code.delx.au - monosys/blob - apple-time-machine-symlink.py
multiboot: memtest
[monosys] / apple-time-machine-symlink.py
1 #!/usr/bin/env python2
2
3 # This tool tries to parse the weird hardlink format Apple uses for Time Machine
4 # The goal is to recover data from a Time Machine backup without a Mac
5
6 import math
7 import stat
8 import os
9 import sys
10
11 def find_lookup_dir(path):
12 while path != "/":
13 lookup_dir = os.path.join(path, ".HFS+ Private Directory Data\r")
14 if os.path.isdir(lookup_dir):
15 return lookup_dir
16 path = os.path.split(path)[0]
17 raise Exception("Could not find HFS+ link dir")
18
19 def resolve_path(lookup_dir, path):
20 st = os.lstat(path)
21 if stat.S_ISREG(st.st_mode) and st.st_size == 0 and st.st_nlink > 1000:
22 return os.path.join(lookup_dir, "dir_%d" % st.st_nlink)
23 else:
24 return path
25
26
27 def process_directory(lookup_dir, dest, path):
28 if os.path.islink(dest):
29 os.unlink(dest)
30 if not os.path.isdir(dest):
31 os.mkdir(dest)
32 path = resolve_path(lookup_dir, path)
33
34 for filename in os.listdir(path):
35 full_filename = os.path.join(path, filename)
36 full_filename = resolve_path(lookup_dir, full_filename)
37 dest_filename = os.path.join(dest, filename)
38
39 if os.path.isdir(full_filename):
40 process_directory(lookup_dir, dest_filename, full_filename)
41 else:
42 if os.path.islink(dest_filename):
43 os.unlink(dest_filename)
44 if not os.path.isdir(dest_filename):
45 os.symlink(full_filename, dest_filename)
46
47 def main(dest, path):
48 lookup_dir = find_lookup_dir(path)
49 process_directory(lookup_dir, dest, path)
50
51 def print_usage_exit():
52 print >>sys.stderr, "Usage: %s dest path" % sys.argv[0]
53 sys.exit(1)
54
55 if __name__ == "__main__":
56 if len(sys.argv) != 3:
57 print_usage_exit()
58
59 dest = sys.argv[1]
60 path = sys.argv[2]
61
62 main(dest, path)
63