Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/util-linux/volume_id/hfs.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 984 - (hide annotations) (download)
Sun May 30 11:32:42 2010 UTC (14 years ago) by niro
File MIME type: text/plain
File size: 7756 byte(s)
-updated to busybox-1.16.1 and enabled blkid/uuid support in default config
1 niro 816 /*
2     * volume_id - reads filesystem label and uuid
3     *
4     * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5     *
6     * This library is free software; you can redistribute it and/or
7     * modify it under the terms of the GNU Lesser General Public
8     * License as published by the Free Software Foundation; either
9     * version 2.1 of the License, or (at your option) any later version.
10     *
11     * This library is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14     * Lesser General Public License for more details.
15     *
16     * You should have received a copy of the GNU Lesser General Public
17     * License along with this library; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19     */
20    
21     #include "volume_id_internal.h"
22    
23     struct hfs_finder_info{
24     uint32_t boot_folder;
25     uint32_t start_app;
26     uint32_t open_folder;
27     uint32_t os9_folder;
28     uint32_t reserved;
29     uint32_t osx_folder;
30     uint8_t id[8];
31 niro 984 } PACKED;
32 niro 816
33     struct hfs_mdb {
34     uint8_t signature[2];
35     uint32_t cr_date;
36     uint32_t ls_Mod;
37     uint16_t atrb;
38     uint16_t nm_fls;
39     uint16_t vbm_st;
40     uint16_t alloc_ptr;
41     uint16_t nm_al_blks;
42     uint32_t al_blk_size;
43     uint32_t clp_size;
44     uint16_t al_bl_st;
45     uint32_t nxt_cnid;
46     uint16_t free_bks;
47     uint8_t label_len;
48     uint8_t label[27];
49     uint32_t vol_bkup;
50     uint16_t vol_seq_num;
51     uint32_t wr_cnt;
52     uint32_t xt_clump_size;
53     uint32_t ct_clump_size;
54     uint16_t num_root_dirs;
55     uint32_t file_count;
56     uint32_t dir_count;
57     struct hfs_finder_info finder_info;
58     uint8_t embed_sig[2];
59     uint16_t embed_startblock;
60     uint16_t embed_blockcount;
61 niro 984 } PACKED;
62 niro 816
63     struct hfsplus_bnode_descriptor {
64     uint32_t next;
65     uint32_t prev;
66     uint8_t type;
67     uint8_t height;
68     uint16_t num_recs;
69     uint16_t reserved;
70 niro 984 } PACKED;
71 niro 816
72     struct hfsplus_bheader_record {
73     uint16_t depth;
74     uint32_t root;
75     uint32_t leaf_count;
76     uint32_t leaf_head;
77     uint32_t leaf_tail;
78     uint16_t node_size;
79 niro 984 } PACKED;
80 niro 816
81     struct hfsplus_catalog_key {
82     uint16_t key_len;
83     uint32_t parent_id;
84     uint16_t unicode_len;
85     uint8_t unicode[255 * 2];
86 niro 984 } PACKED;
87 niro 816
88     struct hfsplus_extent {
89     uint32_t start_block;
90     uint32_t block_count;
91 niro 984 } PACKED;
92 niro 816
93     #define HFSPLUS_EXTENT_COUNT 8
94     struct hfsplus_fork {
95     uint64_t total_size;
96     uint32_t clump_size;
97     uint32_t total_blocks;
98     struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
99 niro 984 } PACKED;
100 niro 816
101     struct hfsplus_vol_header {
102     uint8_t signature[2];
103     uint16_t version;
104     uint32_t attributes;
105     uint32_t last_mount_vers;
106     uint32_t reserved;
107     uint32_t create_date;
108     uint32_t modify_date;
109     uint32_t backup_date;
110     uint32_t checked_date;
111     uint32_t file_count;
112     uint32_t folder_count;
113     uint32_t blocksize;
114     uint32_t total_blocks;
115     uint32_t free_blocks;
116     uint32_t next_alloc;
117     uint32_t rsrc_clump_sz;
118     uint32_t data_clump_sz;
119     uint32_t next_cnid;
120     uint32_t write_count;
121     uint64_t encodings_bmp;
122     struct hfs_finder_info finder_info;
123     struct hfsplus_fork alloc_file;
124     struct hfsplus_fork ext_file;
125     struct hfsplus_fork cat_file;
126     struct hfsplus_fork attr_file;
127     struct hfsplus_fork start_file;
128 niro 984 } PACKED;
129 niro 816
130     #define HFS_SUPERBLOCK_OFFSET 0x400
131     #define HFS_NODE_LEAF 0xff
132     #define HFSPLUS_POR_CNID 1
133    
134 niro 984 int FAST_FUNC volume_id_probe_hfs_hfsplus(struct volume_id *id /*,uint64_t off*/)
135 niro 816 {
136 niro 984 uint64_t off = 0;
137 niro 816 unsigned blocksize;
138     unsigned cat_block;
139     unsigned ext_block_start;
140     unsigned ext_block_count;
141     int ext;
142     unsigned leaf_node_head;
143     unsigned leaf_node_count;
144     unsigned leaf_node_size;
145     unsigned leaf_block;
146     uint64_t leaf_off;
147     unsigned alloc_block_size;
148     unsigned alloc_first_block;
149     unsigned embed_first_block;
150     unsigned record_count;
151     struct hfsplus_vol_header *hfsplus;
152     struct hfsplus_bnode_descriptor *descr;
153     struct hfsplus_bheader_record *bnode;
154     struct hfsplus_catalog_key *key;
155     unsigned label_len;
156     struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
157     struct hfs_mdb *hfs;
158     const uint8_t *buf;
159    
160     dbg("probing at offset 0x%llx", (unsigned long long) off);
161    
162     buf = volume_id_get_buffer(id, off + HFS_SUPERBLOCK_OFFSET, 0x200);
163     if (buf == NULL)
164     return -1;
165    
166     hfs = (struct hfs_mdb *) buf;
167     if (hfs->signature[0] != 'B' || hfs->signature[1] != 'D')
168     goto checkplus;
169    
170     /* it may be just a hfs wrapper for hfs+ */
171     if (hfs->embed_sig[0] == 'H' && hfs->embed_sig[1] == '+') {
172     alloc_block_size = be32_to_cpu(hfs->al_blk_size);
173     dbg("alloc_block_size 0x%x", alloc_block_size);
174    
175     alloc_first_block = be16_to_cpu(hfs->al_bl_st);
176     dbg("alloc_first_block 0x%x", alloc_first_block);
177    
178     embed_first_block = be16_to_cpu(hfs->embed_startblock);
179     dbg("embed_first_block 0x%x", embed_first_block);
180    
181     off += (alloc_first_block * 512) +
182     (embed_first_block * alloc_block_size);
183     dbg("hfs wrapped hfs+ found at offset 0x%llx", (unsigned long long) off);
184    
185     buf = volume_id_get_buffer(id, off + HFS_SUPERBLOCK_OFFSET, 0x200);
186     if (buf == NULL)
187     return -1;
188     goto checkplus;
189     }
190    
191     if (hfs->label_len > 0 && hfs->label_len < 28) {
192     // volume_id_set_label_raw(id, hfs->label, hfs->label_len);
193     volume_id_set_label_string(id, hfs->label, hfs->label_len) ;
194     }
195    
196     volume_id_set_uuid(id, hfs->finder_info.id, UUID_HFS);
197     // volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
198     // id->type = "hfs";
199    
200     return 0;
201    
202     checkplus:
203     hfsplus = (struct hfsplus_vol_header *) buf;
204     if (hfs->signature[0] == 'H')
205     if (hfs->signature[1] == '+' || hfs->signature[1] == 'X')
206     goto hfsplus;
207     return -1;
208    
209     hfsplus:
210     volume_id_set_uuid(id, hfsplus->finder_info.id, UUID_HFS);
211    
212     blocksize = be32_to_cpu(hfsplus->blocksize);
213     dbg("blocksize %u", blocksize);
214    
215     memcpy(extents, hfsplus->cat_file.extents, sizeof(extents));
216     cat_block = be32_to_cpu(extents[0].start_block);
217     dbg("catalog start block 0x%x", cat_block);
218    
219     buf = volume_id_get_buffer(id, off + (cat_block * blocksize), 0x2000);
220     if (buf == NULL)
221     goto found;
222    
223     bnode = (struct hfsplus_bheader_record *)
224     &buf[sizeof(struct hfsplus_bnode_descriptor)];
225    
226     leaf_node_head = be32_to_cpu(bnode->leaf_head);
227     dbg("catalog leaf node 0x%x", leaf_node_head);
228    
229     leaf_node_size = be16_to_cpu(bnode->node_size);
230     dbg("leaf node size 0x%x", leaf_node_size);
231    
232     leaf_node_count = be32_to_cpu(bnode->leaf_count);
233     dbg("leaf node count 0x%x", leaf_node_count);
234     if (leaf_node_count == 0)
235     goto found;
236    
237     leaf_block = (leaf_node_head * leaf_node_size) / blocksize;
238    
239     /* get physical location */
240     for (ext = 0; ext < HFSPLUS_EXTENT_COUNT; ext++) {
241     ext_block_start = be32_to_cpu(extents[ext].start_block);
242     ext_block_count = be32_to_cpu(extents[ext].block_count);
243     dbg("extent start block 0x%x, count 0x%x", ext_block_start, ext_block_count);
244    
245     if (ext_block_count == 0)
246     goto found;
247    
248     /* this is our extent */
249     if (leaf_block < ext_block_count)
250     break;
251    
252     leaf_block -= ext_block_count;
253     }
254     if (ext == HFSPLUS_EXTENT_COUNT)
255     goto found;
256     dbg("found block in extent %i", ext);
257    
258     leaf_off = (ext_block_start + leaf_block) * blocksize;
259    
260     buf = volume_id_get_buffer(id, off + leaf_off, leaf_node_size);
261     if (buf == NULL)
262     goto found;
263    
264     descr = (struct hfsplus_bnode_descriptor *) buf;
265     dbg("descriptor type 0x%x", descr->type);
266    
267     record_count = be16_to_cpu(descr->num_recs);
268     dbg("number of records %u", record_count);
269     if (record_count == 0)
270     goto found;
271    
272     if (descr->type != HFS_NODE_LEAF)
273     goto found;
274    
275     key = (struct hfsplus_catalog_key *)
276     &buf[sizeof(struct hfsplus_bnode_descriptor)];
277    
278     dbg("parent id 0x%x", be32_to_cpu(key->parent_id));
279     if (key->parent_id != cpu_to_be32(HFSPLUS_POR_CNID))
280     goto found;
281    
282     label_len = be16_to_cpu(key->unicode_len) * 2;
283     dbg("label unicode16 len %i", label_len);
284     // volume_id_set_label_raw(id, key->unicode, label_len);
285     volume_id_set_label_unicode16(id, key->unicode, BE, label_len);
286    
287     found:
288     // volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
289     // id->type = "hfsplus";
290    
291     return 0;
292     }