• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/fstools/libblkid-tiny/hfs.c

  1 /*
  2  * Copyright (C) 2004-2008 Kay Sievers <kay.sievers@vrfy.org>
  3  * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
  4  *
  5  * This file may be redistributed under the terms of the
  6  * GNU Lesser General Public License.
  7  */
  8 #include <stdio.h>
  9 #include <stdlib.h>
 10 #include <unistd.h>
 11 #include <string.h>
 12 #include <inttypes.h>
 13 
 14 #include "superblocks.h"
 15 
 16 #if 0
 17 #include "md5.h"
 18 #endif
 19 
 20 /* HFS / HFS+ */
 21 struct hfs_finder_info {
 22         uint32_t        boot_folder;
 23         uint32_t        start_app;
 24         uint32_t        open_folder;
 25         uint32_t        os9_folder;
 26         uint32_t        reserved;
 27         uint32_t        osx_folder;
 28         uint8_t         id[8];
 29 } __attribute__((packed));
 30 
 31 struct hfs_mdb {
 32         uint8_t         signature[2];
 33         uint32_t        cr_date;
 34         uint32_t        ls_Mod;
 35         uint16_t        atrb;
 36         uint16_t        nm_fls;
 37         uint16_t        vbm_st;
 38         uint16_t        alloc_ptr;
 39         uint16_t        nm_al_blks;
 40         uint32_t        al_blk_size;
 41         uint32_t        clp_size;
 42         uint16_t        al_bl_st;
 43         uint32_t        nxt_cnid;
 44         uint16_t        free_bks;
 45         uint8_t         label_len;
 46         uint8_t         label[27];
 47         uint32_t        vol_bkup;
 48         uint16_t        vol_seq_num;
 49         uint32_t        wr_cnt;
 50         uint32_t        xt_clump_size;
 51         uint32_t        ct_clump_size;
 52         uint16_t        num_root_dirs;
 53         uint32_t        file_count;
 54         uint32_t        dir_count;
 55         struct hfs_finder_info finder_info;
 56         uint8_t         embed_sig[2];
 57         uint16_t        embed_startblock;
 58         uint16_t        embed_blockcount;
 59 } __attribute__((packed));
 60 
 61 
 62 #define HFS_NODE_LEAF                   0xff
 63 #define HFSPLUS_POR_CNID                1
 64 
 65 struct hfsplus_bnode_descriptor {
 66         uint32_t                next;
 67         uint32_t                prev;
 68         uint8_t         type;
 69         uint8_t         height;
 70         uint16_t                num_recs;
 71         uint16_t                reserved;
 72 } __attribute__((packed));
 73 
 74 struct hfsplus_bheader_record {
 75         uint16_t                depth;
 76         uint32_t                root;
 77         uint32_t                leaf_count;
 78         uint32_t                leaf_head;
 79         uint32_t                leaf_tail;
 80         uint16_t                node_size;
 81 } __attribute__((packed));
 82 
 83 struct hfsplus_catalog_key {
 84         uint16_t        key_len;
 85         uint32_t        parent_id;
 86         uint16_t        unicode_len;
 87         uint8_t         unicode[255 * 2];
 88 } __attribute__((packed));
 89 
 90 struct hfsplus_extent {
 91         uint32_t                start_block;
 92         uint32_t                block_count;
 93 } __attribute__((packed));
 94 
 95 #define HFSPLUS_EXTENT_COUNT            8
 96 struct hfsplus_fork {
 97         uint64_t                total_size;
 98         uint32_t                clump_size;
 99         uint32_t                total_blocks;
100         struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
101 } __attribute__((packed));
102 
103 struct hfsplus_vol_header {
104         uint8_t         signature[2];
105         uint16_t                version;
106         uint32_t                attributes;
107         uint32_t                last_mount_vers;
108         uint32_t                reserved;
109         uint32_t                create_date;
110         uint32_t                modify_date;
111         uint32_t                backup_date;
112         uint32_t                checked_date;
113         uint32_t                file_count;
114         uint32_t                folder_count;
115         uint32_t                blocksize;
116         uint32_t                total_blocks;
117         uint32_t                free_blocks;
118         uint32_t                next_alloc;
119         uint32_t                rsrc_clump_sz;
120         uint32_t                data_clump_sz;
121         uint32_t                next_cnid;
122         uint32_t                write_count;
123         uint64_t                encodings_bmp;
124         struct hfs_finder_info finder_info;
125         struct hfsplus_fork alloc_file;
126         struct hfsplus_fork ext_file;
127         struct hfsplus_fork cat_file;
128         struct hfsplus_fork attr_file;
129         struct hfsplus_fork start_file;
130 }  __attribute__((packed));
131 
132 #define HFSPLUS_SECTOR_SIZE        512
133 
134 static int hfs_set_uuid(blkid_probe pr, unsigned char const *hfs_info, size_t len)
135 {
136 #if 0
137         static unsigned char const hash_init[MD5LENGTH] = {
138                 0xb3, 0xe2, 0x0f, 0x39, 0xf2, 0x92, 0x11, 0xd6,
139                 0x97, 0xa4, 0x00, 0x30, 0x65, 0x43, 0xec, 0xac
140         };
141         unsigned char uuid[MD5LENGTH];
142         struct MD5Context md5c;
143 
144         if (memcmp(hfs_info, "\0\0\0\0\0\0\0\0", len) == 0)
145                 return -1;
146         MD5Init(&md5c);
147         MD5Update(&md5c, hash_init, MD5LENGTH);
148         MD5Update(&md5c, hfs_info, len);
149         MD5Final(uuid, &md5c);
150         uuid[6] = 0x30 | (uuid[6] & 0x0f);
151         uuid[8] = 0x80 | (uuid[8] & 0x3f);
152         return blkid_probe_set_uuid(pr, uuid);
153 #else
154         return -ENOSYS;
155 #endif
156 }
157 
158 static int probe_hfs(blkid_probe pr, const struct blkid_idmag *mag)
159 {
160         struct hfs_mdb  *hfs;
161 
162         hfs = blkid_probe_get_sb(pr, mag, struct hfs_mdb);
163         if (!hfs)
164                 return errno ? -errno : 1;
165 
166         if ((memcmp(hfs->embed_sig, "H+", 2) == 0) ||
167             (memcmp(hfs->embed_sig, "HX", 2) == 0))
168                 return 1;       /* Not hfs, but an embedded HFS+ */
169 
170         hfs_set_uuid(pr, hfs->finder_info.id, sizeof(hfs->finder_info.id));
171 
172         blkid_probe_set_label(pr, hfs->label, hfs->label_len);
173         return 0;
174 }
175 
176 static int probe_hfsplus(blkid_probe pr, const struct blkid_idmag *mag)
177 {
178         struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
179         struct hfsplus_bnode_descriptor *descr;
180         struct hfsplus_bheader_record *bnode;
181         struct hfsplus_catalog_key *key;
182         struct hfsplus_vol_header *hfsplus;
183         struct hfs_mdb *sbd;
184         unsigned int alloc_block_size;
185         unsigned int alloc_first_block;
186         unsigned int embed_first_block;
187         unsigned int off = 0;
188         unsigned int blocksize;
189         unsigned int cat_block;
190         unsigned int ext_block_start;
191         unsigned int ext_block_count;
192         unsigned int record_count;
193         unsigned int leaf_node_head;
194         unsigned int leaf_node_count;
195         unsigned int leaf_node_size;
196         unsigned int leaf_block;
197         int ext;
198         uint64_t leaf_off;
199         unsigned char *buf;
200 
201         sbd = blkid_probe_get_sb(pr, mag, struct hfs_mdb);
202         if (!sbd)
203                 return errno ? -errno : 1;
204 
205         /* Check for a HFS+ volume embedded in a HFS volume */
206         if (memcmp(sbd->signature, "BD", 2) == 0) {
207                 if ((memcmp(sbd->embed_sig, "H+", 2) != 0) &&
208                     (memcmp(sbd->embed_sig, "HX", 2) != 0))
209                         /* This must be an HFS volume, so fail */
210                         return 1;
211 
212                 alloc_block_size = be32_to_cpu(sbd->al_blk_size);
213                 alloc_first_block = be16_to_cpu(sbd->al_bl_st);
214                 embed_first_block = be16_to_cpu(sbd->embed_startblock);
215                 off = (alloc_first_block * 512) +
216                         (embed_first_block * alloc_block_size);
217 
218                 buf = blkid_probe_get_buffer(pr,
219                                 off + (mag->kboff * 1024),
220                                 sizeof(struct hfsplus_vol_header));
221                 hfsplus = (struct hfsplus_vol_header *) buf;
222 
223         } else
224                 hfsplus = blkid_probe_get_sb(pr, mag,
225                                 struct hfsplus_vol_header);
226 
227         if (!hfsplus)
228                 return errno ? -errno : 1;
229 
230         if ((memcmp(hfsplus->signature, "H+", 2) != 0) &&
231             (memcmp(hfsplus->signature, "HX", 2) != 0))
232                 return 1;
233 
234         hfs_set_uuid(pr, hfsplus->finder_info.id, sizeof(hfsplus->finder_info.id));
235 
236         blocksize = be32_to_cpu(hfsplus->blocksize);
237         if (blocksize < HFSPLUS_SECTOR_SIZE)
238                 return 1;
239 
240         memcpy(extents, hfsplus->cat_file.extents, sizeof(extents));
241         cat_block = be32_to_cpu(extents[0].start_block);
242 
243         buf = blkid_probe_get_buffer(pr,
244                         off + ((blkid_loff_t) cat_block * blocksize), 0x2000);
245         if (!buf)
246                 return errno ? -errno : 0;
247 
248         bnode = (struct hfsplus_bheader_record *)
249                 &buf[sizeof(struct hfsplus_bnode_descriptor)];
250 
251         leaf_node_head = be32_to_cpu(bnode->leaf_head);
252         leaf_node_size = be16_to_cpu(bnode->node_size);
253         leaf_node_count = be32_to_cpu(bnode->leaf_count);
254         if (leaf_node_count == 0)
255                 return 0;
256 
257         leaf_block = (leaf_node_head * leaf_node_size) / blocksize;
258 
259         /* get physical location */
260         for (ext = 0; ext < HFSPLUS_EXTENT_COUNT; ext++) {
261                 ext_block_start = be32_to_cpu(extents[ext].start_block);
262                 ext_block_count = be32_to_cpu(extents[ext].block_count);
263                 if (ext_block_count == 0)
264                         return 0;
265 
266                 /* this is our extent */
267                 if (leaf_block < ext_block_count)
268                         break;
269 
270                 leaf_block -= ext_block_count;
271         }
272         if (ext == HFSPLUS_EXTENT_COUNT)
273                 return 0;
274 
275         leaf_off = ((uint64_t) ext_block_start + leaf_block) * blocksize;
276 
277         buf = blkid_probe_get_buffer(pr,
278                                 (blkid_loff_t) off + leaf_off,
279                                 leaf_node_size);
280         if (!buf)
281                 return errno ? -errno : 0;
282 
283         descr = (struct hfsplus_bnode_descriptor *) buf;
284         record_count = be16_to_cpu(descr->num_recs);
285         if (record_count == 0)
286                 return 0;
287 
288         if (descr->type != HFS_NODE_LEAF)
289                 return 0;
290 
291         key = (struct hfsplus_catalog_key *)
292                 &buf[sizeof(struct hfsplus_bnode_descriptor)];
293 
294         if (be32_to_cpu(key->parent_id) != HFSPLUS_POR_CNID)
295                 return 0;
296 
297         blkid_probe_set_utf8label(pr, key->unicode,
298                         be16_to_cpu(key->unicode_len) * 2,
299                         BLKID_ENC_UTF16BE);
300 
301         return 0;
302 }
303 
304 const struct blkid_idinfo hfs_idinfo =
305 {
306         .name           = "hfs",
307         .usage          = BLKID_USAGE_FILESYSTEM,
308         .probefunc      = probe_hfs,
309         .flags          = BLKID_IDINFO_TOLERANT,
310         .magics         =
311         {
312                 { .magic = "BD", .len = 2, .kboff = 1 },
313                 { NULL }
314         }
315 };
316 
317 const struct blkid_idinfo hfsplus_idinfo =
318 {
319         .name           = "hfsplus",
320         .usage          = BLKID_USAGE_FILESYSTEM,
321         .probefunc      = probe_hfsplus,
322         .magics         =
323         {
324                 { .magic = "BD", .len = 2, .kboff = 1 },
325                 { .magic = "H+", .len = 2, .kboff = 1 },
326                 { .magic = "HX", .len = 2, .kboff = 1 },
327                 { NULL }
328         }
329 };
330 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt