diff --git a/CHANGES.txt b/CHANGES.txt
index 48697cd17cd5f96091ce8634939725920cb2e80f..af19365a5d607a0715b63c795c6f76149234e948 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -22,6 +22,8 @@ Rob Joyce and Judson Powers.
 directory have an unknown file name type (instead of being equal
 to meta type).  (Bug: 2389901). Reported by Barry Grundy.
 
+1/11/09: Update: Support for HFS Wrappers was added.  Patch by Rob Joyce.
+
 
 ---------------- VERSION 3.0.0 -------------- 
 0/00/00: Update: Many, many, many API changes.
diff --git a/tsk3/fs/hfs.c b/tsk3/fs/hfs.c
index ed7486600c083f9117261d5b35b598657fca5e00..fe18b22a8e48db75111d651bdd62cca5bf6fd688 100644
--- a/tsk3/fs/hfs.c
+++ b/tsk3/fs/hfs.c
@@ -938,7 +938,7 @@ hfs_ext_find_extent_record_attr(HFS_INFO * hfs, uint32_t cnid,
                 tsk_errno = TSK_ERR_FS_READ;
             }
             snprintf(tsk_errstr2, TSK_ERRSTR_L,
-                     "hfs_ext_find_extent_record_attr: Error reading header");
+                "hfs_ext_find_extent_record_attr: Error reading header");
             return 0;
         }
     }
@@ -985,7 +985,8 @@ hfs_ext_find_extent_record_attr(HFS_INFO * hfs, uint32_t cnid,
                 tsk_errno = TSK_ERR_FS_READ;
             }
             snprintf(tsk_errstr2, TSK_ERRSTR_L,
-                     "hfs_ext_find_extent_record_attr: Error reading node %d at offset %"PRIuOFF, cur_node, cur_off);
+                "hfs_ext_find_extent_record_attr: Error reading node %d at offset %"
+                PRIuOFF, cur_node, cur_off);
             free(node);
             return 1;
         }
@@ -1026,8 +1027,8 @@ hfs_ext_find_extent_record_attr(HFS_INFO * hfs, uint32_t cnid,
                 if (rec_off > nodesize) {
                     tsk_errno = TSK_ERR_FS_GENFS;
                     snprintf(tsk_errstr, TSK_ERRSTR_L,
-                             "hfs_ext_find_extent_record_attr: offset of record %d in index node %d too large (%zu vs %"PRIu16")",
-                             rec, cur_node, rec_off, nodesize);
+                        "hfs_ext_find_extent_record_attr: offset of record %d in index node %d too large (%zu vs %"
+                        PRIu16 ")", rec, cur_node, rec_off, nodesize);
                     free(node);
                     return 1;
                 }
@@ -1048,11 +1049,12 @@ hfs_ext_find_extent_record_attr(HFS_INFO * hfs, uint32_t cnid,
                 /* if all keys are larger than our key, select the leftmost key */
                 if ((cmp <= 0) || (next_node == 0)) {
                     int keylen = tsk_getu16(fs->endian, key->key_len);
-                    if (rec_off+keylen > nodesize) {
+                    if (rec_off + keylen > nodesize) {
                         tsk_errno = TSK_ERR_FS_GENFS;
                         snprintf(tsk_errstr, TSK_ERRSTR_L,
-                                 "hfs_ext_find_extent_record_attr: offset and keylenth of record %d in index node %d too large (%zu vs %"PRIu16")",
-                                 rec, cur_node, rec_off+keylen, nodesize);
+                            "hfs_ext_find_extent_record_attr: offset and keylenth of record %d in index node %d too large (%zu vs %"
+                            PRIu16 ")", rec, cur_node, rec_off + keylen,
+                            nodesize);
                         free(node);
                         return 1;
                     }
@@ -1063,13 +1065,13 @@ hfs_ext_find_extent_record_attr(HFS_INFO * hfs, uint32_t cnid,
                     break;
                 }
             }
-            
+
             // check if we found any relevant node
             if (next_node == 0) {
                 tsk_errno = TSK_ERR_FS_GENFS;
                 snprintf(tsk_errstr, TSK_ERRSTR_L,
-                         "hfs_ext_find_extent_record_attr: did not find any keys for %d in index node %d",
-                         cnid, cur_node);
+                    "hfs_ext_find_extent_record_attr: did not find any keys for %d in index node %d",
+                    cnid, cur_node);
                 free(node);
                 return 1;
             }
@@ -1094,8 +1096,8 @@ hfs_ext_find_extent_record_attr(HFS_INFO * hfs, uint32_t cnid,
                 if (rec_off > nodesize) {
                     tsk_errno = TSK_ERR_FS_GENFS;
                     snprintf(tsk_errstr, TSK_ERRSTR_L,
-                             "hfs_ext_find_extent_record_attr: offset of record %d in leaf node %d too large (%zu vs %"PRIu16")",
-                             rec, cur_node, rec_off, nodesize);
+                        "hfs_ext_find_extent_record_attr: offset of record %d in leaf node %d too large (%zu vs %"
+                        PRIu16 ")", rec, cur_node, rec_off, nodesize);
                     free(node);
                     return 1;
                 }
@@ -1120,33 +1122,36 @@ hfs_ext_find_extent_record_attr(HFS_INFO * hfs, uint32_t cnid,
                     break;
 
                 keylen = tsk_getu16(fs->endian, key->key_len);
-                if (rec_off+keylen > nodesize) {
+                if (rec_off + keylen > nodesize) {
                     tsk_errno = TSK_ERR_FS_GENFS;
                     snprintf(tsk_errstr, TSK_ERRSTR_L,
-                             "hfs_ext_find_extent_record_attr: offset and keylenth of record %d in leaf node %d too large (%zu vs %"PRIu16")",
-                             rec, cur_node, rec_off+keylen, nodesize);
+                        "hfs_ext_find_extent_record_attr: offset and keylenth of record %d in leaf node %d too large (%zu vs %"
+                        PRIu16 ")", rec, cur_node, rec_off + keylen,
+                        nodesize);
                     free(node);
                     return 1;
                 }
 
                 // get the starting offset of this extent
                 ext_off = tsk_getu32(fs->endian, key->start_block);
-                
+
                 // convert the extents to the TSK format
                 extents = (hfs_extents *) & node[rec_off + keylen];
-                
+
                 attr_run =
                     hfs_extents_to_attr(fs, extents->extents, ext_off);
                 if (attr_run == NULL) {
-                    strncat(tsk_errstr2, " - hfs_ext_find_extent_record_attr",
-                            TSK_ERRSTR_L - strlen(tsk_errstr2));
+                    strncat(tsk_errstr2,
+                        " - hfs_ext_find_extent_record_attr",
+                        TSK_ERRSTR_L - strlen(tsk_errstr2));
                     free(node);
                     return 1;
                 }
 
                 if (tsk_fs_attr_add_run(fs, a_attr, attr_run)) {
-                    strncat(tsk_errstr2, " - hfs_ext_find_extent_record_attr",
-                            TSK_ERRSTR_L - strlen(tsk_errstr2));
+                    strncat(tsk_errstr2,
+                        " - hfs_ext_find_extent_record_attr",
+                        TSK_ERRSTR_L - strlen(tsk_errstr2));
                     free(node);
                     return 1;
                 }
@@ -1255,7 +1260,8 @@ hfs_cat_get_record_offset(HFS_INFO * hfs, hfs_cat_key * needle)
                 tsk_errno = TSK_ERR_FS_READ;
             }
             snprintf(tsk_errstr2, TSK_ERRSTR_L,
-                     "hfs_cat_get_record_offset: Error reading node %d at offset %"PRIuOFF, cur_node, cur_off);
+                "hfs_cat_get_record_offset: Error reading node %d at offset %"
+                PRIuOFF, cur_node, cur_off);
             free(node);
             return 0;
         }
@@ -1294,8 +1300,8 @@ hfs_cat_get_record_offset(HFS_INFO * hfs, hfs_cat_key * needle)
                 if (rec_off > nodesize) {
                     tsk_errno = TSK_ERR_FS_GENFS;
                     snprintf(tsk_errstr, TSK_ERRSTR_L,
-                             "hfs_cat_get_record_offset: offset of record %d in index node %d too large (%zu vs %"PRIu16")",
-                             rec, cur_node, rec_off, nodesize);
+                        "hfs_cat_get_record_offset: offset of record %d in index node %d too large (%zu vs %"
+                        PRIu16 ")", rec, cur_node, rec_off, nodesize);
                     free(node);
                     return 1;
                 }
@@ -1316,8 +1322,9 @@ hfs_cat_get_record_offset(HFS_INFO * hfs, hfs_cat_key * needle)
                     if (rec_off + keylen > nodesize) {
                         tsk_errno = TSK_ERR_FS_GENFS;
                         snprintf(tsk_errstr, TSK_ERRSTR_L,
-                                 "hfs_cat_get_record_offset: offset of record and keylength %d in index node %d too large (%zu vs %"PRIu16")",
-                                 rec, cur_node, rec_off+keylen, nodesize);
+                            "hfs_cat_get_record_offset: offset of record and keylength %d in index node %d too large (%zu vs %"
+                            PRIu16 ")", rec, cur_node, rec_off + keylen,
+                            nodesize);
                         free(node);
                         return 0;
                     }
@@ -1332,8 +1339,8 @@ hfs_cat_get_record_offset(HFS_INFO * hfs, hfs_cat_key * needle)
             if (next_node == 0) {
                 tsk_errno = TSK_ERR_FS_GENFS;
                 snprintf(tsk_errstr, TSK_ERRSTR_L,
-                         "hfs_cat_get_record_offset: did not find any keys in index node %d",
-                         cur_node);
+                    "hfs_cat_get_record_offset: did not find any keys in index node %d",
+                    cur_node);
                 is_done = 1;
                 break;
             }
@@ -1356,8 +1363,8 @@ hfs_cat_get_record_offset(HFS_INFO * hfs, hfs_cat_key * needle)
                 if (rec_off > nodesize) {
                     tsk_errno = TSK_ERR_FS_GENFS;
                     snprintf(tsk_errstr, TSK_ERRSTR_L,
-                             "hfs_cat_get_record_offset: offset of record %d in leaf node %d too large (%zu vs %"PRIu16")",
-                             rec, cur_node, rec_off, nodesize);
+                        "hfs_cat_get_record_offset: offset of record %d in leaf node %d too large (%zu vs %"
+                        PRIu16 ")", rec, cur_node, rec_off, nodesize);
                     free(node);
                     return 0;
                 }
@@ -1388,8 +1395,8 @@ hfs_cat_get_record_offset(HFS_INFO * hfs, hfs_cat_key * needle)
                 if (rec_off2 > nodesize) {
                     tsk_errno = TSK_ERR_FS_GENFS;
                     snprintf(tsk_errstr, TSK_ERRSTR_L,
-                             "hfs_cat_get_record_offset: offset of record and keylength %d in leaf node %d too large (%zu vs %"PRIu16")",
-                             rec, cur_node, rec_off2, nodesize);
+                        "hfs_cat_get_record_offset: offset of record and keylength %d in leaf node %d too large (%zu vs %"
+                        PRIu16 ")", rec, cur_node, rec_off2, nodesize);
                     free(node);
                     return 0;
                 }
@@ -1438,7 +1445,8 @@ hfs_cat_read_thread_record(HFS_INFO * hfs, TSK_OFF_T off,
             tsk_errno = TSK_ERR_FS_READ;
         }
         snprintf(tsk_errstr2, TSK_ERRSTR_L,
-                 "hfs_cat_read_thread_record: Error reading catalog offset %"PRIuOFF" (header)", off);
+            "hfs_cat_read_thread_record: Error reading catalog offset %"
+            PRIuOFF " (header)", off);
         return 1;
     }
 
@@ -1471,7 +1479,8 @@ hfs_cat_read_thread_record(HFS_INFO * hfs, TSK_OFF_T off,
             tsk_errno = TSK_ERR_FS_READ;
         }
         snprintf(tsk_errstr2, TSK_ERRSTR_L,
-                 "hfs_cat_read_thread_record: Error reading catalog offset %"PRIuOFF" (name)", off+10);
+            "hfs_cat_read_thread_record: Error reading catalog offset %"
+            PRIuOFF " (name)", off + 10);
         return 1;
     }
 
@@ -1501,7 +1510,8 @@ hfs_cat_read_file_folder_record(HFS_INFO * hfs, TSK_OFF_T off,
             tsk_errno = TSK_ERR_FS_READ;
         }
         snprintf(tsk_errstr2, TSK_ERRSTR_L,
-                 "hfs_cat_read_file_folder_record: Error reading catalog offset %"PRIuOFF" (header)", off);
+            "hfs_cat_read_file_folder_record: Error reading catalog offset %"
+            PRIuOFF " (header)", off);
         return 1;
     }
 
@@ -1515,7 +1525,8 @@ hfs_cat_read_file_folder_record(HFS_INFO * hfs, TSK_OFF_T off,
                 tsk_errno = TSK_ERR_FS_READ;
             }
             snprintf(tsk_errstr2, TSK_ERRSTR_L,
-                     "hfs_cat_read_file_folder_record: Error reading catalog offset %"PRIuOFF" (folder)", off);
+                "hfs_cat_read_file_folder_record: Error reading catalog offset %"
+                PRIuOFF " (folder)", off);
             return 1;
         }
     }
@@ -1530,7 +1541,8 @@ hfs_cat_read_file_folder_record(HFS_INFO * hfs, TSK_OFF_T off,
                 tsk_errno = TSK_ERR_FS_READ;
             }
             snprintf(tsk_errstr2, TSK_ERRSTR_L,
-                     "hfs_cat_read_file_folder_record: Error reading catalog offset %"PRIuOFF" (file)", off);
+                "hfs_cat_read_file_folder_record: Error reading catalog offset %"
+                PRIuOFF " (file)", off);
             return 1;
         }
     }
@@ -1579,7 +1591,8 @@ hfs_cat_file_lookup(HFS_INFO * hfs, TSK_INUM_T inum, HFS_ENTRY * entry)
         (inum == HFS_ATTRIBUTES_FILE_ID)) {
         tsk_errno = TSK_ERR_FS_GENFS;
         snprintf(tsk_errstr, TSK_ERRSTR_L,
-                 "hfs_cat_file_lookup: Called on special file: %"PRIuINUM, inum);
+            "hfs_cat_file_lookup: Called on special file: %" PRIuINUM,
+            inum);
         return 1;
     }
 
@@ -1592,13 +1605,15 @@ hfs_cat_file_lookup(HFS_INFO * hfs, TSK_INUM_T inum, HFS_ENTRY * entry)
     /* look up the thread record */
     off = hfs_cat_get_record_offset(hfs, &key);
     if (off == 0) {
-        snprintf(tsk_errstr2, TSK_ERRSTR_L, " hfs_cat_file_lookup: thread for file (%"PRIuINUM")", inum);
+        snprintf(tsk_errstr2, TSK_ERRSTR_L,
+            " hfs_cat_file_lookup: thread for file (%" PRIuINUM ")", inum);
         return 1;
     }
 
     /* read the thread record */
     if (hfs_cat_read_thread_record(hfs, off, &thread)) {
-        snprintf(tsk_errstr2, TSK_ERRSTR_L, " hfs_cat_file_lookup: file (%"PRIuINUM")", inum);
+        snprintf(tsk_errstr2, TSK_ERRSTR_L,
+            " hfs_cat_file_lookup: file (%" PRIuINUM ")", inum);
         return 1;
     }
 
@@ -1613,13 +1628,15 @@ hfs_cat_file_lookup(HFS_INFO * hfs, TSK_INUM_T inum, HFS_ENTRY * entry)
     /* look up the record */
     off = hfs_cat_get_record_offset(hfs, &key);
     if (off == 0) {
-        snprintf(tsk_errstr2, TSK_ERRSTR_L, " hfs_cat_file_lookup: file (%"PRIuINUM")", inum);
+        snprintf(tsk_errstr2, TSK_ERRSTR_L,
+            " hfs_cat_file_lookup: file (%" PRIuINUM ")", inum);
         return 1;
     }
 
     /* read the record */
     if (hfs_cat_read_file_folder_record(hfs, off, &record)) {
-        snprintf(tsk_errstr2, TSK_ERRSTR_L, " hfs_cat_file_lookup: file (%"PRIuINUM")", inum);
+        snprintf(tsk_errstr2, TSK_ERRSTR_L,
+            " hfs_cat_file_lookup: file (%" PRIuINUM ")", inum);
         return 1;
     }
 
@@ -2337,14 +2354,14 @@ hfs_load_attrs(TSK_FS_FILE * fs_file)
             TSK_ERRSTR_L - strlen(tsk_errstr2));
         return 1;
     }
-    
+
     // if not a file, then make an empty entry
     if (fs_file->meta->type != TSK_FS_META_TYPE_REG) {
         if (tsk_fs_attr_set_run(fs_file, fs_attr, NULL, NULL,
-                                TSK_FS_ATTR_TYPE_DEFAULT, TSK_FS_ATTR_ID_DEFAULT,
-                                0, 0, 0, 0)) {
+                TSK_FS_ATTR_TYPE_DEFAULT, TSK_FS_ATTR_ID_DEFAULT,
+                0, 0, 0, 0)) {
             strncat(tsk_errstr2, " - hfs_load_attrs (non-file)",
-                    TSK_ERRSTR_L - strlen(tsk_errstr2));
+                TSK_ERRSTR_L - strlen(tsk_errstr2));
             tsk_fs_attr_free(fs_attr);
             tsk_fs_attr_run_free(attr_run);
             return 1;
@@ -2456,7 +2473,8 @@ hfs_block_is_alloc(HFS_INFO * hfs, TSK_DADDR_T a_addr)
                 tsk_errno = TSK_ERR_FS_READ;
             }
             snprintf(tsk_errstr2, TSK_ERRSTR_L,
-                     "hfs_block_is_alloc: Error reading block bitmap at offset %"PRIuOFF, b);            
+                "hfs_block_is_alloc: Error reading block bitmap at offset %"
+                PRIuOFF, b);
             return -1;
         }
         hfs->blockmap_cache_start = b;
@@ -2785,6 +2803,11 @@ hfs_fsstat(TSK_FS_INFO * fs, FILE * hFile)
         tsk_fprintf(hFile, " (unknown)\n");
         break;
     }
+    if (hfs->hfs_wrapper_offset > 0) {
+        tsk_fprintf(hFile,
+            "File system is embedded in an HFS wrapper at offset %" PRIuOFF
+            "\n", hfs->hfs_wrapper_offset);
+    }
 
     tsk_fprintf(hFile, "Last mounted version: %" PRIx32,
         tsk_getu32(fs->endian, sb->last_mnt_ver));
@@ -3139,15 +3162,13 @@ hfs_open(TSK_IMG_INFO * img_info, TSK_OFF_T offset,
         return NULL;
     }
 
-
     /*
      * Verify we are looking at an HFS+ image
      */
     if (tsk_fs_guessu16(fs, hfs->fs->signature, HFSPLUS_MAGIC) &&
-        tsk_fs_guessu16(fs, hfs->fs->signature, HFSX_MAGIC)) {
-        if (!tsk_fs_guessu16(fs, hfs->fs->signature, HFS_MAGIC)) {
-            tsk_fprintf(stderr, "HFS volumes not supported\n");
-        }
+        tsk_fs_guessu16(fs, hfs->fs->signature, HFSX_MAGIC) &&
+        tsk_fs_guessu16(fs, hfs->fs->signature, HFS_MAGIC)) {
+
         fs->tag = 0;
         free(hfs->fs);
         free(hfs);
@@ -3157,6 +3178,54 @@ hfs_open(TSK_IMG_INFO * img_info, TSK_OFF_T offset,
         return NULL;
     }
 
+    /*
+     * Handle an HFS-wrapped HFS+ image
+     */
+    if (tsk_getu16(fs->endian, hfs->fs->signature) == HFS_MAGIC) {
+
+        hfs_wrapper_sb *wrapper_sb = (hfs_wrapper_sb *) hfs->fs;
+
+        if ((tsk_getu16(fs->endian,
+                    wrapper_sb->drEmbedSigWord) == HFSPLUS_MAGIC)
+            || (tsk_getu16(fs->endian,
+                    wrapper_sb->drEmbedSigWord) == HFSX_MAGIC)) {
+
+            TSK_FS_INFO *fs_info2;
+            uint16_t drAlBlSt =
+                tsk_getu16(fs->endian, wrapper_sb->drAlBlSt);
+            uint32_t drAlBlkSiz =
+                tsk_getu32(fs->endian, wrapper_sb->drAlBlkSiz);
+            uint16_t startBlock =
+                tsk_getu16(fs->endian,
+                wrapper_sb->drEmbedExtent_startBlock);
+            TSK_OFF_T hfsplus_offset =
+                (drAlBlSt * (TSK_OFF_T) 512) +
+                (drAlBlkSiz * (TSK_OFF_T) startBlock);
+            if (tsk_verbose)
+                tsk_fprintf(stderr,
+                    "hfs_open: HFS+/HFSX within HFS wrapper at byte offset %"
+                    PRIuOFF "\n", hfsplus_offset);
+
+            fs->tag = 0;
+            free(hfs->fs);
+            free(hfs);
+
+            /* just re-open with the new offset, then record the offset */
+            fs_info2 =
+                hfs_open(img_info, offset + hfsplus_offset, ftype, test);
+            ((HFS_INFO *) fs_info2)->hfs_wrapper_offset = hfsplus_offset;
+            return fs_info2;
+        }
+
+        fs->tag = 0;
+        free(hfs->fs);
+        free(hfs);
+        tsk_errno = TSK_ERR_FS_MAGIC;
+        snprintf(tsk_errstr, TSK_ERRSTR_L,
+            "HFS file systems (other than wrappers HFS+/HFSX file systems) are not supported");
+        return NULL;
+    }
+
     fs->block_count = tsk_getu32(fs->endian, hfs->fs->blk_cnt);
     fs->first_block = 0;
     fs->last_block = fs->last_block_act = fs->block_count - 1;
@@ -3239,7 +3308,7 @@ hfs_open(TSK_IMG_INFO * img_info, TSK_OFF_T offset,
             tsk_errno = TSK_ERR_FS_READ;
         }
         snprintf(tsk_errstr2, TSK_ERRSTR_L,
-                 "hfs_open: Error reading catalog header");           
+            "hfs_open: Error reading catalog header");
         fs->tag = 0;
         free(hfs->fs);
         free(hfs);
@@ -3269,7 +3338,7 @@ hfs_open(TSK_IMG_INFO * img_info, TSK_OFF_T offset,
 
     // update the numbers.
     fs->last_inum = hfs_find_highest_inum(hfs);
-    fs->inum_count = fs->last_inum+1;
+    fs->inum_count = fs->last_inum + 1;
 
     snprintf((char *) fs->fs_id, 17, "%08" PRIx32 "%08" PRIx32,
         tsk_getu32(fs->endian, &(hfs->fs->finder_info[24])),
diff --git a/tsk3/fs/tsk_fs.h b/tsk3/fs/tsk_fs.h
index 36ba50a50c25aef096b70dc916c1a396a51c8fd1..bf6e9eff9ee5421168e2b901024c310627d1db4b 100644
--- a/tsk3/fs/tsk_fs.h
+++ b/tsk3/fs/tsk_fs.h
@@ -698,11 +698,11 @@ extern "C" {
         TSK_FS_TYPE_SWAP = 0x00000200,  ///< SWAP file system
         TSK_FS_TYPE_SWAP_DETECT = 0x00000200,   ///< SWAP auto detection
         TSK_FS_TYPE_RAW = 0x00000400,   ///< RAW file system
-        TSK_FS_TYPE_RAW_DETECT = 0x00000400,    ///< Raw auto detection
+        TSK_FS_TYPE_RAW_DETECT = 0x00000400,    ///< RAW auto detection
         TSK_FS_TYPE_ISO9660 = 0x00000800,       ///< ISO9660 file system
         TSK_FS_TYPE_ISO9660_DETECT = 0x00000800,        ///< ISO9660 auto detection
         TSK_FS_TYPE_HFS = 0x00001000,   ///< HFS file system
-        TSK_FS_TYPE_HFS_DETECT = 0x00001000,    ///< FAT auto detection
+        TSK_FS_TYPE_HFS_DETECT = 0x00001000,    ///< HFS auto detection
         TSK_FS_TYPE_UNSUPP = 0xffffffff,        ///< Unsupported file system
     };
     typedef enum TSK_FS_TYPE_ENUM TSK_FS_TYPE_ENUM;
diff --git a/tsk3/fs/tsk_hfs.h b/tsk3/fs/tsk_hfs.h
index 336760fff4071e6c88699edd3e370bae598a8937..5852b5475f0607d8974e2133407c125796368b8a 100644
--- a/tsk3/fs/tsk_hfs.h
+++ b/tsk3/fs/tsk_hfs.h
@@ -222,7 +222,7 @@ typedef struct {
 } hfs_fork;
 
 /*
-** Super Block
+** HFS+/HFSX Super Block
 */
 typedef struct {
     uint8_t signature[2];       /* "H+" for HFS+, "HX" for HFSX */
@@ -253,6 +253,42 @@ typedef struct {
     hfs_fork start_file;        /* location and size of startup file */
 } hfs_sb;
 
+/*
+** HFS Super Block for wrapped HFS+/HFSX file systems
+*/
+typedef struct {
+    uint8_t drSigWord[2];       /* "BD" for HFS (same location as hfs_sb.signature) */
+    uint8_t drCrDate[4];        /* volume creation date */
+    uint8_t drLsMod[4];         /* volume last modified date */
+    uint8_t drAtrb[2];          /* volume attributes */
+    uint8_t drNmFls[2];         /* number of files on volume */
+    uint8_t drVBMSt[2];         /* starting block for volume bitmap */
+    uint8_t drAllocPtr[2];      /* start of next allocation search */
+    uint8_t drNmAlBlks[2];      /* number of blocks on disk */
+    uint8_t drAlBlkSiz[4];      /* size in bytes of each allocation block */
+    uint8_t drClpSiz[4];        /* default clump size for volume */
+    uint8_t drAlBlSt[2];        /* first allocation block, in 512-byte sectors */
+    uint8_t drNxtCNID[4];       /* next unused catalog node ID */
+    uint8_t drFreeBlks[2];      /* number of unused allocation blocks */
+    uint8_t drVN[28];           /* volume name, where first byte is length */
+    uint8_t drVolBkUp[4];       /* volume last backup date */
+    uint8_t drVSeqNum[2];       /* volume sequence number */
+    uint8_t drWrCnt[4];         /* write count */
+    uint8_t drXTClpSiz[4];      /* clump size for extents overflow file */
+    uint8_t drCTClpSiz[4];      /* clump size for catalog file */
+    uint8_t drNmRtDirs[2];      /* number of folders in root directory */
+    uint8_t drFilCnt[4];        /* number of files on volume */
+    uint8_t drDirCnt[4];        /* number of directories on volume */
+    uint8_t drFndrInfo[32];     /* Finder info */
+    uint8_t drEmbedSigWord[2];  /* signature of the embedded HFS+ volume (eg, "H+") */
+    uint8_t drEmbedExtent_startBlock[2];        /* extent descriptor for start of embedded volume */
+    uint8_t drEmbedExtent_blockCount[2];        /* extent descriptor for start of embedded volume */
+    uint8_t drXTFlSize[4];      /* size of the extents overflow file */
+    uint8_t drXTExtRec[12];     /* extent record with size and location of extents overflow file */
+    uint8_t drCTFlSize[4];      /* size of the catalog file */
+    uint8_t drCTExtRec[12];     /* extent record with size and location of catalog file */
+} hfs_wrapper_sb;
+
 typedef struct {
     uint8_t key_len[2];
     uint8_t parent_cnid[4];
@@ -398,6 +434,7 @@ typedef struct {
     const TSK_FS_ATTR *extents_attr;
     hfs_btree_header_record extents_header;
 
+    TSK_OFF_T hfs_wrapper_offset;       /* byte offset of this FS within an HFS wrapper */
 } HFS_INFO;
 
 typedef struct {