/[pearpc]/src/io/prom/fs/hfs.cc
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /src/io/prom/fs/hfs.cc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (show annotations)
Wed Sep 5 17:11:21 2007 UTC (16 years, 7 months ago) by dpavlin
File size: 12807 byte(s)
import upstream CVS
1 /*
2 * PearPC
3 * hfs.cc
4 *
5 * Copyright (C) 2004 Stefan Weyergraf
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program 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
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include <string.h>
22
23 #include "debug/tracers.h"
24 #include "hfs.h"
25 #include "hfsstruct.h"
26 #include "hfsplus.h"
27 #include "tools/debug.h"
28 #include "tools/endianess.h"
29 #include "tools/except.h"
30 #include "tools/snprintf.h"
31
32 extern "C" {
33 #include "hfs/libhfs.h"
34 #include "hfs/volume.h"
35 }
36
37 byte HFSNodeDescriptor_struct[] = {
38 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
39 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
40 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
41 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
42 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
43 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
44 0
45 };
46
47 byte HFSBTHdrRec_struct[] = {
48 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
49 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
50 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
51 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
52 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
53 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
54 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
55 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
56 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
57 0
58 };
59
60 byte HFSCatKeyRec_struct[] = {
61 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
62 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
63 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
64 // 31 bytes
65 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
66 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
67 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
68 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
69 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
70 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
71 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
72 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
73
74 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
75 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
76 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
77 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
78 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
79 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
80 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
81 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
82
83 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
84 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
85 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
86 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
87 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
88 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
89 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
90 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
91
92 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
93 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
94 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
95 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
96 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
97 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
98 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
99
100 0
101 };
102
103 byte HFSCatFileRec_struct[] = {
104 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
105 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
106 // FInfo
107 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
108 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
109 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
110 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
111 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
112 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
113 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
114 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
115 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
116 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
117 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
118 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
119 //
120 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
121 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
122 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
123 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
124 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
125 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
126 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
127 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
128 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
129 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
130 // FXInfo
131 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
132 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
133 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
134 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
135 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
136 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
137 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
138 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
139 //
140 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
141 // data fork extent record
142 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
143 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
144 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
145 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
146 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
147 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
148 // res fork extent record
149 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
150 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
151 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
152 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
153 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
154 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
155 //
156 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
157 0
158 };
159
160 byte HFSMDB_struct[] = {
161 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
162 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
163 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
164 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
165 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
166 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
167 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
168 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
169 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
170 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
171 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
172 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
173 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
174 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
175 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
176 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
177 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
178 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
179 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
180 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
181 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
182 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
183 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
184 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
185 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
186 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
187 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
188 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
189 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
190 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
191 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
192 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
193 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
194 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
195 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
196 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
197 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
198 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
199 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
200 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
201 STRUCT_ENDIAN_8 | STRUCT_ENDIAN_HOST,
202 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
203 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
204 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
205 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
206 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
207 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
208 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
209 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
210 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
211 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
212 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
213 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
214 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
215 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
216 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
217 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
218 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
219 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
220 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
221 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
222 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
223 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
224 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
225 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
226 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
227 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
228 STRUCT_ENDIAN_32 | STRUCT_ENDIAN_HOST,
229 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
230 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
231 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
232 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
233 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
234 STRUCT_ENDIAN_16 | STRUCT_ENDIAN_HOST,
235 0
236 };
237
238 /*
239 *
240 */
241 static bool doTryBootHFS(const HFSMDB &mdb, File *aDevice, uint aDeviceBlocksize, FileOfs start, PartitionEntry *partEnt);
242
243 bool tryBootHFS(File *aDevice, uint aDeviceBlocksize, FileOfs start, PartitionEntry *partEnt)
244 {
245 HFSMDB mdb;
246 aDevice->seek(start+0x400);
247 if (aDevice->read((byte*)&mdb, sizeof mdb) == sizeof mdb) {
248 createHostStructx(&mdb, sizeof mdb, HFSMDB_struct, big_endian);
249 if (mdb.drSigWord == HFSSigWord) {
250 if (mdb.drEmbedSigWord == HFSPlusSigWord) {
251 // HFS+ (embedded in HFS)
252 IO_PROM_FS_TRACE("contains HFS volume, embedding a HFS+ volume\n");
253 IO_PROM_FS_TRACE("embed.start=%08x, embed.count=%08x, hfsblksz=%08x\n",
254 mdb.drEmbedExtent.startBlock,
255 mdb.drEmbedExtent.blockCount,
256 mdb.drAlblkSz);
257 return tryBootHFSPlus(aDevice, aDeviceBlocksize, start+mdb.drEmbedExtent.startBlock*mdb.drAlblkSz, partEnt);
258 } else {
259 IO_PROM_FS_TRACE("contains HFS volume\n");
260 return doTryBootHFS(mdb, aDevice, aDeviceBlocksize, start, partEnt);
261 }
262 }
263 }
264 return false;
265 }
266
267 struct HFSInstantiateBootFilePrivData {
268 int mPartNum;
269 };
270
271 static File *HFSInstantiateBootFile(File *aDevice, void *priv)
272 {
273 HFSInstantiateBootFilePrivData *p = (HFSInstantiateBootFilePrivData*)priv;
274 HFSFileSystem *fs = new HFSFileSystem(aDevice, p->mPartNum);
275 File *f = fs->openBootFile();
276 if (!f) delete fs;
277 return f;
278 }
279
280 static FileSystem *HFSInstantiateFileSystem(File *aDevice, int partnum)
281 {
282 return new HFSFileSystem(aDevice, partnum);
283 }
284
285 static bool doTryBootHFS(const HFSMDB &mdb, File *aDevice, uint aDeviceBlocksize, FileOfs start, PartitionEntry *partEnt)
286 {
287 if (partEnt->mPartNum <= 0) return false;
288 hfs_devicehandle_s dh;
289 dh.mDevice = aDevice;
290 dh.mStart = 0;
291 hfsvol *vol = hfs_mount(&dh, partEnt->mPartNum-1, HFS_MODE_RDONLY);
292 if (vol) {
293 hfs_umount(vol);
294 HFSInstantiateBootFilePrivData *priv = (HFSInstantiateBootFilePrivData*)
295 malloc(sizeof (HFSInstantiateBootFilePrivData));
296 priv->mPartNum = partEnt->mPartNum;
297 partEnt->mInstantiateBootFilePrivData = priv;
298 partEnt->mInstantiateBootFile = HFSInstantiateBootFile;
299 partEnt->mInstantiateFileSystem = HFSInstantiateFileSystem;
300 partEnt->mBootMethod = BM_chrp;
301 return true;
302 } else IO_PROM_FS_TRACE("couldn't mount HFS partition.\n");
303 return false;
304 }
305
306 /***/
307 class HFSFile: public File {
308 protected:
309 hfsfile * mFile;
310 FileOfs mCurOfs;
311 FileSystem * mFS;
312 bool mOwnFS;
313 public:
314
315 HFSFile(hfsfile *file, FileSystem *fs, bool own_fs)
316 {
317 mFile = file;
318 mCurOfs = 0;
319 mFS = fs;
320 mOwnFS = own_fs;
321 }
322
323 virtual ~HFSFile()
324 {
325 hfs_close(mFile);
326 if (mOwnFS) delete mFS;
327 }
328
329 virtual FileOfs getSize() const
330 {
331 return mFile->cat.u.fil.filLgLen;
332 }
333
334 virtual uint read(void *buf, uint size)
335 {
336 uint r = hfs_read(mFile, buf, size);
337 mCurOfs += r;
338 return r;
339 }
340
341 virtual void seek(FileOfs offset)
342 {
343 hfs_seek(mFile, offset, HFS_SEEK_SET);
344 mCurOfs = offset;
345 }
346
347 virtual FileOfs tell() const
348 {
349 return mCurOfs;
350 }
351
352 };
353
354 /***/
355 HFSFileSystem::HFSFileSystem(File *device, int partnum)
356 : FileSystem(device)
357 {
358 dh.mDevice = mDevice;
359 dh.mStart = 0;
360 hfshandle = hfs_mount(&dh, partnum-1, HFS_MODE_RDONLY);
361 if (!hfshandle) throw MsgException("couldn't mount HFS file system");
362 }
363
364 HFSFileSystem::~HFSFileSystem()
365 {
366 hfs_umount((hfsvol*)hfshandle);
367 }
368
369 File *HFSFileSystem::open(const String &filename)
370 {
371 hfsfile *f = hfs_open((hfsvol*)hfshandle, filename.contentChar());
372 if (!f) return NULL;
373 return new HFSFile(f, this, false);
374 }
375
376 // WARNING: on success this will bind this filesystem to the file (mOwnFS)
377 File *HFSFileSystem::openBootFile()
378 {
379 hfsvol *vol = (hfsvol*)hfshandle;
380 uint startupFolderID = vol->mdb.drFndrInfo[0];
381 hfsdir *dir = hfs_opendir_by_id(vol, startupFolderID);
382 if (!dir) {
383 IO_PROM_FS_TRACE("couldn't get Startup Folder of HFS partition.\n");
384 return NULL;
385 }
386 hfsdirent dirent;
387 while (hfs_readdir(dir, &dirent) == 0) {
388 // IO_PROM_FS_TRACE("%-4s %08x %s\n", dirent.u.file.type, dirent.cnid, dirent.name);
389 if (strcmp(dirent.u.file.type, "tbxi") == 0) {
390 hfsfile *file = hfs_open_by_dirent(vol, &dirent);
391 if (file) {
392 /* IO_PROM_FS_TRACE("got Startup FILE!\n");
393 char buf[32];
394 hfs_read(file, buf, 32);
395 buf[31] = 0;
396 IO_PROM_FS_TRACE("%s\n", buf);*/
397 return new HFSFile(file, this, true);
398 }
399 }
400 }
401 IO_PROM_FS_TRACE("couldn't find a Startup File in the Startup Folder of the HFS partition.\n");
402 return NULL;
403 }
404
405 bool HFSFileSystem::getBlessedPath(String &blessed)
406 {
407 hfsvol *vol = (hfsvol*)hfshandle;
408 uint startupFolderID = vol->mdb.drFndrInfo[0];
409 uint id = startupFolderID;
410 uint maxit = 200;
411 blessed.assign("/");
412 while ((id != HFS_CNID_ROOTDIR) && maxit--) {
413 CatDataRec dthd;
414 if (v_getdthread(vol, id, &dthd, NULL) <= 0) return false;
415 String p(dthd.u.dthd.thdCName);
416 blessed.prepend(p);
417 blessed.prepend("/");
418 id = dthd.u.dthd.thdParID;
419 }
420 return (id == HFS_CNID_ROOTDIR);
421 }

  ViewVC Help
Powered by ViewVC 1.1.26