From b0637e0182683a939377b25c082c8f9bc02fa31f Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 5 Apr 2002 09:04:34 +0000 Subject: [PATCH] Mostly implemented (fully implemented if you don't want aliases to work like symlinks). --- platform/macclassic.c | 305 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 261 insertions(+), 44 deletions(-) diff --git a/platform/macclassic.c b/platform/macclassic.c index 517c5a9..2a7d0a2 100644 --- a/platform/macclassic.c +++ b/platform/macclassic.c @@ -24,6 +24,7 @@ #include #include #include +#include #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 @@ int __PHYSFS_platformDeinit(void) } /* __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 *__PHYSFS_platformCalcBaseDir(const char *argv0) char *ptr; char *retval = NULL; UInt32 retLength = 0; - ProcessSerialNumber psn; - struct ProcessInfoRec procInfo; - FSSpec spec; CInfoPBRec infoPB; - OSErr err; Str255 str255; + FSSpec spec; - /* 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 @@ static OSErr fnameToFSSpec(const char *fname, FSSpec *spec) { 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 @@ int __PHYSFS_platformIsDirectory(const char *fname) 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 *__PHYSFS_platformEnumerateFiles(const char *dirname, 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 @@ LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname, prev = l; l->next = NULL; - } /* while */ + } /* for */ return(retval); } /* __PHYSFS_platformEnumerateFiles */ @@ -322,81 +399,221 @@ char *__PHYSFS_platformRealPath(const char *path) 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 @@ void __PHYSFS_platformReleaseMutex(void *mutex) /* no mutexes on MacOS Classic. */ } /* __PHYSFS_platformReleaseMutex */ -/* end of unix.c ... */ +/* end of macclassic.c ... */