diff options
Diffstat (limited to 'qemu/roms/openbios/fs/hfs/hfs.c')
-rw-r--r-- | qemu/roms/openbios/fs/hfs/hfs.c | 747 |
1 files changed, 0 insertions, 747 deletions
diff --git a/qemu/roms/openbios/fs/hfs/hfs.c b/qemu/roms/openbios/fs/hfs/hfs.c deleted file mode 100644 index 0c5fefb47..000000000 --- a/qemu/roms/openbios/fs/hfs/hfs.c +++ /dev/null @@ -1,747 +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: hfs.c,v 1.15 1998/11/02 22:09:00 rob Exp $ - */ - -#include "config.h" -#include "libhfs.h" -#include "data.h" -#include "block.h" -#include "medium.h" -#include "file.h" -#include "btree.h" -#include "node.h" -#include "record.h" -#include "volume.h" - -const char *hfs_error = "no error"; /* static error string */ - -hfsvol *hfs_mounts; /* linked list of mounted volumes */ - -static -hfsvol *curvol; /* current volume */ - - -/* - * NAME: getvol() - * DESCRIPTION: validate a volume reference - */ -static -int getvol(hfsvol **vol) -{ - if (*vol == NULL) - { - if (curvol == NULL) - ERROR(EINVAL, "no volume is current"); - - *vol = curvol; - } - - return 0; - -fail: - return -1; -} - -/* High-Level Volume Routines ============================================== */ - -/* - * NAME: hfs->mount() - * DESCRIPTION: open an HFS volume; return volume descriptor or 0 (error) - */ -hfsvol *hfs_mount( int os_fd, int pnum) -{ - hfsvol *vol, *check; - int mode = HFS_MODE_RDONLY; - - /* see if the volume is already mounted */ - for (check = hfs_mounts; check; check = check->next) - { - if (check->pnum == pnum && v_same(check, os_fd) == 1) - { - vol = check; - goto done; - } - } - - vol = ALLOC(hfsvol, 1); - if (vol == NULL) - ERROR(ENOMEM, NULL); - - v_init(vol, mode); - - vol->flags |= HFS_VOL_READONLY; - if( v_open(vol, os_fd) == -1 ) - goto fail; - - /* mount the volume */ - - if (v_geometry(vol, pnum) == -1 || - v_mount(vol) == -1) - goto fail; - - /* add to linked list of volumes */ - - vol->prev = NULL; - vol->next = hfs_mounts; - - if (hfs_mounts) - hfs_mounts->prev = vol; - - hfs_mounts = vol; - -done: - ++vol->refs; - curvol = vol; - - return vol; - -fail: - if (vol) - { - v_close(vol); - FREE(vol); - } - - return NULL; -} - - -/* - * NAME: hfs->umount() - * DESCRIPTION: close an HFS volume - */ -int hfs_umount(hfsvol *vol) -{ - int result = 0; - - if (getvol(&vol) == -1) - goto fail; - - if (--vol->refs) - { - goto done; - } - - /* close all open files and directories */ - - while (vol->files) - { - if (hfs_close(vol->files) == -1) - result = -1; - } - - while (vol->dirs) - { - if (hfs_closedir(vol->dirs) == -1) - result = -1; - } - - /* close medium */ - - if (v_close(vol) == -1) - result = -1; - - /* remove from linked list of volumes */ - - if (vol->prev) - vol->prev->next = vol->next; - if (vol->next) - vol->next->prev = vol->prev; - - if (vol == hfs_mounts) - hfs_mounts = vol->next; - if (vol == curvol) - curvol = NULL; - - FREE(vol); - -done: - return result; - -fail: - return -1; -} - -/* - * NAME: hfs->umountall() - * DESCRIPTION: unmount all mounted volumes - */ -void hfs_umountall(void) -{ - while (hfs_mounts) - hfs_umount(hfs_mounts); -} - -/* - * NAME: hfs->getvol() - * DESCRIPTION: return a pointer to a mounted volume - */ -hfsvol *hfs_getvol(const char *name) -{ - hfsvol *vol; - - if (name == NULL) - return curvol; - - for (vol = hfs_mounts; vol; vol = vol->next) - { - if (d_relstring(name, vol->mdb.drVN) == 0) - return vol; - } - - return NULL; -} - -/* - * NAME: hfs->setvol() - * DESCRIPTION: change the current volume - */ -void hfs_setvol(hfsvol *vol) -{ - curvol = vol; -} - -/* - * NAME: hfs->vstat() - * DESCRIPTION: return volume statistics - */ -int hfs_vstat(hfsvol *vol, hfsvolent *ent) -{ - if (getvol(&vol) == -1) - goto fail; - - strcpy(ent->name, vol->mdb.drVN); - - ent->flags = (vol->flags & HFS_VOL_READONLY) ? HFS_ISLOCKED : 0; - - ent->totbytes = vol->mdb.drNmAlBlks * vol->mdb.drAlBlkSiz; - ent->freebytes = vol->mdb.drFreeBks * vol->mdb.drAlBlkSiz; - - ent->alblocksz = vol->mdb.drAlBlkSiz; - ent->clumpsz = vol->mdb.drClpSiz; - - ent->numfiles = vol->mdb.drFilCnt; - ent->numdirs = vol->mdb.drDirCnt; - - ent->crdate = d_ltime(vol->mdb.drCrDate); - ent->mddate = d_ltime(vol->mdb.drLsMod); - ent->bkdate = d_ltime(vol->mdb.drVolBkUp); - - ent->blessed = vol->mdb.drFndrInfo[0]; - - return 0; - -fail: - return -1; -} - - -/* High-Level Directory Routines =========================================== */ - -/* - * NAME: hfs->chdir() - * DESCRIPTION: change current HFS directory - */ -int hfs_chdir(hfsvol *vol, const char *path) -{ - CatDataRec data; - - if (getvol(&vol) == -1 || - v_resolve(&vol, path, &data, NULL, NULL, NULL) <= 0) - goto fail; - - if (data.cdrType != cdrDirRec) - ERROR(ENOTDIR, NULL); - - vol->cwd = data.u.dir.dirDirID; - - return 0; - -fail: - return -1; -} - -/* - * NAME: hfs->getcwd() - * DESCRIPTION: return the current working directory ID - */ -unsigned long hfs_getcwd(hfsvol *vol) -{ - if (getvol(&vol) == -1) - return 0; - - return vol->cwd; -} - -/* - * NAME: hfs->setcwd() - * DESCRIPTION: set the current working directory ID - */ -int hfs_setcwd(hfsvol *vol, unsigned long id) -{ - if (getvol(&vol) == -1) - goto fail; - - if (id == vol->cwd) - goto done; - - /* make sure the directory exists */ - - if (v_getdthread(vol, id, NULL, NULL) <= 0) - goto fail; - - vol->cwd = id; - -done: - return 0; - -fail: - return -1; -} - -/* - * NAME: hfs->dirinfo() - * DESCRIPTION: given a directory ID, return its (name and) parent ID - */ -int hfs_dirinfo(hfsvol *vol, unsigned long *id, char *name) -{ - CatDataRec thread; - - if (getvol(&vol) == -1 || - v_getdthread(vol, *id, &thread, NULL) <= 0) - goto fail; - - *id = thread.u.dthd.thdParID; - - if (name) - strcpy(name, thread.u.dthd.thdCName); - - return 0; - -fail: - return -1; -} - -/* - * NAME: hfs->opendir() - * DESCRIPTION: prepare to read the contents of a directory - */ -hfsdir *hfs_opendir(hfsvol *vol, const char *path) -{ - hfsdir *dir = NULL; - CatKeyRec key; - CatDataRec data; - byte pkey[HFS_CATKEYLEN]; - - if (getvol(&vol) == -1) - goto fail; - - dir = ALLOC(hfsdir, 1); - if (dir == NULL) - ERROR(ENOMEM, NULL); - - dir->vol = vol; - - if (*path == 0) - { - /* meta-directory containing root dirs from all mounted volumes */ - - dir->dirid = 0; - dir->vptr = hfs_mounts; - } - else - { - if (v_resolve(&vol, path, &data, NULL, NULL, NULL) <= 0) - goto fail; - - if (data.cdrType != cdrDirRec) - ERROR(ENOTDIR, NULL); - - dir->dirid = data.u.dir.dirDirID; - dir->vptr = NULL; - - r_makecatkey(&key, dir->dirid, ""); - r_packcatkey(&key, pkey, NULL); - - if (bt_search(&vol->cat, pkey, &dir->n) <= 0) - goto fail; - } - - dir->prev = NULL; - dir->next = vol->dirs; - - if (vol->dirs) - vol->dirs->prev = dir; - - vol->dirs = dir; - - return dir; - -fail: - FREE(dir); - return NULL; -} - -/* - * NAME: hfs->readdir() - * DESCRIPTION: return the next entry in the directory - */ -int hfs_readdir(hfsdir *dir, hfsdirent *ent) -{ - CatKeyRec key; - CatDataRec data; - const byte *ptr; - - if (dir->dirid == 0) - { - hfsvol *vol; - char cname[HFS_MAX_FLEN + 1]; - - for (vol = hfs_mounts; vol; vol = vol->next) - { - if (vol == dir->vptr) - break; - } - - if (vol == NULL) - ERROR(ENOENT, "no more entries"); - - if (v_getdthread(vol, HFS_CNID_ROOTDIR, &data, NULL) <= 0 || - v_catsearch(vol, HFS_CNID_ROOTPAR, data.u.dthd.thdCName, - &data, cname, NULL) <= 0) - goto fail; - - r_unpackdirent(HFS_CNID_ROOTPAR, cname, &data, ent); - - dir->vptr = vol->next; - - goto done; - } - - if (dir->n.rnum == -1) - ERROR(ENOENT, "no more entries"); - - while (1) - { - ++dir->n.rnum; - - while (dir->n.rnum >= dir->n.nd.ndNRecs) - { - if (dir->n.nd.ndFLink == 0) - { - dir->n.rnum = -1; - ERROR(ENOENT, "no more entries"); - } - - if (bt_getnode(&dir->n, dir->n.bt, dir->n.nd.ndFLink) == -1) - { - dir->n.rnum = -1; - goto fail; - } - - dir->n.rnum = 0; - } - - ptr = HFS_NODEREC(dir->n, dir->n.rnum); - - r_unpackcatkey(ptr, &key); - - if (key.ckrParID != dir->dirid) - { - dir->n.rnum = -1; - ERROR(ENOENT, "no more entries"); - } - - r_unpackcatdata(HFS_RECDATA(ptr), &data); - - switch (data.cdrType) - { - case cdrDirRec: - case cdrFilRec: - r_unpackdirent(key.ckrParID, key.ckrCName, &data, ent); - goto done; - - case cdrThdRec: - case cdrFThdRec: - break; - - default: - dir->n.rnum = -1; - ERROR(EIO, "unexpected directory entry found"); - } - } - -done: - return 0; - -fail: - return -1; -} - -/* - * NAME: hfs->closedir() - * DESCRIPTION: stop reading a directory - */ -int hfs_closedir(hfsdir *dir) -{ - hfsvol *vol = dir->vol; - - if (dir->prev) - dir->prev->next = dir->next; - if (dir->next) - dir->next->prev = dir->prev; - if (dir == vol->dirs) - vol->dirs = dir->next; - - FREE(dir); - - return 0; -} - -/* High-Level File Routines ================================================ */ - -/* - * NAME: hfs->open() - * DESCRIPTION: prepare a file for I/O - */ -hfsfile *hfs_open(hfsvol *vol, const char *path) -{ - hfsfile *file = NULL; - - if (getvol(&vol) == -1) - goto fail; - - file = ALLOC(hfsfile, 1); - if (file == NULL) - ERROR(ENOMEM, NULL); - - if (v_resolve(&vol, path, &file->cat, &file->parid, file->name, NULL) <= 0) - goto fail; - - if (file->cat.cdrType != cdrFilRec) - ERROR(EISDIR, NULL); - - /* package file handle for user */ - - file->vol = vol; - file->flags = 0; - - f_selectfork(file, fkData); - - file->prev = NULL; - file->next = vol->files; - - if (vol->files) - vol->files->prev = file; - - vol->files = file; - - return file; - -fail: - FREE(file); - return NULL; -} - -/* - * NAME: hfs->setfork() - * DESCRIPTION: select file fork for I/O operations - */ -int hfs_setfork(hfsfile *file, int fork) -{ - int result = 0; - - f_selectfork(file, fork ? fkRsrc : fkData); - - return result; -} - -/* - * NAME: hfs->getfork() - * DESCRIPTION: return the current fork for I/O operations - */ -int hfs_getfork(hfsfile *file) -{ - return file->fork != fkData; -} - -/* - * NAME: hfs->read() - * DESCRIPTION: read from an open file - */ -unsigned long hfs_read(hfsfile *file, void *buf, unsigned long len) -{ - unsigned long *lglen, count; - byte *ptr = buf; - - f_getptrs(file, NULL, &lglen, NULL); - - if (file->pos + len > *lglen) - len = *lglen - file->pos; - - count = len; - while (count) - { - unsigned long bnum, offs, chunk; - - bnum = file->pos >> HFS_BLOCKSZ_BITS; - offs = file->pos & (HFS_BLOCKSZ - 1); - - chunk = HFS_BLOCKSZ - offs; - if (chunk > count) - chunk = count; - - if (offs == 0 && chunk == HFS_BLOCKSZ) - { - if (f_getblock(file, bnum, (block *) ptr) == -1) - goto fail; - } - else - { - block b; - - if (f_getblock(file, bnum, &b) == -1) - goto fail; - - memcpy(ptr, b + offs, chunk); - } - - ptr += chunk; - - file->pos += chunk; - count -= chunk; - } - - return len; - -fail: - return -1; -} - -/* - * NAME: hfs->seek() - * DESCRIPTION: change file seek pointer - */ -unsigned long hfs_seek(hfsfile *file, long offset, int from) -{ - unsigned long *lglen, newpos; - - f_getptrs(file, NULL, &lglen, NULL); - - switch (from) - { - case HFS_SEEK_SET: - newpos = (offset < 0) ? 0 : offset; - break; - - case HFS_SEEK_CUR: - if (offset < 0 && (unsigned long) -offset > file->pos) - newpos = 0; - else - newpos = file->pos + offset; - break; - - case HFS_SEEK_END: - if (offset < 0 && (unsigned long) -offset > *lglen) - newpos = 0; - else - newpos = *lglen + offset; - break; - - default: - ERROR(EINVAL, NULL); - } - - if (newpos > *lglen) - newpos = *lglen; - - file->pos = newpos; - - return newpos; - -fail: - return -1; -} - -/* - * NAME: hfs->close() - * DESCRIPTION: close a file - */ -int hfs_close(hfsfile *file) -{ - hfsvol *vol = file->vol; - int result = 0; - - if (file->prev) - file->prev->next = file->next; - if (file->next) - file->next->prev = file->prev; - if (file == vol->files) - vol->files = file->next; - - FREE(file); - - return result; -} - -/* High-Level Catalog Routines ============================================= */ - -/* - * NAME: hfs->stat() - * DESCRIPTION: return catalog information for an arbitrary path - */ -int hfs_stat(hfsvol *vol, const char *path, hfsdirent *ent) -{ - CatDataRec data; - unsigned long parid; - char name[HFS_MAX_FLEN + 1]; - - if (getvol(&vol) == -1 || - v_resolve(&vol, path, &data, &parid, name, NULL) <= 0) - goto fail; - - r_unpackdirent(parid, name, &data, ent); - - return 0; - -fail: - return -1; -} - -/* - * NAME: hfs->fstat() - * DESCRIPTION: return catalog information for an open file - */ -int hfs_fstat(hfsfile *file, hfsdirent *ent) -{ - r_unpackdirent(file->parid, file->name, &file->cat, ent); - - return 0; -} - -/* - * NAME: hfs->probe() - * DESCRIPTION: return whether a HFS filesystem is present at the given offset - */ -int hfs_probe(int fd, long long offset) -{ - return v_probe(fd, offset); -} |