--- a/platform/macclassic.c Fri Apr 05 09:02:57 2002 +0000
+++ b/platform/macclassic.c Fri Apr 05 09:04:34 2002 +0000
@@ -24,6 +24,7 @@
#include <Resources.h>
#include <MacMemory.h>
#include <Events.h>
+#include <DriverGestalt.h>
#endif
#define __PHYSICSFS_INTERNAL__
@@ -32,10 +33,21 @@
const char *__PHYSFS_platformDirSeparator = ":";
+static struct ProcessInfoRec procInfo;
+static FSSpec procfsspec;
int __PHYSFS_platformInit(void)
{
- return(1); /* always succeeds. */
+ OSErr err;
+ ProcessSerialNumber psn;
+ BAIL_IF_MACRO(GetCurrentProcess(&psn) != noErr, ERR_OS_ERROR, 0);
+ memset(&procInfo, '\0', sizeof (ProcessInfoRec));
+ memset(&procfsspec, '\0', sizeof (FSSpec));
+ procInfo.processInfoLength = sizeof (ProcessInfoRec);
+ procInfo.processAppSpec = &procfsspec;
+ err = GetProcessInformation(&psn, &procInfo);
+ BAIL_IF_MACRO(err != noErr, ERR_OS_ERROR, 0);
+ return(1); /* we're golden. */
} /* __PHYSFS_platformInit */
@@ -45,9 +57,62 @@
} /* __PHYSFS_platformDeinit */
+/*
+ * CD detection code is borrowed from Apple Technical Q&A DV18.
+ * http://developer.apple.com/qa/dv/dv18.html
+ */
char **__PHYSFS_platformDetectAvailableCDs(void)
{
- BAIL_MACRO(ERR_NOT_IMPLEMENTED, NULL);
+ DriverGestaltParam pb;
+ DrvQEl *dqp;
+ OSErr status;
+ char **retval = (char **) malloc(sizeof (char *));
+ int cd_count = 1;
+
+ BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
+
+ *retval = NULL;
+
+ pb.csCode = kDriverGestaltCode;
+ pb.driverGestaltSelector = kdgDeviceType;
+ dqp = (DrvQEl *) GetDrvQHdr()->qHead;
+
+ while (dqp != NULL)
+ {
+ pb.ioCRefNum = dqp->dQRefNum;
+ pb.ioVRefNum = dqp->dQDrive;
+ status = PBStatusSync((ParmBlkPtr) &pb);
+ if ((status == noErr) && (pb.driverGestaltResponse == kdgCDType))
+ {
+ Str63 volName;
+ HParamBlockRec hpbr;
+ memset(&hpbr, '\0', sizeof (HParamBlockRec));
+ hpbr.volumeParam.ioNamePtr = volName;
+ hpbr.volumeParam.ioVRefNum = dqp->dQDrive;
+ hpbr.volumeParam.ioVolIndex = 0;
+ if (PBHGetVInfoSync(&hpbr) == noErr)
+ {
+ char **tmp = realloc(retval, sizeof (char *) * cd_count + 1);
+ if (tmp)
+ {
+ char *str = (char *) malloc(volName[0] + 1);
+ retval = tmp;
+ if (str != NULL)
+ {
+ memcpy(str, &volName[1], volName[0]);
+ str[volName[0]] = '\0';
+ retval[cd_count-1] = str;
+ cd_count++;
+ } /* if */
+ } /* if */
+ } /* if */
+ } /* if */
+
+ dqp = (DrvQEl *) dqp->qLink;
+ } /* while */
+
+ retval[cd_count - 1] = NULL;
+ return(retval);
} /* __PHYSFS_platformDetectAvailableCDs */
@@ -56,27 +121,17 @@
char *ptr;
char *retval = NULL;
UInt32 retLength = 0;
- ProcessSerialNumber psn;
- struct ProcessInfoRec procInfo;
+ CInfoPBRec infoPB;
+ Str255 str255;
FSSpec spec;
- CInfoPBRec infoPB;
- OSErr err;
- Str255 str255;
- /* Get the FSSpecPtr of the current process's binary... */
- BAIL_IF_MACRO(GetCurrentProcess(&psn) != noErr, ERR_OS_ERROR, NULL);
- memset(&procInfo, '\0', sizeof (procInfo));
- procInfo.processInfoLength = sizeof (procInfo);
- procInfo.processAppSpec = &spec;
- err = GetProcessInformation(&psn, &procInfo);
- BAIL_IF_MACRO(err != noErr, ERR_OS_ERROR, NULL);
-
/* Get the name of the binary's parent directory. */
+ memcpy(&spec, &procfsspec, sizeof (FSSpec));
memset(&infoPB, '\0', sizeof (CInfoPBRec));
- infoPB.dirInfo.ioNamePtr = str255; /* put name in here. */
- infoPB.dirInfo.ioVRefNum = spec.vRefNum; /* ID of bin's volume. */
- infoPB.dirInfo.ioDrParID = spec.parID; /* ID of bin's dir. */
- infoPB.dirInfo.ioFDirIndex = -1; /* get dir (not file) info. */
+ infoPB.dirInfo.ioNamePtr = str255; /* put name in here. */
+ infoPB.dirInfo.ioVRefNum = spec.vRefNum; /* ID of bin's volume. */
+ infoPB.dirInfo.ioDrParID = spec.parID; /* ID of bin's dir. */
+ infoPB.dirInfo.ioFDirIndex = -1; /* get dir (not file) info. */
/* walk the tree back to the root dir (volume), building path string... */
do
@@ -167,14 +222,20 @@
{
OSErr err;
Str255 str255;
- int len = strlen(fname);
+ int needColon = (strchr(fname, ':') == NULL);
+ int len = strlen(fname) + ((needColon) ? 1 : 0);
if (len > 255)
return(bdNamErr);
/* !!! FIXME: What happens with relative pathnames? */
- str255[0] = strlen(fname);
- memcpy(&str255[1], fname, str255[0]);
+ str255[0] = len;
+ memcpy(&str255[1], fname, len);
+
+ /* probably just a volume name, which seems to need a ':' at the end. */
+ if (needColon)
+ str255[len] = ':';
+
err = FSMakeFSSpec(0, 0, str255, spec);
return(err);
} /* fnameToFSSpec */
@@ -206,7 +267,7 @@
infoPB.dirInfo.ioDrDirID = spec.parID; /* ID of bin's dir. */
infoPB.dirInfo.ioFDirIndex = 0; /* file (not parent) info. */
err = PBGetCatInfoSync(&infoPB);
- BAIL_IF_MACRO((err != noErr) && (err != fnfErr), ERR_OS_ERROR, 0);
+ BAIL_IF_MACRO(err != noErr, ERR_OS_ERROR, 0);
return((infoPB.dirInfo.ioFlAttrib & kioFlAttribDirMask) != 0);
} /* __PHYSFS_platformIsDirectory */
@@ -254,23 +315,39 @@
LinkedStringList *retval = NULL;
LinkedStringList *l = NULL;
LinkedStringList *prev = NULL;
- UInt16 i = 0;
+ UInt16 i;
+ UInt16 max;
FSSpec spec;
CInfoPBRec infoPB;
Str255 str255;
+ long dirID;
BAIL_IF_MACRO(fnameToFSSpec(dirname, &spec) != noErr, ERR_OS_ERROR, 0);
- while (1)
+ /* get the dir ID of what we want to enumerate... */
+ memset(&infoPB, '\0', sizeof (CInfoPBRec));
+ infoPB.dirInfo.ioNamePtr = spec.name; /* name of dir to enum. */
+ infoPB.dirInfo.ioVRefNum = spec.vRefNum; /* ID of file's volume. */
+ infoPB.dirInfo.ioDrDirID = spec.parID; /* ID of dir. */
+ infoPB.dirInfo.ioFDirIndex = 0; /* file (not parent) info. */
+ BAIL_IF_MACRO(PBGetCatInfoSync(&infoPB) != noErr, ERR_OS_ERROR, NULL);
+
+ if ((infoPB.dirInfo.ioFlAttrib & kioFlAttribDirMask) == 0)
+ BAIL_MACRO(ERR_NOT_A_DIR, NULL);
+
+ dirID = infoPB.dirInfo.ioDrDirID;
+ max = infoPB.dirInfo.ioDrNmFls;
+
+ for (i = 1; i <= max; i++)
{
memset(&infoPB, '\0', sizeof (CInfoPBRec));
str255[0] = 0;
- infoPB.dirInfo.ioNamePtr = str255; /* store name in here. */
- infoPB.dirInfo.ioVRefNum = spec.vRefNum; /* ID of file's volume. */
- infoPB.dirInfo.ioDrDirID = spec.parID; /* ID of bin's dir. */
- infoPB.dirInfo.ioFDirIndex = ++i; /* file (not parent) info. */
+ infoPB.dirInfo.ioNamePtr = str255; /* store name in here. */
+ infoPB.dirInfo.ioVRefNum = spec.vRefNum; /* ID of dir's volume. */
+ infoPB.dirInfo.ioDrDirID = dirID; /* ID of dir. */
+ infoPB.dirInfo.ioFDirIndex = i; /* next file's info. */
if (PBGetCatInfoSync(&infoPB) != noErr)
- break;
+ continue; /* skip this file. Oh well. */
l = (LinkedStringList *) malloc(sizeof (LinkedStringList));
if (l == NULL)
@@ -293,7 +370,7 @@
prev = l;
l->next = NULL;
- } /* while */
+ } /* for */
return(retval);
} /* __PHYSFS_platformEnumerateFiles */
@@ -322,81 +399,221 @@
int __PHYSFS_platformMkDir(const char *path)
{
- BAIL_MACRO(ERR_NOT_IMPLEMENTED, 0);
+ SInt32 val = 0;
+ FSSpec spec;
+ OSErr err = fnameToFSSpec(path, &spec);
+
+ BAIL_IF_MACRO(err == noErr, ERR_FILE_EXISTS, 0);
+ BAIL_IF_MACRO(err != fnfErr, ERR_OS_ERROR, 0);
+
+ err = DirCreate(spec.vRefNum, spec.parID, spec.name, &val);
+ BAIL_IF_MACRO(err != noErr, ERR_OS_ERROR, 0);
+ return(1);
} /* __PHYSFS_platformMkDir */
+static SInt16 *macDoOpen(const char *fname, SInt8 perm, int createIfMissing)
+{
+ int created = 0;
+ SInt16 *retval = NULL;
+ FSSpec spec;
+ OSErr err = fnameToFSSpec(fname, &spec);
+ BAIL_IF_MACRO((err != noErr) && (err != fnfErr), ERR_OS_ERROR, NULL);
+ if (err == fnfErr)
+ {
+ BAIL_IF_MACRO(!createIfMissing, ERR_FILE_NOT_FOUND, NULL);
+ err = HCreate(spec.vRefNum, spec.parID, spec.name,
+ procInfo.processSignature, 'BINA');
+ BAIL_IF_MACRO(err != noErr, ERR_OS_ERROR, NULL);
+ created = 1;
+ } /* if */
+
+ retval = (SInt16 *) malloc(sizeof (SInt16));
+ if (retval == NULL)
+ {
+ if (created)
+ HDelete(spec.vRefNum, spec.parID, spec.name);
+ BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
+ } /* if */
+
+ if (HOpenDF(spec.vRefNum, spec.parID, spec.name, perm, retval) != noErr)
+ {
+ free(retval);
+ if (created)
+ HDelete(spec.vRefNum, spec.parID, spec.name);
+ BAIL_MACRO(ERR_OS_ERROR, NULL);
+ } /* if */
+
+ return(retval);
+} /* macDoOpen */
+
+
void *__PHYSFS_platformOpenRead(const char *filename)
{
- BAIL_MACRO(ERR_NOT_IMPLEMENTED, NULL);
+ SInt16 *retval = macDoOpen(filename, fsRdPerm, 0);
+ if (retval != NULL) /* got a file; seek to start. */
+ {
+ if (SetFPos(*retval, fsFromStart, 0) != noErr)
+ {
+ FSClose(*retval);
+ BAIL_MACRO(ERR_OS_ERROR, NULL);
+ } /* if */
+ } /* if */
+
+ return((void *) retval);
} /* __PHYSFS_platformOpenRead */
void *__PHYSFS_platformOpenWrite(const char *filename)
{
- BAIL_MACRO(ERR_NOT_IMPLEMENTED, NULL);
+ SInt16 *retval = macDoOpen(filename, fsRdWrPerm, 1);
+ if (retval != NULL) /* got a file; truncate it. */
+ {
+ if ((SetEOF(*retval, 0) != noErr) ||
+ (SetFPos(*retval, fsFromStart, 0) != noErr))
+ {
+ FSClose(*retval);
+ BAIL_MACRO(ERR_OS_ERROR, NULL);
+ } /* if */
+ } /* if */
+
+ return((void *) retval);
} /* __PHYSFS_platformOpenWrite */
void *__PHYSFS_platformOpenAppend(const char *filename)
{
- BAIL_MACRO(ERR_NOT_IMPLEMENTED, NULL);
+ SInt16 *retval = macDoOpen(filename, fsRdWrPerm, 1);
+ if (retval != NULL) /* got a file; seek to end. */
+ {
+ if (SetFPos(*retval, fsFromLEOF, 0) != noErr)
+ {
+ FSClose(*retval);
+ BAIL_MACRO(ERR_OS_ERROR, NULL);
+ } /* if */
+ } /* if */
+
+ return(retval);
} /* __PHYSFS_platformOpenAppend */
PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buffer,
PHYSFS_uint32 size, PHYSFS_uint32 count)
{
- BAIL_MACRO(ERR_NOT_IMPLEMENTED, -1);
+ SInt16 ref = *((SInt16 *) opaque);
+ SInt32 br;
+ PHYSFS_uint32 i;
+
+ for (i = 0; i < count; i++)
+ {
+ br = size;
+ BAIL_IF_MACRO(FSRead(ref, &br, buffer) != noErr, ERR_OS_ERROR, i);
+ BAIL_IF_MACRO(br != size, ERR_OS_ERROR, i);
+ buffer = ((PHYSFS_uint8 *) buffer) + size;
+ } /* for */
+
+ return(count);
} /* __PHYSFS_platformRead */
PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer,
PHYSFS_uint32 size, PHYSFS_uint32 count)
{
- BAIL_MACRO(ERR_NOT_IMPLEMENTED, -1);
+ SInt16 ref = *((SInt16 *) opaque);
+ SInt32 bw;
+ PHYSFS_uint32 i;
+
+ for (i = 0; i < count; i++)
+ {
+ bw = size;
+ BAIL_IF_MACRO(FSWrite(ref, &bw, buffer) != noErr, ERR_OS_ERROR, i);
+ BAIL_IF_MACRO(bw != size, ERR_OS_ERROR, i);
+ buffer = ((PHYSFS_uint8 *) buffer) + size;
+ } /* for */
+
+ return(count);
} /* __PHYSFS_platformWrite */
int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos)
{
- BAIL_MACRO(ERR_NOT_IMPLEMENTED, -1);
+ SInt16 ref = *((SInt16 *) opaque);
+ OSErr err = SetFPos(ref, fsFromStart, (SInt32) pos);
+ BAIL_IF_MACRO(err != noErr, ERR_OS_ERROR, 0);
+ return(1);
} /* __PHYSFS_platformSeek */
PHYSFS_sint64 __PHYSFS_platformTell(void *opaque)
{
- BAIL_MACRO(ERR_NOT_IMPLEMENTED, -1);
+ SInt16 ref = *((SInt16 *) opaque);
+ SInt32 curPos;
+ BAIL_IF_MACRO(GetFPos(ref, &curPos) != noErr, ERR_OS_ERROR, -1);
+ return((PHYSFS_sint64) curPos);
} /* __PHYSFS_platformTell */
PHYSFS_sint64 __PHYSFS_platformFileLength(void *opaque)
{
- BAIL_MACRO(ERR_NOT_IMPLEMENTED, -1);
+ SInt16 ref = *((SInt16 *) opaque);
+ SInt32 eofPos;
+ BAIL_IF_MACRO(GetEOF(ref, &eofPos) != noErr, ERR_OS_ERROR, -1);
+ return((PHYSFS_sint64) eofPos);
} /* __PHYSFS_platformFileLength */
int __PHYSFS_platformEOF(void *opaque)
{
- BAIL_MACRO(ERR_NOT_IMPLEMENTED, -1);
+ SInt16 ref = *((SInt16 *) opaque);
+ SInt32 eofPos, curPos;
+ BAIL_IF_MACRO(GetEOF(ref, &eofPos) != noErr, ERR_OS_ERROR, 1);
+ BAIL_IF_MACRO(GetFPos(ref, &curPos) != noErr, ERR_OS_ERROR, 1);
+ return(curPos >= eofPos);
} /* __PHYSFS_platformEOF */
int __PHYSFS_platformFlush(void *opaque)
{
- BAIL_MACRO(ERR_NOT_IMPLEMENTED, 0);
+ SInt16 ref = *((SInt16 *) opaque);
+ ParamBlockRec pb;
+ memset(&pb, '\0', sizeof (ParamBlockRec));
+ pb.ioParam.ioRefNum = ref;
+ BAIL_IF_MACRO(PBFlushFileSync(&pb) != noErr, ERR_OS_ERROR, 0);
+ return(1);
} /* __PHYSFS_platformFlush */
int __PHYSFS_platformClose(void *opaque)
{
- BAIL_MACRO(ERR_NOT_IMPLEMENTED, 0);
+ SInt16 ref = *((SInt16 *) opaque);
+ SInt16 vRefNum;
+ HParamBlockRec hpbr;
+ Str63 volName;
+
+ BAIL_IF_MACRO(GetVRefNum (ref, &vRefNum) != noErr, ERR_OS_ERROR, 0);
+
+ memset(&hpbr, '\0', sizeof (HParamBlockRec));
+ hpbr.volumeParam.ioNamePtr = volName;
+ hpbr.volumeParam.ioVRefNum = vRefNum;
+ hpbr.volumeParam.ioVolIndex = 0;
+ BAIL_IF_MACRO(PBHGetVInfoSync(&hpbr) != noErr, ERR_OS_ERROR, 0);
+
+ BAIL_IF_MACRO(FSClose(ref) != noErr, ERR_OS_ERROR, 0);
+ free(opaque);
+
+ FlushVol(volName, vRefNum);
+ return(1);
} /* __PHYSFS_platformClose */
int __PHYSFS_platformDelete(const char *path)
{
- BAIL_MACRO(ERR_NOT_IMPLEMENTED, 0);
+ FSSpec spec;
+ OSErr err;
+ BAIL_IF_MACRO(fnameToFSSpec(path, &spec) != noErr, ERR_OS_ERROR, 0);
+ err = HDelete(spec.vRefNum, spec.parID, spec.name);
+ BAIL_IF_MACRO(err != noErr, ERR_OS_ERROR, 0);
+ return(1);
} /* __PHYSFS_platformDelete */
@@ -423,5 +640,5 @@
/* no mutexes on MacOS Classic. */
} /* __PHYSFS_platformReleaseMutex */
-/* end of unix.c ... */
+/* end of macclassic.c ... */