Mac OS X Internals: A Systems Approach

12.6. The HFS Wrapper

An HFS+ volume may be embedded in an HFS wrapper. After the introduction of HFS+ with Mac OS 8.1, Apple had to ensure that computers with no HFS+ support in ROM were able to boot Mac OS 8.1 and newer systems from an HFS+ volume. The solution Apple used was to wrap the HFS+ volume so that it appeared as an HFS volume to the ROM. The System file residing on the HFS volume would only contain code to find the offset of the embedded HFS+ volume, mount it, and perform the actual boot using the System file on the HFS+ volume.

In HFS-embedded HFS+ volumes, the HFS+ volume header does not reside at a 1024-byte offset from the beginning of the volumethe HFS master directory block (MDB) does. The MDB is the HFS analog of the volume header. It contains enough information so that the HFS+ volume header's location can be computed. There is also an alternate MDB that is analogous to the alternate volume header.

Let us create an embedded HFS+ volume and examine its contents.

% hdiutil create -size 16m -layout NONE /tmp/hfswrapper.dmg ... created: /tmp/hfswrapper.dmg % hdiutil attach -nomount /tmp/hfswrapper.dmg ... /dev/disk10

Note the device node path (/dev/disk10 in this example) printed by hdiutil. Make sure you use the correct device path; otherwise, you may destroy existing data on a volume.

The -w option to newfs_hfs adds an HFS wrapper around the HFS+ file system that newfs_hfs creates. Similarly, the -w option to mount_hfs causes the wrapper volume to be mounted instead of the embedded HFS+ volume.

% newfs_hfs -w -v HFSWrapper /dev/rdisk10 Initialized /dev/rdisk10 as a 16 MB HFS Plus Volume % mkdir /tmp/mnt % mount_hfs -w /dev/disk10 /tmp/mnt % ls -l /tmp/mnt total 64 -rwxr-xr-x 1 amit wheel 4096 17 Apr 17:40 Desktop DB -rwxr-xr-x 1 amit wheel 0 17 Apr 17:40 Desktop DF -rwxr-xr-x 1 amit wheel 0 17 Apr 17:40 Finder -rwxr-xr-x 1 amit wheel 1781 17 Apr 17:40 ReadMe -rwxr-xr-x 1 amit wheel 0 17 Apr 17:40 System

The wrapper volume is created with five files in its root directory. The System file's data fork is empty, but its resource fork contains boot code. The Finder file has both forks empty. All files are marked invisible except ReadMe. When such a volume is used on a system with no HFS+ support (e.g., a system earlier than Mac OS 8.1), the user would see a volume with only the ReadMe file on it. The file explains why the user cannot see any files on the volume and the steps needed to access them.

Figure 129 shows the layout of an HFS wrapper volume containing an embedded HFS+ volume.

Figure 129. An HFS wrapper volume containing an embedded HFS+ volume

Let us unmount the wrapper volume and mount the HFS+ volume within it. Unless explicitly instructed to mount the wrapper volume, Mac OS X will mount the embedded HFS+ volume.

$ umount /tmp/mnt $ hdiutil detach disk10 "disk10" unmounted. "disk10" ejected. $ open /tmp/hfswrapper.dmg $ mount ... /dev/disk10 on /Volumes/HFSWrapper (local, nodev, suid, mounted by amit)

When used to display the volume header of an embedded HFS+ volume, hfsdebug also displays the contents of the MDB (Figure 1210).

Figure 1210. The contents of a master directory block

$ sudo hfsdebug -d /dev/rdisk10 -v HFS Plus Volume with HFS Wrapper Embedded offset = 88 bytes Wrapper volume size = 16376.00 KB/15.99 MB/0.02 GB Embedded volume size = 16336.00 KB/15.95 MB/0.02 GB # HFS Wrapper Master Directory Block drSigWord = $4244 (BD) drCrDate = Sun Oct 9 18:17:08 2005 drLsMod = Sun Oct 9 18:17:08 2005 drAtrb = 1000001100000000 . kHFSVolumeUnmounted (volume was successfully unmounted) . kHFSVolumeSparedBlocks (volume has bad blocks spared) . kHFSVolumeSoftwareLock (volume is locked by software) drNmFls = 5 drVBMSt = 0x3 (3) drAllocPtr = 0 (0) drNmAlBlks = 4094 drAlBlkSiz = 4096 bytes drClpSiz = 4096 drAlBlSt = 0x8 (8) drNxtCNID = 21 drFreeBks = 0 drVN = HFSWrapper (10 characters) drVolBkUp = Fri Jan 1 00:00:00 1904 drVSeqNum = 0 drWrCnt = 3 drXTClpSiz = 4096 drNmRtDirs = 0 drFilCnt = 5 drDirCnt = 0 EmbedSigWord = $482B (H+) # Finder Info drFndrInfo [0] = 0x2 drFndrInfo [1] = 0 drFndrInfo [2] = 0 drFndrInfo [3] = 0 drFndrInfo [4] = 0x656e6300 drFndrInfo [5] = 0 drFndrInfo [6] = 0x8a0d0159 drFndrInfo [7] = 0xf39492fd drEmbedExtent = start count 0x000a 0x0ff4 drXTFlSize = 4096 blocks drXTExtRec = start count 0x0000 0x0001 0x0000 0x0000 0x0000 0x0000 drCTFlSize = 4096 blocks drCTExtRec = start count 0x0001 0x0001 0x0000 0x0000 0x0000 0x0000 # HFS Plus Volume Header ... fileCount = 1 folderCount = 3 /* not including the root folder */ blockSize = 4096 totalBlocks = 4084 freeBlocks = 4017 ...

Figure 1210 shows that the embedded signature field (EmbedSigWord) contains H+ to indicate the presence of an embedded volume. Note that the wrapper volume has no free blocks, as is indicated by the MDB's drFreeBks field. This is because from the HFS volume's standpoint, all space is already allocatedit is used by the embedded volume. Moreover, the embedded volume's space is actually marked as "bad" in the HFS volume, as indicated by the kHFSVolumeSparedBlocks bit being set in the MDB's drAtrb field. This prevents the embedded volume's space from being recovered or otherwise used in any way. The MDB's drNmFls field is 5, indicating that the wrapper volume contains 5 files.

Категории