executor/src/hfsFile.c

1656 lines
43 KiB
C

/* Copyright 1992 - 1996 by Abacus Research and
* Development, Inc. All rights reserved.
*/
#if !defined (OMIT_RCSID_STRINGS)
char ROMlib_rcsid_hfsFile[] =
"$Id: hfsFile.c 87 2005-05-25 01:57:33Z ctm $";
#endif
#include "rsys/common.h"
#include "OSUtil.h"
#include "FileMgr.h"
#include "MemoryMgr.h"
#include "rsys/file.h"
#include "rsys/hfs.h"
PUBLIC filecontrolblock *ROMlib_getfreefcbp( void )
{
short length;
filecontrolblock *fcbp, *efcbp;
length = CW(*(short *)MR(FCBSPtr));
fcbp = (filecontrolblock *) ((short *)MR(FCBSPtr)+1);
efcbp = (filecontrolblock *) ((char *)MR(FCBSPtr) + length);
for (;fcbp < efcbp && Cx(fcbp->fcbFlNum);
fcbp = (filecontrolblock *) ((char *)fcbp + CW(FSFCBLen)))
;
return fcbp < efcbp ? fcbp : 0;
}
PUBLIC filecontrolblock *ROMlib_refnumtofcbp(uint16 refnum)
{
uint16 len;
filecontrolblock *retval;
if (refnum < sizeof(short) || refnum % CW(FSFCBLen) != sizeof(short))
return 0;
len = CW(*(uint16 *)MR(FCBSPtr));
if (refnum >= len)
return 0;
retval = (filecontrolblock *)((char *)MR(FCBSPtr) + refnum);
if (retval->fcbFlNum == 0)
retval = 0;
return retval;
}
PRIVATE LONGINT pbabsoffset(ioParam *pb, filecontrolblock *fcbp)
{
switch (CW(pb->ioPosMode) & 0x3) {
case fsAtMark:
return Cx(fcbp->fcbCrPs);
case fsFromStart:
return Cx(pb->ioPosOffset);
case fsFromLEOF:
return Cx(fcbp->fcbEOF) + Cx(pb->ioPosOffset);
case fsFromMark:
return Cx(fcbp->fcbCrPs) + Cx(pb->ioPosOffset);
default:
return -1;
}
}
PRIVATE LONGINT xtntbnotophys(xtntrec xtr, unsigned short bno,
unsigned short *nphyscontigp)
{
unsigned short bc;
LONGINT retblock;
bc = Cx(xtr[0].blockcount);
if (bno < bc) {
*nphyscontigp = bc - bno;
retblock = Cx(xtr[0].blockstart) + bno;
} else {
bno -= bc;
bc = Cx(xtr[1].blockcount);
if (bno < bc) {
*nphyscontigp = bc - bno;
retblock = Cx(xtr[1].blockstart) + bno;
} else {
bno -= bc;
bc = Cx(xtr[2].blockcount);
if (bno < bc) {
*nphyscontigp = bc - bno;
retblock = Cx(xtr[2].blockstart) + bno;
} else
retblock = -1;
}
}
return retblock;
}
PUBLIC compretval ROMlib_xtntcompare(void *firstp, void *secondp)
{
xtntkey *xp1, *xp2;
xp1 = firstp;
xp2 = secondp;
if (Cx(xp1->xkrFNum) < Cx(xp2->xkrFNum))
return firstisless;
else if (Cx(xp1->xkrFNum) > Cx(xp2->xkrFNum))
return firstisgreater;
else {
if (Cx(xp1->xkrFkType) < Cx(xp2->xkrFkType))
return firstisless;
else if (Cx(xp1->xkrFkType) > Cx(xp2->xkrFkType))
return firstisgreater;
else {
if (CW(xp1->xkrFABN) < CW(xp2->xkrFABN))
return firstisless;
else if (CW(xp1->xkrFABN) > CW(xp2->xkrFABN))
return firstisgreater;
else
return same;
}
}
}
PUBLIC compretval ROMlib_catcompare(void *firstp, void *secondp)
{
catkey *ckp1, *ckp2;
ckp1 = firstp;
ckp2 = secondp;
if (Cx(ckp1->ckrParID) < Cx(ckp2->ckrParID))
return firstisless;
if (Cx(ckp1->ckrParID) > Cx(ckp2->ckrParID))
return firstisgreater;
else
return RelString((StringPtr) ckp1->ckrCName, (StringPtr) ckp2->ckrCName,
FALSE, TRUE);
}
PUBLIC void ROMlib_makextntkey(xtntkey *keyp, forktype forkwanted, LONGINT flnum,
uint16 bno)
{
keyp->xkrKeyLen = 7;
keyp->xkrFkType = forkwanted;
keyp->xkrFNum = CL(flnum);
keyp->xkrFABN = CW(bno);
}
PUBLIC void ROMlib_makextntparam(btparam *btpb, HVCB *vcbp, forktype forkwanted,
LONGINT flnum, uint16 bno)
{
btpb->vcbp = vcbp;
ROMlib_makextntkey((xtntkey *) &btpb->tofind, forkwanted, flnum, bno);
btpb->fp = ROMlib_xtntcompare;
btpb->refnum = Cx(vcbp->vcbXTRef);
btpb->leafindex = -1;
}
PRIVATE xtntkey *fcbpbnotoxkeyp(filecontrolblock *fcbp, uint16 bno)
{
forktype forkwanted;
xtntkey *xkeyp;
btparam btparamblock;
OSErr err;
forkwanted = fcbp->fcbMdRByt & RESOURCEBIT ? resourcefork : datafork;
ROMlib_makextntparam(&btparamblock, MR(fcbp->fcbVPtr), forkwanted,
CL(fcbp->fcbFlNum), bno);
err = ROMlib_keyfind(&btparamblock);
#if 0
ROMlib_cleancache(btparamblock.vcbp);
#endif
xkeyp = (xtntkey *) btparamblock.foundp;
if (err != noErr || Cx(xkeyp->xkrFkType) != forkwanted ||
Cx(xkeyp->xkrFNum) != Cx(fcbp->fcbFlNum))
return 0;
return xkeyp;
}
PUBLIC LONGINT ROMlib_logtophys(filecontrolblock *fcbp, LONGINT absoffset,
LONGINT *nphyscontigp)
{
uint16 bno;
HVCB *vcbp;
LONGINT alblksiz, retblock;
xtntkey *xkeyp;
LONGINT skip;
LONGINT alinphys;
unsigned short nphysalcontig;
vcbp = (HVCB *) MR(fcbp->fcbVPtr);
alblksiz = Cx(vcbp->vcbAlBlkSiz);
bno = absoffset / alblksiz;
skip = absoffset % alblksiz;
retblock = xtntbnotophys(fcbp->fcbExtRec, bno, &nphysalcontig);
if (retblock == -1) {
xkeyp = fcbpbnotoxkeyp(fcbp, bno);
if (!xkeyp)
return -1;
retblock = xtntbnotophys((xtntdesc *) DATAPFROMKEY(xkeyp),
bno - CW(xkeyp->xkrFABN), &nphysalcontig);
if (retblock == -1)
return -1;
}
alinphys = alblksiz / PHYSBSIZE;
*nphyscontigp = alinphys * nphysalcontig - (skip / PHYSBSIZE);
return Cx(vcbp->vcbAlBlSt) * (LONGINT) PHYSBSIZE + retblock * alblksiz + skip;
}
PRIVATE OSErr pbtofcbp(ioParam *pb, filecontrolblock **fcbpp, accesstype rw)
{
OSErr retval;
*fcbpp = ROMlib_refnumtofcbp(Cx(pb->ioRefNum));
if (!*fcbpp)
retval = rfNumErr;
else {
if (rw == writing) {
retval = ROMlib_writefcbp(*fcbpp);
if (retval == noErr)
retval = ROMlib_writevcbp(MR((*fcbpp)->fcbVPtr));
} else
retval = noErr;
}
return retval;
}
PRIVATE void setbits(HVCB *vcbp, ULONGINT bno, ULONGINT ntoset, unsigned char lookfor)
{
unsigned char *cp, *ecp;
ULONGINT ebno;
INTEGER startbit, stopbit;
unsigned char mask, want;
ULONGINT first_map_block, last_map_block;
if (lookfor)
vcbp->vcbFreeBks = CW(CW(vcbp->vcbFreeBks) - (ntoset));
else
vcbp->vcbFreeBks = CW(CW(vcbp->vcbFreeBks) + (ntoset));
vcbp->vcbFlags |= CW(VCBDIRTY);
/* bno -= Cx(vcbp->vcbAlBlSt); not sure about this */
ebno = bno + ntoset;
cp = (unsigned char *) MR(vcbp->vcbMAdr) + bno / 8 + MADROFFSET;
ecp = (unsigned char *) MR(vcbp->vcbMAdr) + ebno / 8 + MADROFFSET;
startbit = bno % 8;
stopbit = ebno % 8;
if (cp == ecp) {
mask = (0xFF >> startbit) & (0xFF << (8 - stopbit));
if (lookfor)
*cp |= mask;
else
*cp &= ~mask;
} else {
if (startbit) {
mask = 0xFF >> startbit;
if (lookfor)
*cp++ |= mask;
else
*cp++ &= ~mask;
}
want = lookfor ? 0xFF : 0;
while (cp != ecp)
*cp++ = want;
if (stopbit) {
mask = 0xFF << (8 - stopbit);
if (lookfor)
*cp |= mask;
else
*cp &= ~mask;
}
}
first_map_block = bno / (PHYSBSIZE * 8);
last_map_block = (ebno - 1) / (PHYSBSIZE * 8);
ROMlib_transphysblk(&((VCBExtra *)vcbp)->u.hfs,
(Cx(vcbp->vcbVBMSt) + first_map_block) * (ULONGINT) PHYSBSIZE,
last_map_block - first_map_block + 1,
MR(vcbp->vcbMAdr) + MADROFFSET + first_map_block * PHYSBSIZE,
writing, (LONGINT *) 0);
vcbsync(vcbp);
}
PRIVATE ULONGINT countbits(HVCB *vcbp, ULONGINT bno, unsigned char lookfor)
{
unsigned char *cp, c;
unsigned char mask, want;
ULONGINT retval, max;
INTEGER bit;
/* assert(lookfor <= 1); */
/* bno -= Cx(vcbp->vcbAlBlSt); not sure about this */
retval = 0;
max = Cx(vcbp->vcbNmAlBlks) - bno;
cp = (unsigned char *) MR(vcbp->vcbMAdr) + bno / 8 + MADROFFSET;
#if 0
{
Size madrlen;
madrlen = GetPtrSize(Cx(vcbp->vcbMAdr));
madrlen = madrlen;
}
#endif
bit = bno % 8;
if (bit) {
c = *cp++;
mask = (unsigned char) ~0 >> bit;
want = lookfor ? mask : 0;
if ((c & mask) == want) {
retval += 8 - bit;
} else {
mask = 1 << (7 - bit);
if (lookfor)
for (; c & mask; mask >>= 1)
retval++;
else
for (; !(c & mask); mask >>= 1)
retval++;
return retval;
}
}
want = lookfor ? 0xFF : 0;
while (retval < max && *cp++ == want) {
retval += 8;
}
if (retval < max) {
c = cp[-1];
mask = 1 << 7;
if (lookfor)
for (; c & mask; mask >>= 1)
retval++;
else
for (; !(c & mask); mask >>= 1)
retval++;
}
return MIN(max, retval);
}
PRIVATE BOOLEAN fillextent(xtntdesc *xp, ULONGINT *nallocneededp, HVCB *vcbp,
uint16 *newabnp)
{
INTEGER nempty;
ULONGINT toextend;
ULONGINT needed, max, nfree, search;
xtntrec tmpxtnt;
xtntdesc *tmpxp;
BOOLEAN retval;
needed = *nallocneededp;
max = Cx(vcbp->vcbNmAlBlks);
for (nempty = 3; nempty > 0 && Cx(xp->blockcount); nempty--, xp++)
*newabnp += Cx(xp->blockcount);
if (nempty != 3) {
--xp;
toextend = countbits(vcbp, Cx(xp->blockstart) + Cx(xp->blockcount), 0);
if (toextend) {
toextend = MIN(toextend, needed);
needed -= toextend;
setbits(vcbp, Cx(xp->blockstart) + Cx(xp->blockcount), toextend, 1);
xp->blockcount = CW(CW(xp->blockcount) + (toextend));
}
++xp;
}
if (needed && nempty) {
tmpxtnt[0].blockcount = 0;
tmpxtnt[1].blockcount = 0;
tmpxtnt[2].blockcount = 0;
nfree = 0;
/*
* NOTE: the condition in the for loop might look strange. The point is it
* isn't worth counting the number of free blocks from a given point if
* even in the best case it couldn't be more than the number you already
* know about.
*/
for (search = countbits(vcbp, 0, 1) /*Cx(vcbp->vcbAlBlSt)*/; max - search > CW(tmpxtnt[2].blockcount);) {
nfree = countbits(vcbp, search, 0);
#if 0
if (nfree == 0)
warning_unexpected ("nfree == 0");
#endif
if (nfree >= needed) {
tmpxtnt[0].blockcount = CW(nfree);
tmpxtnt[0].blockstart = CW(search);
break;
}
if (nfree > CW(tmpxtnt[1].blockcount)) {
if (nfree > CW(tmpxtnt[0].blockcount)) {
tmpxtnt[2].blockcount = tmpxtnt[1].blockcount;
tmpxtnt[2].blockstart = tmpxtnt[1].blockstart;
tmpxtnt[1].blockcount = tmpxtnt[0].blockcount;
tmpxtnt[1].blockstart = tmpxtnt[0].blockstart;
tmpxtnt[0].blockcount = CW(nfree);
tmpxtnt[0].blockstart = CW(search);
} else {
tmpxtnt[2].blockcount = tmpxtnt[1].blockcount;
tmpxtnt[2].blockstart = tmpxtnt[1].blockstart;
tmpxtnt[1].blockcount = CW(nfree);
tmpxtnt[1].blockstart = CW(search);
}
} else if (nfree > tmpxtnt[2].blockcount) {
tmpxtnt[2].blockcount = CW(nfree);
tmpxtnt[2].blockstart = CW(search);
}
search += nfree;
search += countbits(vcbp, search, 1);
}
tmpxp = tmpxtnt;
while (needed > 0 && --nempty >= 0 && tmpxp->blockcount) {
xp->blockstart = tmpxp->blockstart;
xp->blockcount = CW(MIN(CW(tmpxp->blockcount), needed));
#if 1
if (xp->blockcount == 0)
warning_unexpected ("blockcount = 0");
#endif
needed -= CW(xp->blockcount);
setbits(vcbp, CW(xp->blockstart), CW(xp->blockcount), 1);
++xp;
++tmpxp;
}
}
*newabnp += *nallocneededp - needed;
retval = needed < (ULONGINT) *nallocneededp;
*nallocneededp = needed;
return retval;
}
PRIVATE void smokexpvcbp(ULONGINT tosmoke, xtntdesc *xp, HVCB *vcbp)
{
if (tosmoke <= CW(xp[2].blockcount)) {
xp[2].blockcount = CW(CW(xp[2].blockcount) - (tosmoke));
setbits(vcbp, CW(xp[2].blockstart) + CW(xp[2].blockcount), tosmoke, 0);
} else {
setbits(vcbp, CW(xp[2].blockstart), CW(xp[2].blockcount), 0);
tosmoke -= CW(xp[2].blockcount);
xp[2].blockcount = CWC(0);
if (tosmoke <= CW(xp[1].blockcount)) {
xp[1].blockcount = CW(CW(xp[1].blockcount) - tosmoke);
setbits(vcbp, CW(xp[1].blockstart) + CW(xp[1].blockcount),
tosmoke, 0);
} else {
setbits(vcbp, CW(xp[1].blockstart), CW(xp[1].blockcount), 0);
tosmoke -= CW(xp[1].blockcount);
xp[1].blockcount = CWC(0);
xp[0].blockcount = CW(CW(xp[0].blockcount) - tosmoke);
setbits(vcbp, CW(xp[0].blockstart) + CW(xp[0].blockcount), tosmoke, 0);
}
}
}
PUBLIC OSErr ROMlib_allochelper(ioParam *pb, BOOLEAN async, alloctype alloc,
BOOLEAN writefcbp)
{
filecontrolblock *fcbp;
OSErr err, err1;
LONGINT neweof, totallength, newneweof;
uint16 clumpsize, newabn;
HVCB *vcbp;
LONGINT tosmoke;
ULONGINT nallocneeded, oldnallocneeded;
BOOLEAN needtoshrink;
xtntdesc *xp;
xtntkey *xtkeyp;
xtntrec saverec;
Byte savetype;
btparam btparamrec;
err = pbtofcbp(pb, &fcbp, writing);
if (err != noErr)
{
fs_err_hook (err);
/*-->*/ PBRETURN(pb, err);
}
switch (alloc) {
case seteof:
neweof = (ULONGINT) Cx(pb->ioMisc);
break;
case allocany:
case alloccontig:
neweof = Cx(fcbp->fcbPLen) + Cx(pb->ioReqCount);
break;
default:
warning_unexpected ("unknown allocator1");
err = fsDSIntErr;
fs_err_hook (err);
PBRETURN(pb, err);
}
#if 0
/*
* Bill showed that the Mac *doesn't* do this
*/
if ((LONGINT) neweof < 0) /* NOTE: This is a guess that Mac stuff does */
neweof = 0; /* this */
#endif
clumpsize = Cx(fcbp->fcbClmpSize);
vcbp = (HVCB *) MR(fcbp->fcbVPtr);
if (!clumpsize)
clumpsize = Cx(vcbp->vcbClpSiz);
#if 0
clumpsize = Cx(vcbp->vcbAlBlkSiz); /* i.e. ignore clumpsize; that's what
the Mac really does */
#endif
/* with Jaz Drives, clumpsize can *still* be zero! */
if (clumpsize == 0)
{
warning_unexpected ("clump size still 0");
clumpsize = PHYSBSIZE;
}
newneweof = (neweof + clumpsize - 1) / clumpsize * clumpsize;
newneweof = (newneweof + Cx(vcbp->vcbAlBlkSiz) - 1) / Cx(vcbp->vcbAlBlkSiz)
* Cx(vcbp->vcbAlBlkSiz);
if (newneweof >= neweof)
neweof = newneweof;
else /* overflow */
neweof = ((unsigned long) (long) -1) / clumpsize * clumpsize;
if (neweof < Cx(fcbp->fcbPLen)) {
needtoshrink = TRUE;
nallocneeded = (Cx(fcbp->fcbPLen) - neweof) / Cx(vcbp->vcbAlBlkSiz);
} else {
needtoshrink = FALSE;
nallocneeded = (neweof - Cx(fcbp->fcbPLen)) / Cx(vcbp->vcbAlBlkSiz);
}
xp = fcbp->fcbExtRec;
totallength = Cx(vcbp->vcbAlBlkSiz) *
(CW(xp[0].blockcount) + CW(xp[1].blockcount) + CW(xp[2].blockcount));
if (needtoshrink) {
if (neweof < totallength) {
tosmoke = (totallength - neweof) / Cx(vcbp->vcbAlBlkSiz);
smokexpvcbp(tosmoke, xp, vcbp);
if (writefcbp)
fcbp->fcbMdRByt |= DIRTYBIT;
}
if (Cx(fcbp->fcbPLen) > totallength) {
newabn = MAX(neweof, totallength) / Cx(vcbp->vcbAlBlkSiz);
if (!(xtkeyp = fcbpbnotoxkeyp(fcbp, newabn))) {
neweof = Cx(fcbp->fcbPLen);
warning_unexpected ("couldn't translate fcbp, newabn 1");
err = fsDSIntErr;
goto done;
}
xp = (xtntdesc *) DATAPFROMKEY(xtkeyp);
totallength = Cx(vcbp->vcbAlBlkSiz) *
(CW(xp[0].blockcount) + CW(xp[1].blockcount) +
CW(xp[2].blockcount));
tosmoke = CW(xtkeyp->xkrFABN) * Cx(vcbp->vcbAlBlkSiz) + totallength
- neweof;
savetype = Cx(xtkeyp->xkrFkType);
if (tosmoke < totallength) {
gui_assert(xtkeyp && Cx(xtkeyp->xkrFNum) == Cx(fcbp->fcbFlNum) &&
Cx(xtkeyp->xkrFkType) == savetype);
smokexpvcbp(tosmoke, xp, vcbp);
ROMlib_dirtyleaf((anykey *)xtkeyp, vcbp);
err = ROMlib_btnext((anykey **) &xtkeyp, (anykey *)xtkeyp, vcbp);
if (err != noErr)
goto done;
}
if (xtkeyp && Cx(xtkeyp->xkrFNum) == Cx(fcbp->fcbFlNum) &&
Cx(xtkeyp->xkrFkType) == savetype) {
memmove(saverec, DATAPFROMKEY(xtkeyp),
(LONGINT) sizeof(saverec));
ROMlib_makextntparam(&btparamrec, vcbp, 0, 0, 0);
btparamrec.tofind = *(anykey *) xtkeyp;
btparamrec.leafindex = -1;
btparamrec.success = TRUE;
btparamrec.foundp = (anykey *) xtkeyp;
} else
btparamrec.success = FALSE;
while (btparamrec.success) {
xtkeyp = (xtntkey *) btparamrec.foundp;
gui_assert(xtkeyp && Cx(xtkeyp->xkrFNum) == Cx(fcbp->fcbFlNum) &&
Cx(xtkeyp->xkrFkType) == savetype);
xp = (xtntdesc *) DATAPFROMKEY(btparamrec.foundp);
setbits(vcbp, CW(xp[0].blockstart), CW(xp[0].blockcount), 0);
setbits(vcbp, CW(xp[1].blockstart), CW(xp[1].blockcount), 0);
setbits(vcbp, CW(xp[2].blockstart), CW(xp[2].blockcount), 0);
newabn = CW(btparamrec.tofind.xtntk.xkrFABN) +
CW(xp[0].blockcount) + CW(xp[1].blockcount) +
CW(xp[2].blockcount);
err = ROMlib_btdelete(&btparamrec);
if (err != noErr)
goto done;
btparamrec.tofind.xtntk.xkrFABN = CW(newabn);
err = ROMlib_keyfind(&btparamrec);
if (err != noErr)
goto done;
}
}
} else if (nallocneeded > 0) {
if ((nallocneeded > (ULONGINT) Cx(vcbp->vcbFreeBks))) {
if ((alloc == seteof || alloc == alloccontig)) {
neweof = Cx(fcbp->fcbPLen);
err = dskFulErr;
/*-->*/ goto done;
}
}
if (Cx(fcbp->fcbPLen) == totallength) { /* possibly some room in this one */
newabn = 0;
if (fillextent(xp, &nallocneeded, vcbp, &newabn) && writefcbp)
fcbp->fcbMdRByt |= DIRTYBIT;
} else {
newabn = Cx(fcbp->fcbPLen) / Cx(vcbp->vcbAlBlkSiz);
if (!(xtkeyp = fcbpbnotoxkeyp(fcbp, newabn))) {
neweof = Cx(fcbp->fcbPLen);
warning_unexpected ("couldn't translate fcbp, newabn 2");
err = fsDSIntErr;
goto done;
}
xp = (xtntdesc *) DATAPFROMKEY(xtkeyp);
newabn = CW(xtkeyp->xkrFABN);
if (fillextent(xp, &nallocneeded, vcbp, &newabn))
ROMlib_dirtyleaf((anykey *)xtkeyp, vcbp);
}
while (nallocneeded > 0) {
xtkeyp = ROMlib_newextentrecord(fcbp, newabn);
if (!xtkeyp) {
warning_unexpected ("newextent failed");
err = fsDSIntErr;
neweof = newabn * Cx(vcbp->vcbAlBlkSiz);
/*-->*/ goto done;
}
xp = (xtntdesc *) DATAPFROMKEY(xtkeyp);
oldnallocneeded = nallocneeded;
if (fillextent(xp, &nallocneeded, vcbp, &newabn))
ROMlib_dirtyleaf((anykey *)xtkeyp, vcbp);
if (nallocneeded == oldnallocneeded) {
neweof = newabn * Cx(vcbp->vcbAlBlkSiz);
err = dskFulErr;
/*-->*/ goto done;
}
}
}
done:
if (writefcbp && (needtoshrink || nallocneeded > 0)) { /* cleancache must NOT be called if we are trashing */
err1 = ROMlib_cleancache(vcbp); /* blocks before we delete a file */
if (err == noErr)
err1 = ROMlib_flushvcbp(vcbp);
} else
err1 = noErr;
switch (alloc) {
case seteof:
if (err == noErr)
fcbp->fcbEOF = (ULONGINT) pb->ioMisc;
break;
case allocany:
case alloccontig:
pb->ioActCount = CL(neweof - Cx(fcbp->fcbPLen));
break;
default:
warning_unexpected ("unknown allocator2");
err = fsDSIntErr;
fs_err_hook (err);
PBRETURN(pb, err);
}
fcbp->fcbPLen = CL(neweof);
fcbp->fcbMdRByt |= 0x80;
if (err == noErr)
err = err1;
fs_err_hook (err);
PBRETURN(pb, err);
}
PUBLIC OSErr hfsPBSetEOF(ParmBlkPtr pb, BOOLEAN async)
{
OSErr err;
err = ROMlib_allochelper((ioParam *) pb, async, seteof, TRUE);
fs_err_hook (err);
return err;
}
PUBLIC OSErr hfsPBAllocate(ParmBlkPtr pb, BOOLEAN async)
{
OSErr err;
err = ROMlib_allochelper((ioParam *) pb, async, allocany, TRUE);
fs_err_hook (err);
return err;
}
PUBLIC OSErr hfsPBAllocContig(ParmBlkPtr pb, BOOLEAN async)
{
OSErr err;
err = ROMlib_allochelper((ioParam *) pb, async, alloccontig, TRUE);
fs_err_hook (err);
return err;
}
#define RETURN(x) do { pb->ioResult = CW(x); goto DONE; } while (0)
PRIVATE OSErr PBReadWrite(ioParam *pb, BOOLEAN async, accesstype rw)
{
filecontrolblock *fcbp;
LONGINT absoffset, totransfer, neweot, templ, physblock, actl;
OSErr err;
OSErr newerr;
LONGINT ntoskip, ntocopy, nphyscontig, nblockstogo, thisrun;
#if 0
LONGINT i, actl2;
#endif
char tbuf[PHYSBSIZE + sizeof(LONGINT)]; /* goes away eventually */
char *tempbuf;
Ptr bufp;
HVCB *vcbp;
INTEGER ntoslide;
char save0, save1, save2;
tempbuf = (char *) (((long)tbuf+3)/ 4 * 4);
pb->ioResult = noErr;
pb->ioActCount = 0;
totransfer = Cx(pb->ioReqCount);
vcbp = 0;
newerr = pbtofcbp(pb, &fcbp, rw);
if (newerr != noErr)
{
fs_err_hook (newerr);
/*-->*/ RETURN(newerr);
}
vcbp = MR(fcbp->fcbVPtr);
absoffset = pbabsoffset(pb, fcbp);
if (absoffset < 0)
{
err = posErr;
fs_err_hook (err);
RETURN(err);
}
pb->ioPosOffset = CL(absoffset);
if (totransfer < 0)
{
err = paramErr;
fs_err_hook (err);
RETURN(err);
}
neweot = absoffset + totransfer;
if (neweot > Cx(fcbp->fcbEOF)) {
if (rw == reading) {
totransfer = Cx(fcbp->fcbEOF) - absoffset;
pb->ioResult = CW(eofErr);
} else {
templ = (LONGINT) Cx(pb->ioMisc);
#if defined(MAC)
pb->ioMisc = CL((Ptr) neweot);
#else /* !defined(MAC) */
pb->ioMisc = CL((LONGINT) neweot);
#endif /* !defined(MAC) */
PBSetEOF((ParmBlkPtr) pb, FALSE);
if (pb->ioResult != CWC(noErr))
totransfer = Cx(fcbp->fcbPLen) - absoffset;
}
}
ntoskip = absoffset % PHYSBSIZE;
nphyscontig = 0;
bufp = MR(pb->ioBuffer);
#if !defined (LETGCCWAIL)
physblock = 0;
#endif /* LETGCCWAIL */
if (ntoskip) {
absoffset -= ntoskip;
physblock = ROMlib_logtophys(fcbp, absoffset, &nphyscontig);
if (nphyscontig < 1) {
fprintf(stderr, "1 absoffset = %d, nphyscontig = %d\n",
(LONGINT) absoffset, (LONGINT) nphyscontig);
err = ioErr;
fs_err_hook (err);
RETURN(err);
}
newerr = ROMlib_transphysblk (&((VCBExtra *)vcbp)->u.hfs, physblock, 1,
(Ptr) tempbuf,
reading, (LONGINT *) 0);
if (newerr != noErr)
{
fs_err_hook (newerr);
RETURN(newerr);
}
ntocopy = MIN(totransfer, PHYSBSIZE - ntoskip);
if (rw == reading)
BlockMove((Ptr) tempbuf + ntoskip, (Ptr) bufp, (Size) ntocopy);
else {
memmove((char *) tempbuf + ntoskip, bufp, (LONGINT) ntocopy);
newerr = ROMlib_transphysblk (&((VCBExtra *)vcbp)->u.hfs, physblock, 1,
(Ptr) tempbuf, writing,
(LONGINT *) 0);
if (newerr != noErr)
{
fs_err_hook (newerr);
RETURN(newerr);
}
}
pb->ioPosOffset = CL(CL(pb->ioPosOffset) + (ntocopy));
pb->ioActCount = CL(CL(pb->ioActCount) + (ntocopy));
totransfer -= ntocopy;
absoffset += PHYSBSIZE;
physblock += PHYSBSIZE;
bufp += ntocopy;
--nphyscontig;
}
if (totransfer >= PHYSBSIZE) {
nblockstogo = totransfer / PHYSBSIZE;
while (nblockstogo > 0) {
if (nphyscontig == 0) {
physblock = ROMlib_logtophys(fcbp, absoffset, &nphyscontig);
if (nphyscontig < 1) {
fprintf(stderr, "2 absoffset = %d, nphyscontig = %d\n",
(LONGINT) absoffset, (LONGINT) nphyscontig);
err = ioErr;
fs_err_hook (err);
RETURN(err);
}
}
thisrun = MIN(nphyscontig, nblockstogo);
#if 0
if (((LONGINT)bufp & 3) == 0) {
newerr = ROMlib_transphysblk (&vcbp->hfs, physblock, thisrun,
bufp, rw, &actl);
actl = CL(actl);
if (rw == reading)
ROMlib_destroy_blocks((syn68k_addr_t) US_TO_SYN68K(bufp), actl, TRUE);
} else {
/* TODO: Hubris attenuation: SPEED THIS UP FOR EXCEL 4.x INSTALLERS!!!! */
newerr = noErr;
actl = 0;
for (i = 0; newerr == noErr && i < thisrun; ++i) {
if (rw == writing)
memmove(tempbuf, bufp + (LONGINT) PHYSBSIZE * i,
PHYSBSIZE);
newerr = ROMlib_transphysblk (&vcbp->hfs,
physblock +
(LONGINT) PHYSBSIZE * i,
1, (Ptr) tempbuf, rw,
&actl2);
actl2 = CL(actl2);
if (rw == reading)
BlockMove((Ptr) tempbuf,
(Ptr) bufp + (LONGINT) PHYSBSIZE * i, (Size) actl2);
actl += actl2;
}
}
#else
ntoslide = (long) bufp & 3;
bufp -= ntoslide;
save0 = bufp[0];
save1 = bufp[1];
save2 = bufp[2];
if (ntoslide && rw == writing)
BlockMove(bufp + ntoslide, bufp, thisrun * PHYSBSIZE);
newerr = ROMlib_transphysblk (&((VCBExtra *) vcbp)->u.hfs, physblock, thisrun,
bufp,
rw, &actl);
actl = CL(actl);
if (ntoslide) {
BlockMove(bufp, bufp + ntoslide, actl);
switch (ntoslide) {
case 3:
bufp[2] = save2;
/* FALL THROUGH */
case 2:
bufp[1] = save1;
/* FALL THROUGH */
case 1:
bufp[0] = save0;
/* FALL THROUGH */
}
}
bufp += ntoslide;
if (rw == reading)
ROMlib_destroy_blocks((syn68k_addr_t)
(long) US_TO_SYN68K(bufp), actl, TRUE);
#endif
pb->ioPosOffset = CL(CL(pb->ioPosOffset) + (actl));
pb->ioActCount = CL(CL(pb->ioActCount) + (actl));
if (newerr != noErr)
{
fs_err_hook (newerr);
RETURN(newerr);
}
bufp += thisrun * (LONGINT) PHYSBSIZE;
absoffset += thisrun * (LONGINT) PHYSBSIZE;
physblock += thisrun * (LONGINT) PHYSBSIZE;
totransfer -= thisrun * (LONGINT) PHYSBSIZE;
nblockstogo -= thisrun;
nphyscontig -= thisrun;
}
}
if (totransfer > 0) {
if (nphyscontig == 0) {
physblock = ROMlib_logtophys(fcbp, absoffset, &nphyscontig);
if (nphyscontig < 1) {
fprintf(stderr, "2 absoffset = %d, nphyscontig = %d\n",
(LONGINT) absoffset, (LONGINT) nphyscontig);
err = ioErr;
fs_err_hook (err);
RETURN(err);
}
}
newerr = ROMlib_transphysblk (&((VCBExtra *)vcbp)->u.hfs, physblock, 1,
(Ptr) tempbuf,
reading, (LONGINT *) 0);
if (newerr != noErr)
{
fs_err_hook (newerr);
RETURN(newerr);
}
if (rw == reading)
BlockMove((Ptr) tempbuf, (Ptr) bufp, (Size) totransfer);
else {
memmove((char *) tempbuf, bufp, (LONGINT) totransfer);
newerr = ROMlib_transphysblk (&((VCBExtra *)vcbp)->u.hfs, physblock, 1,
(Ptr) tempbuf, writing,
(LONGINT *) 0);
if (newerr != noErr)
{
fs_err_hook (newerr);
RETURN(newerr);
}
}
pb->ioPosOffset = CL(CL(pb->ioPosOffset) + (totransfer));
pb->ioActCount = CL(CL(pb->ioActCount) + (totransfer));
}
fcbp->fcbCrPs = pb->ioPosOffset;
DONE:
if (vcbp)
newerr = ROMlib_cleancache(vcbp);
else
newerr = noErr;
if (pb->ioResult == noErr)
pb->ioResult = CW(newerr);
fs_err_hook (CW (pb->ioResult));
return CW(pb->ioResult);
}
#undef RETURN
PUBLIC OSErr hfsPBRead(ParmBlkPtr pb, BOOLEAN async)
{
OSErr err;
err = PBReadWrite((ioParam *) pb, async, reading);
fs_err_hook (err);
return err;
}
PUBLIC OSErr hfsPBWrite(ParmBlkPtr pb, BOOLEAN async)
{
OSErr err;
err = PBReadWrite((ioParam *) pb, async, writing);
fs_err_hook (err);
return err;
}
PRIVATE OSErr dirtyfcbp(filecontrolblock *fcbp)
{
ULONGINT catpos;
short refnum;
HVCB *vcbp;
cacheentry *cachep;
catkey key;
unsigned char *namep;
anykey *retkeyp;
filerec *frp;
OSErr err;
INTEGER dumint;
if (fcbp->fcbMdRByt & DIRTYBIT) {
refnum = (char *) fcbp - (char *) MR(FCBSPtr);
vcbp = MR(fcbp->fcbVPtr);
if ((catpos = Cx(fcbp->fcbCatPos))) {
err = ROMlib_getcache(&cachep, CW(MR(fcbp->fcbVPtr)->vcbCTRef),
catpos, 0);
if (err != noErr)
{
fs_err_hook (err);
return err;
}
namep = fcbp->fcbCName;
ROMlib_makecatkey(&key, Cx(fcbp->fcbDirID), namep[0], (Ptr) namep+1);
if (!ROMlib_searchnode((btnode *)cachep->buf, (void *)&key, ROMlib_catcompare,
&retkeyp, &dumint)) {
btparam btparamrec;
btparamrec.vcbp = MR (fcbp->fcbVPtr);
btparamrec.tofind.catk = key;
btparamrec.fp = ROMlib_catcompare;
btparamrec.refnum = CW (MR (fcbp->fcbVPtr)->vcbCTRef);
err = ROMlib_keyfind (&btparamrec);
if (err == noErr)
{
if (btparamrec.success)
{
retkeyp = btparamrec.foundp;
cachep = btparamrec.trail[btparamrec.leafindex].cachep;
}
else
err = fsDSIntErr;
}
if (err)
{
warning_unexpected ("err = %d", err);
return err;
}
}
frp = (filerec *) DATAPFROMKEY(retkeyp);
if (fcbp->fcbMdRByt & FLOCKEDBIT)
frp->filFlags |= FSOFTLOCKBIT;
else
frp->filFlags &= ~FSOFTLOCKBIT;
#if 0
frp->filTyp = fcbp->fcbTypByt;
frp->filStBlk = fcbp->fcbSBlk;
frp->filClpSize = fcbp->fcbClmpSize;
/* When this line was present, Excel wouldn't recognize its own files */
frp->filUsrWds.fdType = fcbp->fcbFType;
#endif
if (fcbp->fcbMdRByt & RESOURCEBIT) {
frp->filRLgLen = fcbp->fcbEOF;
frp->filRPyLen = fcbp->fcbPLen;
memmove(frp->filRExtRec, fcbp->fcbExtRec,
(LONGINT) sizeof(frp->filRExtRec));
} else {
frp->filLgLen = fcbp->fcbEOF;
frp->filPyLen = fcbp->fcbPLen;
memmove(frp->filExtRec, fcbp->fcbExtRec,
(LONGINT) sizeof(frp->filExtRec));
}
cachep->flags |= CACHEDIRTY;
} else if (refnum == Cx(vcbp->vcbXTRef) || refnum == Cx(vcbp->vcbCTRef)) {
err = noErr;
vcbp->vcbFlags |= CW(VCBDIRTY);
} else {
warning_unexpected ("no catpos (nor are we XTRef or CTRef)");
err = fsDSIntErr;
}
if (err == noErr)
fcbp->fcbMdRByt &= ~DIRTYBIT;
fs_err_hook (err);
return err;
} else
return noErr;
}
PUBLIC OSErr hfsPBFlushFile(ParmBlkPtr pb, BOOLEAN async)
{
filecontrolblock *fcbp;
OSErr err;
fcbp = ROMlib_refnumtofcbp(Cx(pb->ioParam.ioRefNum));
if (!fcbp)
err = rfNumErr;
else
err = dirtyfcbp(fcbp);
if (err == noErr)
err = ROMlib_flushvcbp (MR(fcbp->fcbVPtr));
fs_err_hook (err);
PBRETURN((ioParam *) pb, err);
}
PUBLIC OSErr hfsPBClose(ParmBlkPtr pb, BOOLEAN async)
{
filecontrolblock *fcbp;
OSErr err;
fcbp = ROMlib_refnumtofcbp(Cx(pb->ioParam.ioRefNum));
if (!fcbp)
err = rfNumErr;
else
{
err = PBFlushFile(pb, async);
fcbp->fcbFlNum = 0;
}
fs_err_hook (err);
PBRETURN((ioParam *) pb, err);
}
PUBLIC OSErr ROMlib_makecatkey(catkey *keyp, LONGINT dirid, INTEGER namelen,
Ptr namep)
{
OSErr retval;
if ((unsigned) namelen > 31)
{
namelen = 31;
retval = bdNamErr;
} else
retval = noErr;
keyp->ckrKeyLen = namelen + 1 + sizeof(LONGINT) + 1;
keyp->ckrResrv1 = 0;
keyp->ckrParID = CL(dirid);
keyp->ckrCName[0] = namelen;
memmove(keyp->ckrCName+1, namep, (LONGINT) namelen);
fs_err_hook (retval);
return retval;
}
/*
* TODO -- FIXME -- NOTE:
*
* On the Mac, if you do a PBGetCatInfo on Cirrus 80:Utilities::, you will
* get info about Cirrus 80, *but* the parent directory will be ... that of
* Utilities. Findentry doesn't return that info, since we pull it out of
* the catalog key instead.
*/
PRIVATE OSErr findentry(LONGINT dirid, StringPtr name, btparam *btpb,
filekind *kindp, BOOLEAN ignorename)
{
filerec *retval;
INTEGER namelen;
unsigned char *namep, *colonp, *endp;
void *recp;
short rectype;
OSErr err;
INTEGER coloncoloncount;
retval = 0;
if (name == 0)
ignorename = TRUE;
if (ignorename) {
namelen = 0;
namep = (StringPtr) "";
} else {
namelen = name[0];
namep = name+1;
}
if (namelen && namep[0] == ':') { /* advance over leading ':' */
--namelen;
++namep;
}
if (namep[namelen-1] == ':') { /* trailing colon means we want */
--namelen; /* only a directory */
*kindp &= directory;
}
if (namelen <= 0 && !ignorename && (*kindp & (directory|thread) ) == 0)
{
err = bdNamErr;
fs_err_hook (err);
/*-->*/ return err;
}
if (namelen < 0)
{
err = bdNamErr;
fs_err_hook (err);
/*-->*/ return err;
}
gui_assert(namelen >= 0);
coloncoloncount = 0;
for (;;) {
err = ROMlib_cleancache(btpb->vcbp);
if (err != noErr)
{
fs_err_hook (err);
/*-->*/ return err;
}
colonp = (unsigned char *) ROMlib_indexn((char *) namep, ':', namelen);
if (colonp)
endp = colonp;
else
endp = namep + namelen;
err = ROMlib_makecatparam(btpb, btpb->vcbp, dirid, endp-namep, (Ptr) namep);
if (err == noErr)
err = ROMlib_keyfind(btpb);
if (err != noErr)
{
fs_err_hook (err);
/*-->*/ return err;
}
if (!btpb->success) {
#if 0
/*-->*/ err = colonp ? dirNFErr : fnfErr;
#else
/*-->*/ err = ROMlib_errortype(btpb);
#endif
fs_err_hook (err);
return err;
}
recp = DATAPFROMKEY(btpb->foundp);
rectype = *(unsigned char *)recp;
if (colonp) { /* expect a directory */
switch (rectype) {
case DIRTYPE:
dirid = CL(((directoryrec *)recp)->dirDirID);
break;
case THREADTYPE:
if (((catkey *) &btpb->tofind)->ckrCName[0]) {
warning_unexpected ("thread with name");
err = fsDSIntErr;
fs_err_hook (err);
/*-->*/ return err;
}
dirid = CL(((threadrec *)recp)->thdParID);
break;
default:
warning_unexpected ("unknown rectype1 in findentry");
err = fsDSIntErr;
fs_err_hook (err);
/*-->*/ return err;
}
namelen -= ((catkey *) &btpb->tofind)->ckrCName[0]+1;
namep += ((catkey *) &btpb->tofind)->ckrCName[0]+1;
} else { /* expect a regular file */
switch (rectype) {
case FILETYPE:
if (!(*kindp & regular))
{
err = bdNamErr;
fs_err_hook (err);
/*-->*/ return err;
}
*kindp = regular;
break;
case DIRTYPE:
if (!(*kindp & directory))
{
err = bdNamErr;
fs_err_hook (err);
/*-->*/ return err;
}
*kindp = directory;
break;
case THREADTYPE:
if (*kindp & thread)
*kindp = thread; /* we're done now */
else if ((ignorename || endp == namep) &&
(*kindp & directory)) {
dirid = CL(((threadrec *)recp)->thdParID);
if (ignorename || coloncoloncount == 1) {
namep = ((threadrec *)recp)->thdCName+1;
namelen = ((threadrec *)recp)->thdCName[0];
} else
++coloncoloncount;
/*-->*/ continue; /* avoid return below */
} else
{
err = dirNFErr;
warning_trace_info ("*kindp = 0x%x, ignorename = %d, "
"endp = %p, namep = %p",
*kindp, ignorename, endp, namep);
fs_err_hook (err);
/*-->*/ return err;
}
break;
default:
warning_unexpected ("unknown rectype2 in findentry");
err = fsDSIntErr;
fs_err_hook (err);
/*-->*/ return err;
}
/*-->*/ return noErr;
}
}
}
/*
* looking for matches of the form "xxx:yyy:zzz:" in "xxx"
*/
/* #warning Use of memcmp is WRONG here. All filesystem name matching code */
/* #warning should do the right things with case and diacritical marks */
PRIVATE BOOLEAN dir_prefixes_volume(StringPtr dirnamep, StringPtr volnamep)
{
if (!dirnamep) /* don't dereference 0 if it's passed in */
return FALSE;
if (dirnamep[0] <= volnamep[0]) /* must be larger, for ":" if nothing else */
/*-->*/return FALSE;
if (memcmp(dirnamep+1, volnamep+1, volnamep[0]) != 0)
/*-->*/return FALSE;
return dirnamep[volnamep[0]+1] == ':';
}
PUBLIC OSErr ROMlib_findvcbandfile(ioParam *pb, LONGINT dirid, btparam *btpb,
filekind *kindp, BOOLEAN ignorename)
{
OSErr err;
int badness;
LONGINT dir;
StringPtr savep;
badness = 0;
dir = 0;
if (pb->ioNamePtr)
{
StringPtr namep;
namep = MR (pb->ioNamePtr);
if (namep[0] == 1 && namep[1] == ':')
ignorename = TRUE;
}
do
{
err = noErr;
savep = pb->ioNamePtr;
if (ignorename)
pb->ioNamePtr = 0;
btpb->vcbp = ROMlib_findvcb(CW(pb->ioVRefNum), MR(pb->ioNamePtr), &dir,
TRUE);
pb->ioNamePtr = savep;
if (dir == 0)
{
dir = dirid;
badness = 1;
}
if (!btpb->vcbp)
{
err = nsvErr;
/*-->*/ break;
}
else
{
Str255 tempstr;
StringPtr to_look_for_p;
if (!ignorename
&& dir_prefixes_volume(MR(pb->ioNamePtr), btpb->vcbp->vcbVN))
dirid = 1;
else
ROMlib_adjustdirid(&dirid, btpb->vcbp, CW(pb->ioVRefNum));
if (!ignorename && dirid == 2 && pb->ioNamePtr
&& MR(pb->ioNamePtr)[0] == 0 && (*kindp & directory))
{
dirid = 1;
str255assign(tempstr, btpb->vcbp->vcbVN);
++tempstr[0];
tempstr[tempstr[0]] = ':';
to_look_for_p = tempstr;
}
else
to_look_for_p = MR(pb->ioNamePtr);
err = findentry(dirid, to_look_for_p, btpb, kindp, ignorename);
if (err)
{
++badness;
dirid = dir;
}
else
badness = 0;
}
}
while (badness == 1);
fs_err_hook (err);
return err;
}
/*
* ROMlib_alreadyopen checks to see whether a given file is already open and if
* so whether that causes a conflict (the conflicting refnum is filled in).
*/
PUBLIC OSErr ROMlib_alreadyopen(HVCB *vcbp, LONGINT flnum, SignedByte *permp,
INTEGER *refnump, busyconcern_t busy)
{
short length;
filecontrolblock *fcbp, *efcbp;
SignedByte temp;
INTEGER tempshort;
Byte busybit;
OSErr err;
if (!permp) {
permp = &temp;
temp = fsWrPerm;
}
if (!refnump)
refnump = &tempshort;
if (*permp == fsRdPerm)
return noErr;
busybit = busy == resourcebusy ? RESOURCEBIT : 0;
length = CW(*(short *)MR(FCBSPtr));
fcbp = (filecontrolblock *) ((short *)MR(FCBSPtr)+1);
efcbp = (filecontrolblock *) ((char *)MR(FCBSPtr) + length);
for (;fcbp < efcbp; fcbp = (filecontrolblock *) ((char *)fcbp + CW(FSFCBLen)))
if (MR(fcbp->fcbVPtr) == vcbp && CL(fcbp->fcbFlNum) == flnum &&
(busy == eitherbusy
|| (fcbp->fcbMdRByt & RESOURCEBIT) == busybit) &&
((fcbp->fcbMdRByt & WRITEBIT) || permp == &temp))
switch (*permp) {
case fsCurPerm:
if (!(fcbp->fcbMdRByt & SHAREDBIT))
{
*permp = fsRdPerm;
return noErr;
}
break;
case fsWrPerm:
case fsRdWrPerm:
*refnump = CW((char *) fcbp - (char *) MR(FCBSPtr));
err = opWrErr;
fs_err_hook (err);
return err;
break;
case fsRdWrShPerm:
if (!(fcbp->fcbMdRByt & SHAREDBIT)) {
*refnump = CW((char *) fcbp - (char *) MR(FCBSPtr));
err = opWrErr;
fs_err_hook (err);
return err;
}
break;
}
return noErr;
}
PRIVATE OSErr PBOpenHelper(ioParam *pb, forktype ft, LONGINT dirid, BOOLEAN async)
{
filecontrolblock *fcbp;
OSErr err;
SignedByte permssn;
cacheentry *cachep;
btparam btparamrec;
filekind kind;
filerec *frp;
catkey *catkeyp;
pb->ioRefNum = CWC(0); /* in case some program ignores a failure */
kind = regular;
err = ROMlib_findvcbandfile(pb, dirid, &btparamrec, &kind, FALSE);
if (err != noErr)
{
fs_err_hook (err);
PBRETURN(pb, err);
}
err = ROMlib_cleancache(btparamrec.vcbp);
if (err != noErr)
{
fs_err_hook (err);
PBRETURN(pb, err);
}
permssn = pb->ioPermssn;
frp = (filerec *) DATAPFROMKEY(btparamrec.foundp);
err = ROMlib_alreadyopen(btparamrec.vcbp, CL(frp->filFlNum), &permssn,
&pb->ioRefNum, ft == resourcefork ? resourcebusy : databusy );
if (err != noErr)
{
fs_err_hook (err);
PBRETURN(pb, err);
}
fcbp = ROMlib_getfreefcbp();
if (!fcbp)
{
err = tmfoErr;
fs_err_hook (err);
/*-->*/ PBRETURN(pb, err);
}
fcbp->fcbFlNum = frp->filFlNum;
if (frp->filFlags & FSOFTLOCKBIT) {
switch (permssn) {
case fsCurPerm:
permssn = fsRdPerm;
break;
case fsWrPerm:
case fsRdWrPerm:
case fsRdWrShPerm:
fcbp->fcbFlNum = 0;
err = permErr;
fs_err_hook (err);
PBRETURN(pb, err);
}
fcbp->fcbMdRByt = FLOCKEDBIT;
} else {
if (permssn == fsCurPerm)
permssn = fsRdWrPerm;
fcbp->fcbMdRByt = 0;
}
switch (permssn) {
case fsRdPerm:
break;
case fsWrPerm:
case fsRdWrPerm:
fcbp->fcbMdRByt |= WRITEBIT;
break;
case fsRdWrShPerm:
fcbp->fcbMdRByt |= (WRITEBIT|SHAREDBIT);
break;
default:
fcbp->fcbFlNum = 0;
warning_unexpected ("unknown permission");
err = fsDSIntErr;
fs_err_hook (err);
PBRETURN(pb, err);
}
if (ft == resourcefork)
fcbp->fcbMdRByt |= RESOURCEBIT;
else
fcbp->fcbMdRByt &= ~RESOURCEBIT;
if (ft == datafork) {
fcbp->fcbEOF = frp->filLgLen;
fcbp->fcbPLen = frp->filPyLen;
fcbp->fcbSBlk = frp->filStBlk;
memmove((char *) fcbp->fcbExtRec, (char *) frp->filExtRec,
(LONGINT) sizeof(frp->filExtRec));
} else {
fcbp->fcbEOF = frp->filRLgLen;
fcbp->fcbPLen = frp->filRPyLen;
fcbp->fcbSBlk = frp->filRStBlk;
memmove((char *) fcbp->fcbExtRec, (char *) frp->filRExtRec,
(LONGINT) sizeof(frp->filRExtRec));
}
fcbp->fcbCrPs = 0;
fcbp->fcbVPtr = RM(btparamrec.vcbp);
#if defined(MAC)
fcbp->fcbBfAdr = pb->ioMisc;
#else /* !defined(MAC) */
fcbp->fcbBfAdr = (Ptr) (long) pb->ioMisc;
#endif /* !defined(MAC) */
fcbp->fcbFlPos = 0;
fcbp->fcbClmpSize = frp->filClpSize;
if (!fcbp->fcbClmpSize)
fcbp->fcbClmpSize = btparamrec.vcbp->vcbClpSiz;
fcbp->fcbBTCBPtr = 0; /* Used only for B-trees I think */
fcbp->fcbFType = frp->filUsrWds.fdType;
catkeyp = (catkey *) btparamrec.foundp;
cachep = ROMlib_addrtocachep((Ptr) catkeyp, btparamrec.vcbp);
fcbp->fcbCatPos = cachep->logblk;
fcbp->fcbDirID = catkeyp->ckrParID;
str255assign(fcbp->fcbCName, catkeyp->ckrCName);
pb->ioRefNum = CW((char *) fcbp - (char *) MR(FCBSPtr));
PBRETURN(pb, noErr);
}
#undef RETURN
PUBLIC OSErr hfsPBOpen(ParmBlkPtr pb, BOOLEAN async)
{
OSErr err;
err = PBOpenHelper((ioParam *) pb, datafork, 0L, async);
fs_err_hook (err);
return err;
}
PUBLIC OSErr hfsPBOpenRF(ParmBlkPtr pb, BOOLEAN async)
{
OSErr err;
err = PBOpenHelper((ioParam *) pb, resourcefork, 0L, async);
fs_err_hook (err);
return err;
}
PUBLIC OSErr hfsPBHOpen(HParmBlkPtr pb, BOOLEAN async)
{
OSErr err;
err = PBOpenHelper((ioParam *) pb, datafork, CL(pb->fileParam.ioDirID),
async);
fs_err_hook (err);
return err;
}
PUBLIC OSErr hfsPBHOpenRF(HParmBlkPtr pb, BOOLEAN async)
{
OSErr err;
err = PBOpenHelper((ioParam *) pb, resourcefork, CL(pb->fileParam.ioDirID),
async);
fs_err_hook (err);
return err;
}
/*
* NOTE: I've tried playing around with the LockRange and UnlockRange calls
* and I don't know what they do. They seem to be unimplemented on
* our Mac+. Perhaps when they were created there was no idea that
* multifinder would exist so they don't do anything if you're not
* on a network.
*/
PUBLIC OSErr hfsPBLockRange(ParmBlkPtr pb, BOOLEAN async)
{
PBRETURN((ioParam *) pb, noErr);
}
PUBLIC OSErr hfsPBUnlockRange(ParmBlkPtr pb, BOOLEAN async)
{
PBRETURN((ioParam *) pb, noErr);
}
PUBLIC OSErr hfsPBGetFPos(ParmBlkPtr pb, BOOLEAN async)
{
filecontrolblock *fcbp;
OSErr err;
fcbp = ROMlib_refnumtofcbp(CW(pb->ioParam.ioRefNum));
if (!fcbp)
{
err = rfNumErr;
fs_err_hook (err);
/*-->*/ PBRETURN((ioParam *) pb, err);
}
pb->ioParam.ioReqCount = 0;
pb->ioParam.ioActCount = 0;
pb->ioParam.ioPosMode = 0;
pb->ioParam.ioPosOffset = fcbp->fcbCrPs;
PBRETURN((ioParam *) pb, noErr);
}
PUBLIC OSErr hfsPBSetFPos(ParmBlkPtr pb, BOOLEAN async)
{
filecontrolblock *fcbp;
LONGINT newpos;
OSErr retval;
fcbp = ROMlib_refnumtofcbp(CW(pb->ioParam.ioRefNum));
if (!fcbp)
{
retval = rfNumErr;
fs_err_hook (retval);
/*-->*/ PBRETURN((ioParam *) pb, retval);
}
retval = noErr;
newpos = pbabsoffset((ioParam *) pb, fcbp);
if (newpos < 0)
retval = posErr;
else if (newpos > Cx(fcbp->fcbEOF)) {
retval = eofErr;
fcbp->fcbCrPs = fcbp->fcbEOF;
} else
fcbp->fcbCrPs = CL(newpos);
pb->ioParam.ioPosOffset = fcbp->fcbCrPs;
fs_err_hook (retval);
PBRETURN((ioParam *) pb, retval);
}
PUBLIC OSErr hfsPBGetEOF(ParmBlkPtr pb, BOOLEAN async)
{
filecontrolblock *fcbp;
OSErr err;
fcbp = ROMlib_refnumtofcbp(CW(pb->ioParam.ioRefNum));
if (!fcbp)
{
err = rfNumErr;
fs_err_hook (err);
/*-->*/ PBRETURN((ioParam *) pb, err);
}
#if defined(MAC)
pb->ioParam.ioMisc = (Ptr) fcbp->fcbEOF;
#else /* !defined(MAC) */
pb->ioParam.ioMisc = fcbp->fcbEOF;
#endif /* !defined(MAC) */
PBRETURN((ioParam *) pb, noErr);
}