mirror of
https://github.com/ctm/executor.git
synced 2024-09-29 18:58:01 +00:00
1067 lines
27 KiB
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;
|
|
}
|