This is just my attempt at creating something for my own use, made specifically for the problem I had. Maybe it will be useful for someone else, either to use directly or to modify for their own needs. Or maybe it won't. It is provided as is; I do not guarantee anything whatsoever. Only tested on Mac OS 10.11. Probably won't work on Windows. Expects a build of Perl with 64-bit integers if the disk is big enough.
This is a program to read HFS+ filesystems (Mac OS Extended, default on OS 8.1 through 10.12 and for Time Machine drives through 10.15), which I wrote to recover data from an external hard drive (Time Machine backup) that I had. The specific issue I had (and therefore the issue it tries to work around) was the record offsets in the catalog tree being wrong. The relevant message fsck_hfs
gave me was:
hfs_swap_BTNode: offsets 26 and 27 out of order (0x0000, 0x0000) Invalid node structure (4, 84706)
(4 = catalog file (3 would be extents overflow, 8 would be attributes), 84706 is the node number of one of the nodes that was corrupted.)
This may also be useful if you want to read data from a Mac-formatted disk but don't have a driver, to read data from a Time Machine backup if you don't have an up-to-date driver, or to examine metadata that you can't normally access.
It does not make any attempt to be able to recover files that were deleted normally.
Everything is written in perl (so perl must be installed) and intended to run from the command line. (Also I'm pretty sure a version of Perl compiled with 64-bit integers is required.)
In each command, the disk parameter is a path to the device file (something in /dev/
, if you're on Unix/Linux/Mac; might not work on Windows) or to a copy of the disk made with a program like dd. path-on-disk can either start with a /
, in which case it's relative to the root of the disk, or a catalog ID (CNID) followed by a slash (the slash is always necessary).
To examine the disk's header/metadata:
perl header.pl disk
To get information/metadata about a file on the disk (and list files in a directory):
perl info.pl disk path-on-disk
To get information about what's in a particular node in a B-tree (including a hexdump of the node):
perl node-info.pl disk (catalog|extents|attr) node
To copy a file from the disk:
perl extract.pl disk path-on-disk path-to-extract-to
path-to-extract-to should be a path on the local disk (i.e., not the disk you're trying to recover data from). The program will not overwrite any existing files, but you can specify an existing directory to resume restoration if the original restoration was interrupted.
This program is mostly based on information found at https://developer.apple.com/legacy/library/technotes/tn/tn1150.html
Information about the attributes file came from https://digital-forensics.sans.org/media/FOR518-Reference-Sheet.pdf
I couldn't find any information about how directory hard links work (used by Time Machine), but they seem to have a type of fdrp
, a creator of MACS
, (although I think this is also the type of aliases?) and the inode number in the "special" field in the permissions structure (same as normal hard links). The actual data is stored in /.HFS+ Private Directory Data\x0d/dir_1234
where 1234 is the inode number, and \x0d
is a return character. At least on my disk, the inode number also seems to match the catalog ID of the directory with the actual data (i.e., dir_1234
has a CNID of 1234). (The program assumes this is the case, so it might not work on some disks.)
Code and Mercurial repository (.tgz) (332K; 1.2M when uncompressed) (remember that this is something I made primarily for myself and is provided as-is and has not been extensively tested)