diff options
Diffstat (limited to 'qemu/roms/openbios/fs/hfs/record.c')
-rw-r--r-- | qemu/roms/openbios/fs/hfs/record.c | 553 |
1 files changed, 553 insertions, 0 deletions
diff --git a/qemu/roms/openbios/fs/hfs/record.c b/qemu/roms/openbios/fs/hfs/record.c new file mode 100644 index 000000000..92a3adddf --- /dev/null +++ b/qemu/roms/openbios/fs/hfs/record.c @@ -0,0 +1,553 @@ +/* + * 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: record.c,v 1.9 1998/11/02 22:09:07 rob Exp $ + */ + +#include "config.h" +#include "libhfs.h" +#include "record.h" +#include "data.h" + +/* + * NAME: record->packcatkey() + * DESCRIPTION: pack a catalog record key + */ +void r_packcatkey(const CatKeyRec *key, byte *pkey, unsigned int *len) +{ + const byte *start = pkey; + + d_storesb(&pkey, key->ckrKeyLen); + d_storesb(&pkey, key->ckrResrv1); + d_storeul(&pkey, key->ckrParID); + + d_storestr(&pkey, key->ckrCName, sizeof(key->ckrCName)); + + if (len) + *len = HFS_RECKEYSKIP(start); +} + +/* + * NAME: record->unpackcatkey() + * DESCRIPTION: unpack a catalog record key + */ +void r_unpackcatkey(const byte *pkey, CatKeyRec *key) +{ + d_fetchsb(&pkey, &key->ckrKeyLen); + d_fetchsb(&pkey, &key->ckrResrv1); + d_fetchul(&pkey, &key->ckrParID); + + d_fetchstr(&pkey, key->ckrCName, sizeof(key->ckrCName)); +} + +/* + * NAME: record->packextkey() + * DESCRIPTION: pack an extents record key + */ +void r_packextkey(const ExtKeyRec *key, byte *pkey, unsigned int *len) +{ + const byte *start = pkey; + + d_storesb(&pkey, key->xkrKeyLen); + d_storesb(&pkey, key->xkrFkType); + d_storeul(&pkey, key->xkrFNum); + d_storeuw(&pkey, key->xkrFABN); + + if (len) + *len = HFS_RECKEYSKIP(start); +} + +/* + * NAME: record->unpackextkey() + * DESCRIPTION: unpack an extents record key + */ +void r_unpackextkey(const byte *pkey, ExtKeyRec *key) +{ + d_fetchsb(&pkey, &key->xkrKeyLen); + d_fetchsb(&pkey, &key->xkrFkType); + d_fetchul(&pkey, &key->xkrFNum); + d_fetchuw(&pkey, &key->xkrFABN); +} + +/* + * NAME: record->comparecatkeys() + * DESCRIPTION: compare two (packed) catalog record keys + */ +int r_comparecatkeys(const CatKeyRec *key1, const CatKeyRec *key2) +{ + int diff; + + diff = key1->ckrParID - key2->ckrParID; + if (diff) + return diff; + + return d_relstring(key1->ckrCName, key2->ckrCName); +} + +/* + * NAME: record->compareextkeys() + * DESCRIPTION: compare two (packed) extents record keys + */ +int r_compareextkeys(const ExtKeyRec *key1, const ExtKeyRec *key2) +{ + int diff; + + diff = key1->xkrFNum - key2->xkrFNum; + if (diff) + return diff; + + diff = (unsigned char) key1->xkrFkType - + (unsigned char) key2->xkrFkType; + if (diff) + return diff; + + return key1->xkrFABN - key2->xkrFABN; +} + +/* + * NAME: record->packcatdata() + * DESCRIPTION: pack catalog record data + */ +void r_packcatdata(const CatDataRec *data, byte *pdata, unsigned int *len) +{ + const byte *start = pdata; + int i; + + d_storesb(&pdata, data->cdrType); + d_storesb(&pdata, data->cdrResrv2); + + switch (data->cdrType) + { + case cdrDirRec: + d_storesw(&pdata, data->u.dir.dirFlags); + d_storeuw(&pdata, data->u.dir.dirVal); + d_storeul(&pdata, data->u.dir.dirDirID); + d_storesl(&pdata, data->u.dir.dirCrDat); + d_storesl(&pdata, data->u.dir.dirMdDat); + d_storesl(&pdata, data->u.dir.dirBkDat); + + d_storesw(&pdata, data->u.dir.dirUsrInfo.frRect.top); + d_storesw(&pdata, data->u.dir.dirUsrInfo.frRect.left); + d_storesw(&pdata, data->u.dir.dirUsrInfo.frRect.bottom); + d_storesw(&pdata, data->u.dir.dirUsrInfo.frRect.right); + d_storesw(&pdata, data->u.dir.dirUsrInfo.frFlags); + d_storesw(&pdata, data->u.dir.dirUsrInfo.frLocation.v); + d_storesw(&pdata, data->u.dir.dirUsrInfo.frLocation.h); + d_storesw(&pdata, data->u.dir.dirUsrInfo.frView); + + d_storesw(&pdata, data->u.dir.dirFndrInfo.frScroll.v); + d_storesw(&pdata, data->u.dir.dirFndrInfo.frScroll.h); + d_storesl(&pdata, data->u.dir.dirFndrInfo.frOpenChain); + d_storesw(&pdata, data->u.dir.dirFndrInfo.frUnused); + d_storesw(&pdata, data->u.dir.dirFndrInfo.frComment); + d_storesl(&pdata, data->u.dir.dirFndrInfo.frPutAway); + + for (i = 0; i < 4; ++i) + d_storesl(&pdata, data->u.dir.dirResrv[i]); + + break; + + case cdrFilRec: + d_storesb(&pdata, data->u.fil.filFlags); + d_storesb(&pdata, data->u.fil.filTyp); + + d_storesl(&pdata, data->u.fil.filUsrWds.fdType); + d_storesl(&pdata, data->u.fil.filUsrWds.fdCreator); + d_storesw(&pdata, data->u.fil.filUsrWds.fdFlags); + d_storesw(&pdata, data->u.fil.filUsrWds.fdLocation.v); + d_storesw(&pdata, data->u.fil.filUsrWds.fdLocation.h); + d_storesw(&pdata, data->u.fil.filUsrWds.fdFldr); + + d_storeul(&pdata, data->u.fil.filFlNum); + + d_storeuw(&pdata, data->u.fil.filStBlk); + d_storeul(&pdata, data->u.fil.filLgLen); + d_storeul(&pdata, data->u.fil.filPyLen); + + d_storeuw(&pdata, data->u.fil.filRStBlk); + d_storeul(&pdata, data->u.fil.filRLgLen); + d_storeul(&pdata, data->u.fil.filRPyLen); + + d_storesl(&pdata, data->u.fil.filCrDat); + d_storesl(&pdata, data->u.fil.filMdDat); + d_storesl(&pdata, data->u.fil.filBkDat); + + d_storesw(&pdata, data->u.fil.filFndrInfo.fdIconID); + for (i = 0; i < 4; ++i) + d_storesw(&pdata, data->u.fil.filFndrInfo.fdUnused[i]); + d_storesw(&pdata, data->u.fil.filFndrInfo.fdComment); + d_storesl(&pdata, data->u.fil.filFndrInfo.fdPutAway); + + d_storeuw(&pdata, data->u.fil.filClpSize); + + for (i = 0; i < 3; ++i) + { + d_storeuw(&pdata, data->u.fil.filExtRec[i].xdrStABN); + d_storeuw(&pdata, data->u.fil.filExtRec[i].xdrNumABlks); + } + + for (i = 0; i < 3; ++i) + { + d_storeuw(&pdata, data->u.fil.filRExtRec[i].xdrStABN); + d_storeuw(&pdata, data->u.fil.filRExtRec[i].xdrNumABlks); + } + + d_storesl(&pdata, data->u.fil.filResrv); + + break; + + case cdrThdRec: + for (i = 0; i < 2; ++i) + d_storesl(&pdata, data->u.dthd.thdResrv[i]); + + d_storeul(&pdata, data->u.dthd.thdParID); + + d_storestr(&pdata, data->u.dthd.thdCName, + sizeof(data->u.dthd.thdCName)); + + break; + + case cdrFThdRec: + for (i = 0; i < 2; ++i) + d_storesl(&pdata, data->u.fthd.fthdResrv[i]); + + d_storeul(&pdata, data->u.fthd.fthdParID); + + d_storestr(&pdata, data->u.fthd.fthdCName, + sizeof(data->u.fthd.fthdCName)); + + break; + + default: + ASSERT(0); + } + + if (len) + *len += pdata - start; +} + +/* + * NAME: record->unpackcatdata() + * DESCRIPTION: unpack catalog record data + */ +void r_unpackcatdata(const byte *pdata, CatDataRec *data) +{ + int i; + + d_fetchsb(&pdata, &data->cdrType); + d_fetchsb(&pdata, &data->cdrResrv2); + + switch (data->cdrType) + { + case cdrDirRec: + d_fetchsw(&pdata, &data->u.dir.dirFlags); + d_fetchuw(&pdata, &data->u.dir.dirVal); + d_fetchul(&pdata, &data->u.dir.dirDirID); + d_fetchsl(&pdata, &data->u.dir.dirCrDat); + d_fetchsl(&pdata, &data->u.dir.dirMdDat); + d_fetchsl(&pdata, &data->u.dir.dirBkDat); + + d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frRect.top); + d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frRect.left); + d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frRect.bottom); + d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frRect.right); + d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frFlags); + d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frLocation.v); + d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frLocation.h); + d_fetchsw(&pdata, &data->u.dir.dirUsrInfo.frView); + + d_fetchsw(&pdata, &data->u.dir.dirFndrInfo.frScroll.v); + d_fetchsw(&pdata, &data->u.dir.dirFndrInfo.frScroll.h); + d_fetchsl(&pdata, &data->u.dir.dirFndrInfo.frOpenChain); + d_fetchsw(&pdata, &data->u.dir.dirFndrInfo.frUnused); + d_fetchsw(&pdata, &data->u.dir.dirFndrInfo.frComment); + d_fetchsl(&pdata, &data->u.dir.dirFndrInfo.frPutAway); + + for (i = 0; i < 4; ++i) + d_fetchsl(&pdata, &data->u.dir.dirResrv[i]); + + break; + + case cdrFilRec: + d_fetchsb(&pdata, &data->u.fil.filFlags); + d_fetchsb(&pdata, &data->u.fil.filTyp); + + d_fetchsl(&pdata, &data->u.fil.filUsrWds.fdType); + d_fetchsl(&pdata, &data->u.fil.filUsrWds.fdCreator); + d_fetchsw(&pdata, &data->u.fil.filUsrWds.fdFlags); + d_fetchsw(&pdata, &data->u.fil.filUsrWds.fdLocation.v); + d_fetchsw(&pdata, &data->u.fil.filUsrWds.fdLocation.h); + d_fetchsw(&pdata, &data->u.fil.filUsrWds.fdFldr); + + d_fetchul(&pdata, &data->u.fil.filFlNum); + + d_fetchuw(&pdata, &data->u.fil.filStBlk); + d_fetchul(&pdata, &data->u.fil.filLgLen); + d_fetchul(&pdata, &data->u.fil.filPyLen); + + d_fetchuw(&pdata, &data->u.fil.filRStBlk); + d_fetchul(&pdata, &data->u.fil.filRLgLen); + d_fetchul(&pdata, &data->u.fil.filRPyLen); + + d_fetchsl(&pdata, &data->u.fil.filCrDat); + d_fetchsl(&pdata, &data->u.fil.filMdDat); + d_fetchsl(&pdata, &data->u.fil.filBkDat); + + d_fetchsw(&pdata, &data->u.fil.filFndrInfo.fdIconID); + for (i = 0; i < 4; ++i) + d_fetchsw(&pdata, &data->u.fil.filFndrInfo.fdUnused[i]); + d_fetchsw(&pdata, &data->u.fil.filFndrInfo.fdComment); + d_fetchsl(&pdata, &data->u.fil.filFndrInfo.fdPutAway); + + d_fetchuw(&pdata, &data->u.fil.filClpSize); + + for (i = 0; i < 3; ++i) + { + d_fetchuw(&pdata, &data->u.fil.filExtRec[i].xdrStABN); + d_fetchuw(&pdata, &data->u.fil.filExtRec[i].xdrNumABlks); + } + + for (i = 0; i < 3; ++i) + { + d_fetchuw(&pdata, &data->u.fil.filRExtRec[i].xdrStABN); + d_fetchuw(&pdata, &data->u.fil.filRExtRec[i].xdrNumABlks); + } + + d_fetchsl(&pdata, &data->u.fil.filResrv); + + break; + + case cdrThdRec: + for (i = 0; i < 2; ++i) + d_fetchsl(&pdata, &data->u.dthd.thdResrv[i]); + + d_fetchul(&pdata, &data->u.dthd.thdParID); + + d_fetchstr(&pdata, data->u.dthd.thdCName, + sizeof(data->u.dthd.thdCName)); + + break; + + case cdrFThdRec: + for (i = 0; i < 2; ++i) + d_fetchsl(&pdata, &data->u.fthd.fthdResrv[i]); + + d_fetchul(&pdata, &data->u.fthd.fthdParID); + + d_fetchstr(&pdata, data->u.fthd.fthdCName, + sizeof(data->u.fthd.fthdCName)); + + break; + + default: + ASSERT(0); + } +} + +/* + * NAME: record->packextdata() + * DESCRIPTION: pack extent record data + */ +void r_packextdata(const ExtDataRec *data, byte *pdata, unsigned int *len) +{ + const byte *start = pdata; + int i; + + for (i = 0; i < 3; ++i) + { + d_storeuw(&pdata, (*data)[i].xdrStABN); + d_storeuw(&pdata, (*data)[i].xdrNumABlks); + } + + if (len) + *len += pdata - start; +} + +/* + * NAME: record->unpackextdata() + * DESCRIPTION: unpack extent record data + */ +void r_unpackextdata(const byte *pdata, ExtDataRec *data) +{ + int i; + + for (i = 0; i < 3; ++i) + { + d_fetchuw(&pdata, &(*data)[i].xdrStABN); + d_fetchuw(&pdata, &(*data)[i].xdrNumABlks); + } +} + +/* + * NAME: record->makecatkey() + * DESCRIPTION: construct a catalog record key + */ +void r_makecatkey(CatKeyRec *key, unsigned long parid, const char *name) +{ + int len; + + len = strlen(name) + 1; + + key->ckrKeyLen = 0x05 + len + (len & 1); + key->ckrResrv1 = 0; + key->ckrParID = parid; + + strcpy(key->ckrCName, name); +} + +/* + * NAME: record->makeextkey() + * DESCRIPTION: construct an extents record key + */ +void r_makeextkey(ExtKeyRec *key, + int fork, unsigned long fnum, unsigned int fabn) +{ + key->xkrKeyLen = 0x07; + key->xkrFkType = fork; + key->xkrFNum = fnum; + key->xkrFABN = fabn; +} + +/* + * NAME: record->packcatrec() + * DESCRIPTION: create a packed catalog record + */ +void r_packcatrec(const CatKeyRec *key, const CatDataRec *data, + byte *precord, unsigned int *len) +{ + r_packcatkey(key, precord, len); + r_packcatdata(data, HFS_RECDATA(precord), len); +} + +/* + * NAME: record->packextrec() + * DESCRIPTION: create a packed extents record + */ +void r_packextrec(const ExtKeyRec *key, const ExtDataRec *data, + byte *precord, unsigned int *len) +{ + r_packextkey(key, precord, len); + r_packextdata(data, HFS_RECDATA(precord), len); +} + +/* + * NAME: record->packdirent() + * DESCRIPTION: make changes to a catalog record + */ +void r_packdirent(CatDataRec *data, const hfsdirent *ent) +{ + switch (data->cdrType) + { + case cdrDirRec: + data->u.dir.dirCrDat = d_mtime(ent->crdate); + data->u.dir.dirMdDat = d_mtime(ent->mddate); + data->u.dir.dirBkDat = d_mtime(ent->bkdate); + + data->u.dir.dirUsrInfo.frFlags = ent->fdflags; + data->u.dir.dirUsrInfo.frLocation.v = ent->fdlocation.v; + data->u.dir.dirUsrInfo.frLocation.h = ent->fdlocation.h; + + data->u.dir.dirUsrInfo.frRect.top = ent->u.dir.rect.top; + data->u.dir.dirUsrInfo.frRect.left = ent->u.dir.rect.left; + data->u.dir.dirUsrInfo.frRect.bottom = ent->u.dir.rect.bottom; + data->u.dir.dirUsrInfo.frRect.right = ent->u.dir.rect.right; + + break; + + case cdrFilRec: + if (ent->flags & HFS_ISLOCKED) + data->u.fil.filFlags |= (1 << 0); + else + data->u.fil.filFlags &= ~(1 << 0); + + data->u.fil.filCrDat = d_mtime(ent->crdate); + data->u.fil.filMdDat = d_mtime(ent->mddate); + data->u.fil.filBkDat = d_mtime(ent->bkdate); + + data->u.fil.filUsrWds.fdFlags = ent->fdflags; + data->u.fil.filUsrWds.fdLocation.v = ent->fdlocation.v; + data->u.fil.filUsrWds.fdLocation.h = ent->fdlocation.h; + + data->u.fil.filUsrWds.fdType = + d_getsl((const unsigned char *) ent->u.file.type); + data->u.fil.filUsrWds.fdCreator = + d_getsl((const unsigned char *) ent->u.file.creator); + + break; + } +} + +/* + * NAME: record->unpackdirent() + * DESCRIPTION: unpack catalog information into hfsdirent structure + */ +void r_unpackdirent(unsigned long parid, const char *name, + const CatDataRec *data, hfsdirent *ent) +{ + strcpy(ent->name, name); + ent->parid = parid; + + switch (data->cdrType) + { + case cdrDirRec: + ent->flags = HFS_ISDIR; + ent->cnid = data->u.dir.dirDirID; + + ent->crdate = d_ltime(data->u.dir.dirCrDat); + ent->mddate = d_ltime(data->u.dir.dirMdDat); + ent->bkdate = d_ltime(data->u.dir.dirBkDat); + + ent->fdflags = data->u.dir.dirUsrInfo.frFlags; + ent->fdlocation.v = data->u.dir.dirUsrInfo.frLocation.v; + ent->fdlocation.h = data->u.dir.dirUsrInfo.frLocation.h; + + ent->u.dir.valence = data->u.dir.dirVal; + + ent->u.dir.rect.top = data->u.dir.dirUsrInfo.frRect.top; + ent->u.dir.rect.left = data->u.dir.dirUsrInfo.frRect.left; + ent->u.dir.rect.bottom = data->u.dir.dirUsrInfo.frRect.bottom; + ent->u.dir.rect.right = data->u.dir.dirUsrInfo.frRect.right; + + break; + + case cdrFilRec: + ent->flags = (data->u.fil.filFlags & (1 << 0)) ? HFS_ISLOCKED : 0; + ent->cnid = data->u.fil.filFlNum; + + ent->crdate = d_ltime(data->u.fil.filCrDat); + ent->mddate = d_ltime(data->u.fil.filMdDat); + ent->bkdate = d_ltime(data->u.fil.filBkDat); + + ent->fdflags = data->u.fil.filUsrWds.fdFlags; + ent->fdlocation.v = data->u.fil.filUsrWds.fdLocation.v; + ent->fdlocation.h = data->u.fil.filUsrWds.fdLocation.h; + + ent->u.file.dsize = data->u.fil.filLgLen; + ent->u.file.rsize = data->u.fil.filRLgLen; + + d_putsl((unsigned char *) ent->u.file.type, + data->u.fil.filUsrWds.fdType); + d_putsl((unsigned char *) ent->u.file.creator, + data->u.fil.filUsrWds.fdCreator); + + ent->u.file.type[4] = ent->u.file.creator[4] = 0; + + break; + } +} |