diff options
Diffstat (limited to 'qemu/roms/openbios/fs/hfs/volume.c')
-rw-r--r-- | qemu/roms/openbios/fs/hfs/volume.c | 612 |
1 files changed, 0 insertions, 612 deletions
diff --git a/qemu/roms/openbios/fs/hfs/volume.c b/qemu/roms/openbios/fs/hfs/volume.c deleted file mode 100644 index 4faf7e6c2..000000000 --- a/qemu/roms/openbios/fs/hfs/volume.c +++ /dev/null @@ -1,612 +0,0 @@ -/* - * libhfs - library for reading and writing Macintosh HFS volumes - * Copyright (C) 1996-1998 Robert Leslie - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, - * MA 02110-1301, USA. - * - * $Id: volume.c,v 1.12 1998/11/02 22:09:10 rob Exp $ - */ - -#include "config.h" -#include "libhfs.h" -#include "volume.h" -#include "data.h" -#include "block.h" -#include "low.h" -#include "medium.h" -#include "file.h" -#include "btree.h" -#include "record.h" -#include "os.h" - -#include "libc/byteorder.h" - -/* - * NAME: vol->init() - * DESCRIPTION: initialize volume structure - */ -void v_init(hfsvol *vol, int flags) -{ - btree *ext = &vol->ext; - btree *cat = &vol->cat; - - vol->os_fd = 0; - vol->flags = flags & HFS_VOL_OPT_MASK; - - vol->pnum = -1; - vol->vstart = 0; - vol->vlen = 0; - vol->lpa = 0; - - vol->cache = NULL; - - vol->vbm = NULL; - vol->vbmsz = 0; - - f_init(&ext->f, vol, HFS_CNID_EXT, "extents overflow"); - - ext->map = NULL; - ext->mapsz = 0; - ext->flags = 0; - - ext->keyunpack = (keyunpackfunc) r_unpackextkey; - ext->keycompare = (keycomparefunc) r_compareextkeys; - - f_init(&cat->f, vol, HFS_CNID_CAT, "catalog"); - - cat->map = NULL; - cat->mapsz = 0; - cat->flags = 0; - - cat->keyunpack = (keyunpackfunc) r_unpackcatkey; - cat->keycompare = (keycomparefunc) r_comparecatkeys; - - vol->cwd = HFS_CNID_ROOTDIR; - - vol->refs = 0; - vol->files = NULL; - vol->dirs = NULL; - - vol->prev = NULL; - vol->next = NULL; -} - -/* - * NAME: vol->open() - * DESCRIPTION: open volume source and lock against concurrent updates - */ -int v_open(hfsvol *vol, int os_fd ) -{ - if (vol->flags & HFS_VOL_OPEN) - ERROR(EINVAL, "volume already open"); - - vol->flags |= HFS_VOL_OPEN; - vol->os_fd = os_fd; - - /* initialize volume block cache (OK to fail) */ - - if (! (vol->flags & HFS_OPT_NOCACHE) && - b_init(vol) != -1) - vol->flags |= HFS_VOL_USINGCACHE; - - return 0; - -fail: - return -1; -} - -/* - * NAME: vol->close() - * DESCRIPTION: close access path to volume source - */ -int v_close(hfsvol *vol) -{ - int result = 0; - - if (! (vol->flags & HFS_VOL_OPEN)) - goto done; - - if ((vol->flags & HFS_VOL_USINGCACHE) && - b_finish(vol) == -1) - result = -1; - - vol->flags &= ~(HFS_VOL_OPEN | HFS_VOL_MOUNTED | HFS_VOL_USINGCACHE); - - /* free dynamically allocated structures */ - - FREE(vol->vbm); - - vol->vbm = NULL; - vol->vbmsz = 0; - - FREE(vol->ext.map); - FREE(vol->cat.map); - - vol->ext.map = NULL; - vol->cat.map = NULL; - -done: - return result; -} - -/* - * NAME: vol->same() - * DESCRIPTION: return 1 iff path is same as open volume - */ -int v_same(hfsvol *vol, int os_fd ) -{ - return vol->os_fd == os_fd; -} - -/* - * NAME: vol->geometry() - * DESCRIPTION: determine volume location and size (possibly in a partition) - */ -int v_geometry(hfsvol *vol, int pnum) -{ - Partition map; - unsigned long bnum = 0; - int found; - - vol->pnum = pnum; - - if (pnum == 0) - { - vol->vstart = 0; - vol->vlen = b_size(vol); - - if (vol->vlen == 0) - goto fail; - } - else - { - while (pnum--) - { - found = m_findpmentry(vol, "Apple_HFS", &map, &bnum); - if (found == -1 || ! found) - goto fail; - } - - vol->vstart = map.pmPyPartStart; - vol->vlen = map.pmPartBlkCnt; - - if (map.pmDataCnt) - { - if ((unsigned long) map.pmLgDataStart + - (unsigned long) map.pmDataCnt > vol->vlen) - ERROR(EINVAL, "partition data overflows partition"); - - vol->vstart += (unsigned long) map.pmLgDataStart; - vol->vlen = map.pmDataCnt; - } - - if (vol->vlen == 0) - ERROR(EINVAL, "volume partition is empty"); - } - - if (vol->vlen < 800 * (1024 >> HFS_BLOCKSZ_BITS)) - ERROR(EINVAL, "volume is smaller than 800K"); - - return 0; - -fail: - return -1; -} - -/* - * NAME: vol->readmdb() - * DESCRIPTION: load Master Directory Block into memory - */ -int v_readmdb(hfsvol *vol) -{ - if (l_getmdb(vol, &vol->mdb, 0) == -1) - goto fail; - - if (vol->mdb.drSigWord != HFS_SIGWORD) - { - if (vol->mdb.drSigWord == HFS_SIGWORD_MFS) - ERROR(EINVAL, "MFS volume format not supported"); - else - ERROR(EINVAL, "not a Macintosh HFS volume"); - } - - if (vol->mdb.drAlBlkSiz % HFS_BLOCKSZ != 0) - ERROR(EINVAL, "bad volume allocation block size"); - - vol->lpa = vol->mdb.drAlBlkSiz >> HFS_BLOCKSZ_BITS; - - /* extents pseudo-file structs */ - - vol->ext.f.cat.u.fil.filStBlk = vol->mdb.drXTExtRec[0].xdrStABN; - vol->ext.f.cat.u.fil.filLgLen = vol->mdb.drXTFlSize; - vol->ext.f.cat.u.fil.filPyLen = vol->mdb.drXTFlSize; - - vol->ext.f.cat.u.fil.filCrDat = vol->mdb.drCrDate; - vol->ext.f.cat.u.fil.filMdDat = vol->mdb.drLsMod; - - memcpy(&vol->ext.f.cat.u.fil.filExtRec, - &vol->mdb.drXTExtRec, sizeof(ExtDataRec)); - - f_selectfork(&vol->ext.f, fkData); - - /* catalog pseudo-file structs */ - - vol->cat.f.cat.u.fil.filStBlk = vol->mdb.drCTExtRec[0].xdrStABN; - vol->cat.f.cat.u.fil.filLgLen = vol->mdb.drCTFlSize; - vol->cat.f.cat.u.fil.filPyLen = vol->mdb.drCTFlSize; - - vol->cat.f.cat.u.fil.filCrDat = vol->mdb.drCrDate; - vol->cat.f.cat.u.fil.filMdDat = vol->mdb.drLsMod; - - memcpy(&vol->cat.f.cat.u.fil.filExtRec, - &vol->mdb.drCTExtRec, sizeof(ExtDataRec)); - - f_selectfork(&vol->cat.f, fkData); - - return 0; - -fail: - return -1; -} - -/* - * NAME: vol->readvbm() - * DESCRIPTION: read volume bitmap into memory - */ -int v_readvbm(hfsvol *vol) -{ - unsigned int vbmst = vol->mdb.drVBMSt; - unsigned int vbmsz = (vol->mdb.drNmAlBlks + 0x0fff) >> 12; - block *bp; - - ASSERT(vol->vbm == 0); - - if (vol->mdb.drAlBlSt - vbmst < vbmsz) - ERROR(EIO, "volume bitmap collides with volume data"); - - vol->vbm = ALLOC(block, vbmsz); - if (vol->vbm == NULL) - ERROR(ENOMEM, NULL); - - vol->vbmsz = vbmsz; - - for (bp = vol->vbm; vbmsz--; ++bp) - { - if (b_readlb(vol, vbmst++, bp) == -1) - goto fail; - } - - return 0; - -fail: - FREE(vol->vbm); - - vol->vbm = NULL; - vol->vbmsz = 0; - - return -1; -} - -/* - * NAME: vol->mount() - * DESCRIPTION: load volume information into memory - */ -int v_mount(hfsvol *vol) -{ - /* read the MDB, volume bitmap, and extents/catalog B*-tree headers */ - - if (v_readmdb(vol) == -1 || - v_readvbm(vol) == -1 || - bt_readhdr(&vol->ext) == -1 || - bt_readhdr(&vol->cat) == -1) - goto fail; - - if (vol->mdb.drAtrb & HFS_ATRB_SLOCKED) - vol->flags |= HFS_VOL_READONLY; - else if (vol->flags & HFS_VOL_READONLY) - vol->mdb.drAtrb |= HFS_ATRB_HLOCKED; - else - vol->mdb.drAtrb &= ~HFS_ATRB_HLOCKED; - - vol->flags |= HFS_VOL_MOUNTED; - - return 0; - -fail: - return -1; -} - -/* - * NAME: vol->catsearch() - * DESCRIPTION: search catalog tree - */ -int v_catsearch(hfsvol *vol, unsigned long parid, const char *name, - CatDataRec *data, char *cname, node *np) -{ - CatKeyRec key; - byte pkey[HFS_CATKEYLEN]; - const byte *ptr; - node n; - int found; - - if (np == NULL) - np = &n; - - r_makecatkey(&key, parid, name); - r_packcatkey(&key, pkey, NULL); - - found = bt_search(&vol->cat, pkey, np); - if (found <= 0) - return found; - - ptr = HFS_NODEREC(*np, np->rnum); - - if (cname) - { - r_unpackcatkey(ptr, &key); - strcpy(cname, key.ckrCName); - } - - if (data) - r_unpackcatdata(HFS_RECDATA(ptr), data); - - return 1; -} - -/* - * NAME: vol->extsearch() - * DESCRIPTION: search extents tree - */ -int v_extsearch(hfsfile *file, unsigned int fabn, - ExtDataRec *data, node *np) -{ - ExtKeyRec key; - ExtDataRec extsave; - unsigned int fabnsave; - byte pkey[HFS_EXTKEYLEN]; - const byte *ptr; - node n; - int found; - - if (np == NULL) - np = &n; - - r_makeextkey(&key, file->fork, file->cat.u.fil.filFlNum, fabn); - r_packextkey(&key, pkey, NULL); - - /* in case bt_search() clobbers these */ - - memcpy(&extsave, &file->ext, sizeof(ExtDataRec)); - fabnsave = file->fabn; - - found = bt_search(&file->vol->ext, pkey, np); - - memcpy(&file->ext, &extsave, sizeof(ExtDataRec)); - file->fabn = fabnsave; - - if (found <= 0) - return found; - - if (data) - { - ptr = HFS_NODEREC(*np, np->rnum); - r_unpackextdata(HFS_RECDATA(ptr), data); - } - - return 1; -} - -/* - * NAME: vol->getthread() - * DESCRIPTION: retrieve catalog thread information for a file or directory - */ -int v_getthread(hfsvol *vol, unsigned long id, - CatDataRec *thread, node *np, int type) -{ - CatDataRec rec; - int found; - - if (thread == NULL) - thread = &rec; - - found = v_catsearch(vol, id, "", thread, NULL, np); - if (found == 1 && thread->cdrType != type) - ERROR(EIO, "bad thread record"); - - return found; - -fail: - return -1; -} - - -/* - * NAME: vol->resolve() - * DESCRIPTION: translate a pathname; return catalog information - */ -int v_resolve(hfsvol **vol, const char *path, - CatDataRec *data, unsigned long *parid, char *fname, node *np) -{ - unsigned long dirid; - char name[HFS_MAX_FLEN + 1], *nptr; - int found = 0; - - if (*path == 0) - ERROR(ENOENT, "empty path"); - - if (parid) - *parid = 0; - - nptr = strchr(path, ':'); - - if (*path == ':' || nptr == NULL) - { - dirid = (*vol)->cwd; /* relative path */ - - if (*path == ':') - ++path; - - if (*path == 0) - { - found = v_getdthread(*vol, dirid, data, NULL); - if (found == -1) - goto fail; - - if (found) - { - if (parid) - *parid = data->u.dthd.thdParID; - - found = v_catsearch(*vol, data->u.dthd.thdParID, - data->u.dthd.thdCName, data, fname, np); - if (found == -1) - goto fail; - } - - goto done; - } - } - else - { - hfsvol *check; - - dirid = HFS_CNID_ROOTPAR; /* absolute path */ - - if (nptr - path > HFS_MAX_VLEN) - ERROR(ENAMETOOLONG, NULL); - - strncpy(name, path, nptr - path); - name[nptr - path] = 0; - - for (check = hfs_mounts; check; check = check->next) - { - if (d_relstring(check->mdb.drVN, name) == 0) - { - *vol = check; - break; - } - } - } - - while (1) - { - while (*path == ':') - { - ++path; - - found = v_getdthread(*vol, dirid, data, NULL); - if (found == -1) - goto fail; - else if (! found) - goto done; - - dirid = data->u.dthd.thdParID; - } - - if (*path == 0) - { - found = v_getdthread(*vol, dirid, data, NULL); - if (found == -1) - goto fail; - - if (found) - { - if (parid) - *parid = data->u.dthd.thdParID; - - found = v_catsearch(*vol, data->u.dthd.thdParID, - data->u.dthd.thdCName, data, fname, np); - if (found == -1) - goto fail; - } - - goto done; - } - - nptr = name; - while (nptr < name + sizeof(name) - 1 && *path && *path != ':') - *nptr++ = *path++; - - if (*path && *path != ':') - ERROR(ENAMETOOLONG, NULL); - - *nptr = 0; - if (*path == ':') - ++path; - - if (parid) - *parid = dirid; - - found = v_catsearch(*vol, dirid, name, data, fname, np); - if (found == -1) - goto fail; - - if (! found) - { - if (*path && parid) - *parid = 0; - - if (*path == 0 && fname) - strcpy(fname, name); - - goto done; - } - - switch (data->cdrType) - { - case cdrDirRec: - if (*path == 0) - goto done; - - dirid = data->u.dir.dirDirID; - break; - - case cdrFilRec: - if (*path == 0) - goto done; - - ERROR(ENOTDIR, "invalid pathname"); - - default: - ERROR(EIO, "unexpected catalog record"); - } - } - -done: - return found; - -fail: - return -1; -} - -/* Determine whether the volume is a HFS volume */ -int -v_probe(int fd, long long offset) -{ - MDB *mdb; - - mdb = (MDB*)malloc(2 * 512); - os_seek_offset( fd, 2 * 512 + offset ); - os_read(fd, mdb, 2, 9); - - if (__be16_to_cpu(mdb->drSigWord) != HFS_SIGWORD) { - free(mdb); - return 0; - } - - free(mdb); - return -1; -} |