/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (hide 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 dpavlin 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