executor/src/hfsVolume.c

1067 lines
27 KiB
C

/* Copyright 1992 - 1995 by Abacus Research and
* Development, Inc. All rights reserved.
*/
#if !defined (OMIT_RCSID_STRINGS)
char ROMlib_rcsid_hfsVolume[] =
"$Id: hfsVolume.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/hfs.h"
#include "rsys/file.h"
#if defined (CYGWIN32)
#include "winfs.h"
#endif
/*
* TODO: support read and write count. This will make it possible to
* discriminate between identically named disks (i.e. when you
* have two Untitled disks that have been ejected). Currently
* disks are matched by name and name only.
*/
/*
* NOTE: in the routines below there is no freeing of memory if an error is
* detected. This should be done sometime.
*/
/*
* NOTE: NewPtr_aligned_4 is so that our miscellaneous buffers will be aligned
* properly for DMA transfers on the NeXT. Depending on the
* implementation of NewPtr, the following loop could
* eat all of memory, but it would require a pretty unlikely
* implementation of NewPtr.
*/
#define NewPtr_aligned_4(x, y) NewPtr(x)
#if !defined(NewPtr_aligned_4)
PRIVATE Ptr NewPtr_aligned_4(Size size, INTEGER align)
{
Ptr p, p2, p3;
Size shim;
p = NewPtr(size);
if (((LONGINT) p & 3) == align)
return p;
else {
shim = 0;
while (p) {
DisposPtr(p);
p2 = NewPtr(++shim);
p = NewPtr(size);
p3 = NewPtr(shim);
DisposPtr(p3);
if (((LONGINT) p & 3) == align) {
DisposPtr(p2);
return p;
} else {
DisposPtr(p);
DisposPtr(p2);
p2 = NewPtr(shim+1);
p = NewPtr(size);
p3 = NewPtr(shim+1);
DisposPtr(p3);
if (((LONGINT) p & 3) == align) {
DisposPtr(p2);
return p;
} else
DisposPtr(p2);
}
}
return p;
}
}
#endif
PRIVATE OSErr readvolumebitmap(HVCB *vcbp, volumeinfoPtr vp)
{
OSErr err;
short nphysrequired;
if (Cx(vp->drSigWord) != 0x4244)
{
long *words;
err = noMacDskErr;
words = (long *) vp;
warning_fs_log ("sigword = 0x%02x (%08lx %08lx %08lx %08lx)",
CW (vp->drSigWord), CL (words[0]), CL (words[1]),
CL (words[2]), CL (words[3]));
}
else {
nphysrequired = NPHYSREQ(ROUNDUP8(Cx(vp->drNmAlBlks)) / 8);
vcbp->vcbMAdr =
RM(NewPtr_aligned_4(PHYSBSIZE * nphysrequired + MADROFFSET, 0));
vcbp->vcbMLen = CW(nphysrequired + MADROFFSET);
/*really add MADROFFSET?*/
if (!vcbp->vcbMAdr)
err = MemError();
else
err = ROMlib_transphysblk (&((VCBExtra *) vcbp)->u.hfs,
CW(vp->drVBMSt) * (ULONGINT) PHYSBSIZE,
nphysrequired,
MR(vcbp->vcbMAdr) + MADROFFSET, reading,
(LONGINT *) 0);
}
return err;
}
PRIVATE OSErr initcache(HVCB *vcbp)
{
THz savezone;
cachehead *headp;
cacheentry *cachep;
INTEGER align;
savezone = TheZone;
TheZone = SysZone;
align = ((char *) &cachep->buf - (char *) &cachep) & 3;
vcbp->vcbCtlBuf = RM(NewPtr_aligned_4(sizeof(cachehead) +
NCACHEENTRIES * sizeof(cacheentry), align));
if (!vcbp->vcbCtlBuf)
return MemError();
TheZone = savezone;
headp = (cachehead *) MR(vcbp->vcbCtlBuf);
headp->nitems = CW(NCACHEENTRIES);
headp->flags = 0;
headp->flink = RM((cacheentry *)(headp + 1));
headp->blink = RM(MR(headp->flink) + NCACHEENTRIES - 1);
for (cachep = MR(headp->flink); cachep <= MR(headp->blink); cachep++) {
cachep->flink = RM(cachep + 1);
cachep->blink = RM(cachep - 1);
cachep->vptr = 0;
cachep->fileno = 0;
cachep->flags = CACHEFREE;
}
MR(headp->flink)->blink = RM((cacheentry *) headp);
MR(headp->blink)->flink = RM((cacheentry *) headp);
return noErr;
}
PUBLIC boolean_t ROMlib_hfs_plus_support = FALSE;
PRIVATE boolean_t
is_hfs_plus_wrapper (volumeinfoPtr vp)
{
boolean_t retval;
retval = vp->drVCSize == CWC (0x482b);
return retval;
}
PRIVATE OSErr
check_volume_size (volumeinfoPtr vp)
{
OSErr retval;
if (is_hfs_plus_wrapper (vp))
{
warning_unexpected ("Found wrapped HFS+ volume");
retval = noErr;
}
else
{
unsigned short nmalblks;
unsigned long dralblksiz;
nmalblks = CW (vp->drNmAlBlks);
dralblksiz = CL (vp->drAlBlkSiz);
retval = ((long long) nmalblks * dralblksiz >= 2LL * 1024 * 1024 * 1024
? paramErr : noErr);
if (retval != noErr)
warning_unexpected ("drNmAlBlks = %d, drAlBlkSiz = %lu",
(int) nmalblks, dralblksiz);
}
return retval;
}
PRIVATE OSErr readvolumeinfo(HVCB *vcbp) /* call once during mounting */
{
OSErr err;
vcbp->vcbBufAdr = RM(NewPtr_aligned_4((Size) PHYSBSIZE, 0));
if (!vcbp)
err = MemError();
else {
err = ROMlib_transphysblk (&((VCBExtra *)vcbp)->u.hfs,
(ULONGINT) VOLUMEINFOBLOCKNO * PHYSBSIZE,
1, MR(vcbp->vcbBufAdr), reading,
(LONGINT *) 0);
if (err == noErr)
err = check_volume_size ((volumeinfoPtr) MR (vcbp->vcbBufAdr));
if (err == noErr) {
err = readvolumebitmap(vcbp, (volumeinfoPtr) MR(vcbp->vcbBufAdr));
if (err == noErr)
err = initcache(vcbp);
}
}
return err;
}
#define VOLUMEINFOBACKUP(vcbp) \
((CW(vcbp->vcbNmAlBlks) * Cx(vcbp->vcbAlBlkSiz)) + \
(Cx(vcbp->vcbAlBlSt) * PHYSBSIZE))
void vcbsync(HVCB *vcbp)
{
if (!ROMlib_nosync)
fsync(((VCBExtra *)vcbp)->u.hfs.fd);
}
PRIVATE OSErr writevolumeinfo(HVCB *vcbp, Ptr p)
{
OSErr err;
err = ROMlib_transphysblk (&((VCBExtra *)vcbp)->u.hfs,
(ULONGINT) VOLUMEINFOBLOCKNO * PHYSBSIZE,
1, p, writing, (LONGINT *) 0);
if (err == noErr)
err = ROMlib_transphysblk (&((VCBExtra *)vcbp)->u.hfs,
(ULONGINT) VOLUMEINFOBACKUP(vcbp), 1, p,
writing, (LONGINT *) 0);
vcbsync(vcbp);
return err;
}
OSErr ROMlib_flushvcbp(HVCB *vcbp)
{
Ptr realp, p;
OSErr retval;
volumeinfoPtr vip;
filecontrolblock *fcbp;
retval = ROMlib_flushcachevcbp(vcbp);
if (retval == noErr)
{
if (Cx(vcbp->vcbFlags) & VCBDIRTY)
{
realp = alloca ((Size) 512 + 4); /* needs to be aligned on unix */
p = (Ptr) (((long) realp+3) & ~3L);
vip = (volumeinfoPtr) p;
memmove(&vip->drSigWord, &vcbp->vcbSigWord, (LONGINT) 64);
memmove(&vip->drVolBkUp, &vcbp->vcbVolBkUp, (LONGINT) 66);
fcbp = (filecontrolblock *)((char *)MR(FCBSPtr)
+ Cx(vcbp->vcbXTRef));
vip->drXTFlSize = fcbp->fcbPLen;
memmove(&vip->drXTExtRec, &fcbp->fcbExtRec,
(LONGINT) sizeof(fcbp->fcbExtRec));
fcbp = (filecontrolblock *)((char *)MR(FCBSPtr)
+ Cx(vcbp->vcbCTRef));
vip->drCTFlSize = fcbp->fcbPLen;
memmove(&vip->drCTExtRec, &fcbp->fcbExtRec,
(LONGINT) sizeof(fcbp->fcbExtRec));
retval = writevolumeinfo(vcbp, p);
vcbp->vcbFlags &= CW(~VCBDIRTY);
}
}
return retval;
}
PRIVATE HVCB *vcbbyname(StringPtr name)
{
HVCB *vcbp;
for (vcbp = (HVCB *) MR(VCBQHdr.qHead); vcbp &&
!EqualString(vcbp->vcbVN, name, FALSE, TRUE) ;
vcbp = (HVCB *) MR(vcbp->qLink))
;
return vcbp;
}
#if defined (CYGWIN32) || defined (MSDOS)
#define VCB_CMPN_FUNC strncasecmp
#define VCB_CMP_FUNC strcasecmp
#else
#define VCB_CMPN_FUNC strncmp
#define VCB_CMP_FUNC strcmp
#endif
PUBLIC HVCB *ROMlib_vcbbybiggestunixname(const char *name)
{
HVCB *vcbp, *bestvcbp;
int namesize, bestsize;
if (strchr (name, '\\'))
{
int len;
char *new_name, *op, c;
const char *ip;
len = strlen (name) + 1;
new_name = alloca (len);
for (op = new_name, ip = name; (c = *ip++);)
*op++ = c == '\\' ? '/' : c;
*op++ = 0;
name = new_name;
}
bestvcbp = 0;
bestsize = -1;
for (vcbp = (HVCB *) MR(VCBQHdr.qHead); vcbp;
vcbp = (HVCB *) MR(vcbp->qLink)) {
if (!vcbp->vcbCTRef) {
namesize = strlen(((VCBExtra *) vcbp)->unixname);
if (namesize > bestsize &&
VCB_CMPN_FUNC(((VCBExtra *) vcbp)->unixname,
name, namesize) == 0) {
bestsize = namesize;
bestvcbp = vcbp;
}
}
}
return bestvcbp;
}
PUBLIC VCBExtra *
ROMlib_vcbbyunixname(char *name)
{
HVCB *vcbp;
for (vcbp = (HVCB *) MR(VCBQHdr.qHead); vcbp &&
(vcbp->vcbCTRef ||
VCB_CMP_FUNC(((VCBExtra *) vcbp)->unixname,
name) != 0);
vcbp = (HVCB *) MR(vcbp->qLink))
;
return (VCBExtra *) vcbp;
}
PUBLIC HVCB *ROMlib_vcbbydrive(short vrefnum)
{
HVCB *vcbp;
for (vcbp = (HVCB *) MR(VCBQHdr.qHead);
vcbp && Cx(vcbp->vcbDrvNum) != vrefnum;
vcbp = (HVCB *) MR(vcbp->qLink))
;
return vcbp;
}
PUBLIC DrvQExtra *
ROMlib_dqbydrive (short vrefnum)
{
DrvQEl *dp;
DrvQExtra *retval;
short swapped_vrefnum;
swapped_vrefnum = CW (vrefnum);
retval = 0;
for (dp = (DrvQEl *) MR (DrvQHdr.qHead);
dp && (retval = (DrvQExtra *) ((char *) dp - sizeof(LONGINT)),
retval->dq.dQDrive != swapped_vrefnum);
dp = (DrvQEl *) MR (dp->qLink))
;
return dp ? retval : 0;
}
PUBLIC HVCB *ROMlib_vcbbyvrn(short vrefnum)
{
HVCB *vcbp;
for (vcbp = (HVCB *) MR(VCBQHdr.qHead);
vcbp && Cx(vcbp->vcbVRefNum) != vrefnum;
vcbp = (HVCB *) MR(vcbp->qLink))
;
return vcbp;
}
PUBLIC HVCB *ROMlib_findvcb(short vrefnum, StringPtr name, LONGINT *diridp,
BOOLEAN usedefault)
{
HVCB *vcbp;
INTEGER namelen;
Str255 tempname;
char *colonp;
wdentry *wdp;
namelen = name ? name[0] : 0;
vcbp = 0;
if (namelen && name[1] != ':' &&
(colonp = ROMlib_indexn((char *) name+2, ':', namelen-1))) {
tempname[0] = colonp - (char *) name - 1;
memmove((char *)tempname+1, (char *) name+1, (LONGINT) tempname[0]);
vcbp = vcbbyname(tempname);
if (vcbp && diridp)
*diridp = 1;
} else {
if (vrefnum > 0)
vcbp = ROMlib_vcbbydrive(vrefnum);
else if (vrefnum < 0) {
if (ISWDNUM(vrefnum)) {
wdp = WDNUMTOWDP(vrefnum);
vcbp = MR(wdp->vcbp);
if (diridp)
*diridp = CL(wdp->dirid);
} else
vcbp = ROMlib_vcbbyvrn(vrefnum);
} else if (usedefault || (!name && !vrefnum)) {
vcbp = (HVCB *) MR(DefVCBPtr);
if (diridp)
*diridp = CL(DefDirID);
}
}
return vcbp;
}
PRIVATE INTEGER drvtodref(INTEGER vref) /* TODO: flesh this out */
{
#if 0
switch (vref) {
case 1:
case 2:
return -5;
case 3:
case 4:
return -2;
default:
return 0;
}
#else
return OURHFSDREF;
#endif
}
PRIVATE INTEGER openxtnt(LONGINT filnum, LONGINT clpsize, LONGINT filsize, xtntrec xtr,
HVCB *vcbp)
{
filecontrolblock *fcbp;
INTEGER retval;
fcbp = ROMlib_getfreefcbp();
if (fcbp) {
fcbp->fcbFlNum = CL(filnum);
fcbp->fcbMdRByt = 0;
fcbp->fcbTypByt = 0;
fcbp->fcbSBlk = 0;
fcbp->fcbEOF = CL(filsize);
fcbp->fcbPLen = CL(filsize);
fcbp->fcbCrPs = 0;
fcbp->fcbVPtr = RM(vcbp);
fcbp->fcbBfAdr = 0;
fcbp->fcbFlPos = 0;
fcbp->fcbClmpSize = CL(clpsize);
fcbp->fcbBTCBPtr = 0;
memmove(fcbp->fcbExtRec, xtr, (LONGINT) sizeof(xtntrec));
fcbp->fcbFType = 0;
fcbp->fcbCatPos = 0;
fcbp->fcbDirID = 0;
fcbp->fcbCName[0] = 0;
retval = (char *) fcbp - (char *) MR(FCBSPtr);
} else
retval = 0;
return retval;
}
#define XTNUM 3
#define CTNUM 4
PUBLIC INTEGER ROMlib_nextvrn = 0; /* TODO: low memory global */
PUBLIC OSErr
hfsPBMountVol (ParmBlkPtr pb, LONGINT floppyfd, LONGINT offset, LONGINT bsize,
LONGINT maxbytes, drive_flags_t flags, DrvQExtra *dqp)
{
HVCB *vcbp, *vcbp2;
OSErr err;
volumeinfoPtr vip;
BOOLEAN alreadythere;
ULONGINT nblocks;
THz saveZone;
warning_fs_log ("floppyfd = 0x%x, offset = %d, bsize = %d, maxbytes = %d "
"flags = 0x%x", floppyfd, offset, bsize, maxbytes, flags);
saveZone = TheZone;
TheZone = SysZone;
vcbp = ROMlib_vcbbydrive(CW(pb->volumeParam.ioVRefNum));
if (vcbp)
err = volOnLinErr;
else {
vcbp = (HVCB *) NewPtr((Size) sizeof(VCBExtra));
((VCBExtra *) vcbp)->u.hfs.fd = floppyfd;
((VCBExtra *) vcbp)->u.hfs.offset = offset;
((VCBExtra *) vcbp)->u.hfs.bsize = bsize;
((VCBExtra *) vcbp)->u.hfs.maxbytes = maxbytes;
if (!vcbp)
err = MemError();
else {
err = readvolumeinfo(vcbp);
if (err == noErr) {
vip = (volumeinfoPtr) MR(vcbp->vcbBufAdr);
alreadythere = FALSE;
for (vcbp2 = (HVCB *) MR(VCBQHdr.qHead); vcbp2;
vcbp2 = (HVCB *) MR(vcbp2->qLink))
if (EqualString(vcbp2->vcbVN, vip->drVN, TRUE, TRUE)
&& vcbp2->vcbDrvNum == 0) {
#if 1
vcbp2->vcbBufAdr = vcbp->vcbBufAdr;
vcbp2->vcbMAdr = vcbp->vcbMAdr;
vcbp2->vcbCtlBuf = vcbp->vcbCtlBuf;
#endif
((VCBExtra *) vcbp2)->unixname =
((VCBExtra *) vcbp)->unixname;
((VCBExtra *) vcbp2)->u.hfs.fd =
((VCBExtra *) vcbp)->u.hfs.fd;
DisposPtr((Ptr) vcbp);
alreadythere = TRUE;
vcbp = vcbp2;
break;
}
memmove(&vcbp->vcbSigWord, &vip->drSigWord, (LONGINT) 64);
nblocks = (CL(vcbp->vcbAlBlkSiz) / PHYSBSIZE) *
CW(vcbp->vcbNmAlBlks) + CW(vcbp->vcbAlBlSt) + 2;
dqp->dq.dQDrvSz = CW(nblocks);
dqp->dq.dQDrvSz2 = CW(nblocks >> 16);
dqp->dq.qType = 1;
vcbp->vcbDrvNum = pb->volumeParam.ioVRefNum;
vcbp->vcbDRefNum = CW(drvtodref(Cx(pb->volumeParam.ioVRefNum)));
vcbp->vcbFSID = 0;
if (!alreadythere)
vcbp->vcbVRefNum = CW(--ROMlib_nextvrn);
vcbp->vcbDirIndex = 0;
vcbp->vcbDirBlk = 0;
vcbp->vcbFlags = 0;
memmove(&vcbp->vcbVolBkUp, &vip->drVolBkUp, (LONGINT) 66);
vcbp->vcbXTAlBlks =
CW(Cx(vip->drXTFlSize) / Cx(vip->drAlBlkSiz));
vcbp->vcbCTAlBlks =
CW(Cx(vip->drCTFlSize) / Cx(vip->drAlBlkSiz));
vcbp->vcbXTRef = CW(openxtnt(XTNUM, Cx(vip->drXTClpSiz),
Cx(vip->drXTFlSize), vip->drXTExtRec, vcbp));
vcbp->vcbCTRef = CW(openxtnt(CTNUM, Cx(vip->drCTClpSiz),
Cx(vip->drCTFlSize), vip->drCTExtRec, vcbp));
vcbp->vcbDirIDM = 0;
vcbp->vcbOffsM = 0;
vcbp->vcbAtrb = 0;
if (flags & DRIVE_FLAGS_FIXED)
vcbp->vcbAtrb |= CW(VNONEJECTABLEBIT);
if (!vcbp->vcbCTRef)
err = tmfoErr;
if (err == noErr) {
if (!(flags & DRIVE_FLAGS_LOCKED))
{
OSErr err2;
signed char buffer[PHYSBSIZE+3];
signed char *buf;
buf = (signed char *) (((long)buffer+3) & ~3L);
err2 =
ROMlib_transphysblk (&((VCBExtra *)vcbp)->u.hfs,
(ULONGINT) VOLUMEINFOBLOCKNO
* PHYSBSIZE, 1, buf, reading,
(LONGINT *) 0);
if (err2 == noErr)
{
err2 =
ROMlib_transphysblk (&((VCBExtra *)vcbp)->u.hfs,
(ULONGINT) VOLUMEINFOBLOCKNO
* PHYSBSIZE, 1, buf,
writing, (LONGINT *) 0);
if (err2 == noErr)
err2 = ROMlib_flushvcbp (vcbp);
}
if (err2 != noErr)
flags |= DRIVE_FLAGS_LOCKED;
}
if (flags & DRIVE_FLAGS_LOCKED)
vcbp->vcbAtrb |= CW(VHARDLOCKBIT);
if (!alreadythere)
Enqueue((QElemPtr) vcbp, &VCBQHdr);
pb->volumeParam.ioVRefNum = vcbp->vcbVRefNum;
if (!DefVCBPtr) {
DefVCBPtr = RM(vcbp);
DefVRefNum = vcbp->vcbVRefNum;
DefDirID = CLC (2);
}
}
}
}
}
TheZone = saveZone;
warning_fs_log ("err = %d", err);
PBRETURN((volumeParam *) pb, err);
}
PRIVATE void goofyclip(unsigned short *up)
{
if (CW(*up) > 0x7C00) /* IMIV-130 */
*up = CWC (0x7C00);
}
/*
* getworkingdir returns the directory id associated with vrefnum
*/
PRIVATE LONGINT getworkingdir(INTEGER vrefnum)
{
LONGINT retval;
wdentry *wdp;
if (ISWDNUM(vrefnum)) {
wdp = WDNUMTOWDP(vrefnum);
retval = CL(wdp->dirid);
} else
retval = 0;
return retval;
}
/*
* getnmfls finds a directory's valence
*/
PRIVATE unsigned short getnmfls(HVCB *vcbp, INTEGER workingdirnum)
{
LONGINT dirid;
catkey key;
threadrec *thp;
unsigned short retval;
btparam btparamrec;
OSErr err;
dirid = getworkingdir(workingdirnum);
err = ROMlib_makecatparam(&btparamrec, vcbp, dirid, 0, (Ptr) 0);
if (err == noErr)
err = ROMlib_keyfind(&btparamrec);
if (err == noErr && btparamrec.success) {
thp = (threadrec *) DATAPFROMKEY(btparamrec.foundp);
key.ckrParID = Cx(thp->thdParID);
str255assign(key.ckrCName, thp->thdCName);
key.ckrKeyLen = sizeof(LONGINT) + 2 + key.ckrCName[0];
err = ROMlib_keyfind(&btparamrec);
if (err == noErr && btparamrec.success)
retval = ((directoryrec *)DATAPFROMKEY(btparamrec.foundp))->dirVal;
else
retval = 0;
} else
retval = 0;
return retval;
}
#define RETURN return
PRIVATE OSErr commonGetVInfo(HVolumeParam *pb, BOOLEAN async, fstype fs)
{
HVCB *vcbp;
INTEGER workingdirnum;
if (Cx(pb->ioVolIndex) > 0) {
vcbp = (HVCB *) ROMlib_indexqueue(&VCBQHdr, Cx(pb->ioVolIndex));
workingdirnum = 0;
} else {
if (pb->ioVolIndex == 0)
vcbp = (HVCB *) ROMlib_findvcb(Cx(pb->ioVRefNum), (StringPtr) 0,
(LONGINT *) 0, FALSE);
else /* if (Cx(pb->ioVolIndex) < 0) */
vcbp = (HVCB *) ROMlib_findvcb(Cx(pb->ioVRefNum), MR(pb->ioNamePtr),
(LONGINT *) 0, TRUE);
workingdirnum = getworkingdir(Cx(pb->ioVRefNum));
}
if (!vcbp)
/*-->*/ PBRETURN(pb, nsvErr);
if (/*CW (pb->ioVolIndex) >= 0 &&*/ pb->ioNamePtr)
str255assign(MR(pb->ioNamePtr), (StringPtr) vcbp->vcbVN);
pb->ioVCrDate = vcbp->vcbCrDate;
pb->ioVAtrb = vcbp->vcbAtrb;
if (workingdirnum)
pb->ioVNmFls = CW(getnmfls(vcbp, workingdirnum));
else
pb->ioVNmFls = vcbp->vcbNmFls;
pb->ioVNmAlBlks = vcbp->vcbNmAlBlks;
pb->ioVAlBlkSiz = vcbp->vcbAlBlkSiz;
pb->ioVClpSiz = vcbp->vcbClpSiz;
pb->ioAlBlSt = vcbp->vcbAlBlSt;
pb->ioVNxtCNID = vcbp->vcbNxtCNID;
pb->ioVFrBlk = vcbp->vcbFreeBks;
switch (fs) {
case mfs:
((volumeParam *) pb)->ioVLsBkUp = vcbp->vcbVolBkUp;
((volumeParam *) pb)->ioVDirSt = 0;
((volumeParam *) pb)->ioVBlLn = 0;
if (!workingdirnum)
pb->ioVRefNum = vcbp->vcbVRefNum;
goofyclip((unsigned short *) &pb->ioVNmAlBlks);
goofyclip((unsigned short *) &pb->ioVFrBlk);
break;
case hfs:
pb->ioVLsMod = vcbp->vcbLsMod;
pb->ioVBitMap = vcbp->vcbVBMSt;
#if !defined (THINKCMESSED)
pb->ioVAllocPtr = vcbp->vcbAllocPtr;
#else /* THINKCMESSED */
pb->ioAllocPtr = vcbp->vcbAllocPtr;
#endif /* THINKCMESSED */
pb->ioVRefNum = vcbp->vcbVRefNum;
pb->ioVSigWord = vcbp->vcbSigWord;
pb->ioVDrvInfo = vcbp->vcbDrvNum;
pb->ioVDRefNum = vcbp->vcbDRefNum;
pb->ioVFSID = vcbp->vcbFSID;
pb->ioVBkUp = vcbp->vcbVolBkUp;
pb->ioVSeqNum = vcbp->vcbVSeqNum;
pb->ioVWrCnt = vcbp->vcbWrCnt;
pb->ioVFilCnt = vcbp->vcbFilCnt;
pb->ioVDirCnt = vcbp->vcbDirCnt;
memmove(pb->ioVFndrInfo, vcbp->vcbFndrInfo,
(LONGINT) sizeof(pb->ioVFndrInfo));
break;
}
PBRETURN(pb, noErr);
}
#undef RETURN
PUBLIC OSErr hfsPBGetVInfo(ParmBlkPtr pb, BOOLEAN async)
{
return commonGetVInfo((HVolumeParam *)pb, async, mfs);
}
PUBLIC OSErr hfsPBHGetVInfo(HParmBlkPtr pb, BOOLEAN async)
{
return commonGetVInfo((HVolumeParam *) pb, async, hfs);
}
#define ATRBMASK VSOFTLOCKBIT
PUBLIC OSErr hfsPBSetVInfo(HParmBlkPtr pb, BOOLEAN async)
{
OSErr err;
HVCB *vcbp;
vcbp = ROMlib_findvcb(Cx(pb->volumeParam.ioVRefNum),
MR(pb->volumeParam.ioNamePtr), (LONGINT *) 0, FALSE);
if (vcbp) {
if (Cx(vcbp->vcbAtrb) & VHARDLOCKBIT)
err = wPrErr;
else {
if (pb->volumeParam.ioNamePtr)
str255assign((StringPtr) vcbp->vcbVN,
MR(pb->volumeParam.ioNamePtr));
vcbp->vcbCrDate = pb->volumeParam.ioVCrDate;
vcbp->vcbLsMod = pb->volumeParam.ioVLsMod;
vcbp->vcbAtrb = CW((Cx(vcbp->vcbAtrb) & ~ATRBMASK) |
(Cx(pb->volumeParam.ioVAtrb) & ATRBMASK));
vcbp->vcbClpSiz = pb->volumeParam.ioVClpSiz;
vcbp->vcbVolBkUp = pb->volumeParam.ioVBkUp;
vcbp->vcbVSeqNum = pb->volumeParam.ioVSeqNum;
memmove(vcbp->vcbFndrInfo, pb->volumeParam.ioVFndrInfo,
(LONGINT) 32);
vcbp->vcbFlags |= CW(VCBDIRTY);
err = noErr;
}
} else
err = nsvErr;
PBRETURN((volumeParam *) pb, err);
}
PRIVATE OSErr getvolcommon(volumeParam *pb)
{
OSErr err;
if (!DefVCBPtr)
err = nsvErr;
else {
err = noErr;
if (pb->ioNamePtr)
str255assign(MR(pb->ioNamePtr), (StringPtr) MR(DefVCBPtr)->vcbVN);
pb->ioVRefNum = DefVRefNum;
}
return err;
}
PUBLIC OSErr hfsPBGetVol(ParmBlkPtr pb, BOOLEAN async)
{
OSErr err;
err = getvolcommon((volumeParam *) pb);
PBRETURN((volumeParam *) pb, err);
}
PUBLIC LONGINT DefDirID = CLC(2);
PUBLIC OSErr hfsPBHGetVol(WDPBPtr pb, BOOLEAN async)
{
wdentry *wdp;
OSErr err;
err = getvolcommon((volumeParam *) pb);
pb->ioWDDirID = DefDirID;
if (err == noErr) {
if (ISWDNUM(Cx(DefVRefNum))) {
wdp = WDNUMTOWDP(Cx(DefVRefNum));
pb->ioWDProcID = wdp->procid;
pb->ioWDVRefNum = MR(wdp->vcbp)->vcbVRefNum;
} else {
pb->ioWDProcID = 0;
pb->ioWDVRefNum = DefVRefNum;
}
}
PBRETURN(pb, err);
}
/*
* NOTE: Considerable change related to PBSetVol, PBHSetVol were made
* just now (Sat Aug 1 16:13:35 MDT 1992). These routines
* have been giving us trouble for some time. Tech Note 140
* implies that there is a "DefDirID" buried somewhere in low
* global space. Sometime we should try to ferret it out.
*
*/
PRIVATE OSErr setvolhelper(volumeParam *pb, BOOLEAN aysnc, LONGINT dirid,
BOOLEAN convertzeros)
{
HVCB *vcbp, *newDefVCBPtr;
OSErr err, err1;
LONGINT newdir, newDefDirID;
INTEGER newDefVRefNum;
CInfoPBRec cpb;
/*
* CinemationCD hack ... they store a directory as a 2-byte quantity and
* sign extend it. This will only help us recover the sign bit.
*/
if (dirid < 0)
dirid = 64 * 1024 + dirid;
newdir = 0;
vcbp = ROMlib_findvcb(Cx(pb->ioVRefNum), MR(pb->ioNamePtr),
&newdir, FALSE);
if (!vcbp)
err = nsvErr;
else {
err = noErr;
newDefVCBPtr = RM(vcbp);
newDefDirID = CLC(0);
if (newdir > 2) { /* picked up working directory */
newDefDirID = dirid ? CL(dirid) : CL(newdir);
newDefVRefNum = pb->ioVRefNum;
} else if (newdir == 1) { /* picked up by name */
newDefDirID = CL(newdir);
newDefVRefNum = vcbp->vcbVRefNum;
} else {
newDefVRefNum = pb->ioVRefNum;
if (dirid == 0 && convertzeros)
newDefDirID = CLC(2);
else
newDefDirID = CL(dirid);
}
if (!convertzeros && pb->ioNamePtr) { /* this could change things */
if (MR(pb->ioNamePtr)[0] == 0)
cpb.hFileInfo.ioNamePtr = 0; /* otherwise we fill in */
else
cpb.hFileInfo.ioNamePtr = pb->ioNamePtr;
cpb.hFileInfo.ioVRefNum = pb->ioVRefNum;
cpb.hFileInfo.ioFDirIndex = CWC (0);
cpb.hFileInfo.ioDirID = CL(dirid);
/*
* NOTE: the else case was added after seeing Excel 4 Installer do a setvol
* to a file, presumably with the intent to set it to the parent id.
*
* Also we make this try twice as a PM PMSP
*/
do {
if ((err1 = PBGetCatInfo(&cpb, FALSE)) == noErr)
{
if (cpb.hFileInfo.ioFlAttrib & ATTRIB_ISADIR)
newDefDirID = cpb.dirInfo.ioDrDirID;
else
newDefDirID = cpb.hFileInfo.ioFlParID;
}
} while (err1 && cpb.hFileInfo.ioDirID == 0 &&
(cpb.hFileInfo.ioDirID = CLC(2)));
}
if (newDefDirID)
DefDirID = newDefDirID;
else if (DefVCBPtr != newDefVCBPtr || DefVRefNum != newDefVRefNum)
DefDirID = CLC(2);
DefVCBPtr = newDefVCBPtr;
DefVRefNum = newDefVRefNum;
}
PBRETURN(pb, err);
}
PUBLIC OSErr hfsPBSetVol(ParmBlkPtr pb, BOOLEAN async)
{
return setvolhelper((volumeParam *) pb, async, 0, TRUE);
}
PUBLIC OSErr hfsPBHSetVol(WDPBPtr pb, BOOLEAN async)
{
return setvolhelper((volumeParam *) pb, async, Cx(pb->ioWDDirID), FALSE);
}
PUBLIC OSErr hfsPBFlushVol(ParmBlkPtr pb, BOOLEAN async)
{
VCB *vcbp;
OSErr err;
vcbp = ROMlib_findvcb(Cx(pb->volumeParam.ioVRefNum),
MR(pb->volumeParam.ioNamePtr), (LONGINT *) 0, TRUE);
if (vcbp)
err = ROMlib_flushvcbp(vcbp);
else
err = nsvErr;
PBRETURN((volumeParam *) pb, err);
}
PRIVATE void closeallvcbfiles(HVCB *vcbp)
{
filecontrolblock *fcbp, *efcbp;
ioParam iopb;
short length;
length = CW(*(short *)MR(FCBSPtr));
fcbp = (filecontrolblock *) ((short *)MR(FCBSPtr)+1);
efcbp = (filecontrolblock *) ((char *)MR(FCBSPtr) + length);
for (;fcbp < efcbp; fcbp = (filecontrolblock *) ((char *)fcbp + Cx(FSFCBLen)))
if (fcbp->fcbFlNum && MR(fcbp->fcbVPtr) == vcbp) {
iopb.ioRefNum = CW((char *) fcbp - (char *) MR(FCBSPtr));
/* my */PBFlushFile((ParmBlkPtr) &iopb, FALSE);
}
}
PUBLIC OSErr hfsPBUnmountVol(ParmBlkPtr pb)
{
OSErr err;
HVCB *vcbp;
vcbp = ROMlib_findvcb(Cx(pb->volumeParam.ioVRefNum),
MR(pb->volumeParam.ioNamePtr), (LONGINT *) 0, FALSE);
if (vcbp) {
closeallvcbfiles(vcbp);
err = ROMlib_flushvcbp(vcbp);
Dequeue((QElemPtr) vcbp, &VCBQHdr);
DisposPtr(MR(vcbp->vcbMAdr));
DisposPtr(MR(vcbp->vcbBufAdr));
DisposPtr(MR(vcbp->vcbCtlBuf));
DisposPtr((Ptr) vcbp);
} else
err = nsvErr;
PBRETURN((volumeParam *) pb, err);
}
PRIVATE OSErr offlinehelper(volumeParam *pb, HVCB *vcbp)
{
OSErr err, err1, err2;
ioParam iop;
err = /* my */PBFlushVol((ParmBlkPtr) pb, FALSE);
err1 = 0;
err2 = 0;
if (err == noErr) {
if (vcbp) {
iop.ioRefNum = vcbp->vcbXTRef;
err1 = PBClose((ParmBlkPtr) &iop, FALSE);
iop.ioRefNum = vcbp->vcbCTRef;
err2 = PBClose((ParmBlkPtr) &iop, FALSE);
#if 1
DisposPtr(MR(vcbp->vcbMAdr));
vcbp->vcbMAdr = 0;
DisposPtr(MR(vcbp->vcbBufAdr));
vcbp->vcbBufAdr = 0;
DisposPtr(MR(vcbp->vcbCtlBuf));
vcbp->vcbCtlBuf = 0;
#endif
vcbp->vcbDrvNum = 0;
/* TODO: look for offline flags in mpw equate files and set them */
} else
err = nsvErr;
}
#if !defined(MAC)
#if 0
if (err == noErr)
err = updatefloppy();
#endif
#endif
if (err == noErr)
err = err1;
if (err == noErr)
err = err2;
return err;
}
PUBLIC OSErr hfsPBOffLine(ParmBlkPtr pb)
{
OSErr err;
HVCB *vcbp;
vcbp = ROMlib_findvcb(Cx(pb->volumeParam.ioVRefNum),
MR(pb->volumeParam.ioNamePtr), (LONGINT *) 0, FALSE);
if (vcbp) {
if (vcbp->vcbDrvNum) {
vcbp->vcbDRefNum = CW(-Cx(vcbp->vcbDrvNum));
err = offlinehelper((volumeParam *) pb, vcbp);
} else
err = noErr;
} else
err = nsvErr;
PBRETURN((volumeParam *) pb, err);
}
PUBLIC OSErr hfsPBEject(ParmBlkPtr pb)
{
OSErr err;
HVCB *vcbp;
INTEGER vref;
vref = Cx(pb->volumeParam.ioVRefNum);
vcbp = ROMlib_findvcb(vref,
MR(pb->volumeParam.ioNamePtr), (LONGINT *) 0, FALSE);
if (vcbp) {
if (Cx(vcbp->vcbDrvNum)) {
vcbp->vcbDRefNum = vcbp->vcbDrvNum;
err = offlinehelper((volumeParam *) pb, vcbp);
} else {
if (Cx(vcbp->vcbDRefNum) < 0) /* offline */
vcbp->vcbDRefNum = CW(Cx(vcbp->vcbDRefNum) * -1);
err = noErr;
}
} else
{
if (vref == 1 || vref == 2)
err = noErr; /* They're explicitly ejecting a particular drive */
else
err = nsvErr;
}
#if !defined(MAC)
if (err == noErr)
err = ROMlib_ejectfloppy(vcbp ? ((VCBExtra *) vcbp)->u.hfs.fd : -1);
#endif
PBRETURN((volumeParam *) pb, err);
}
PUBLIC OSErr ROMlib_pbvolrename(ioParam *pb, StringPtr newnamep)
{
OSErr err;
HParamBlockRec hpb;
Str255 name_copy;
str255assign (name_copy, MR (pb->ioNamePtr));
hpb.volumeParam.ioNamePtr = (StringPtr) CL ((long) name_copy);
hpb.volumeParam.ioVRefNum = pb->ioVRefNum;
hpb.volumeParam.ioVolIndex = CWC(-1);
err = /* my */PBHGetVInfo((HParmBlkPtr) &hpb, FALSE);
if (err == noErr) {
hpb.volumeParam.ioNamePtr = RM(newnamep);
err = /* my */PBSetVInfo((HParmBlkPtr) &hpb, FALSE);
}
return err;
}