2002-04-02 15:43:29 +02:00
|
|
|
/*
|
|
|
|
* MacOS Classic support routines for PhysicsFS.
|
|
|
|
*
|
|
|
|
* Please see the file LICENSE in the source's root directory.
|
|
|
|
*
|
|
|
|
* This file written by Ryan C. Gordon.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Please note that I haven't tried this code with CarbonLib or under
|
|
|
|
* MacOS X at all. The code in unix.c is known to work with Darwin,
|
|
|
|
* and you may or may not be better off using that.
|
|
|
|
*/
|
|
|
|
#ifdef __PHYSFS_CARBONIZED__
|
|
|
|
#include <Carbon.h>
|
|
|
|
#else
|
|
|
|
#include <OSUtils.h>
|
|
|
|
#include <Processes.h>
|
|
|
|
#include <Files.h>
|
2002-04-02 16:33:08 +02:00
|
|
|
#include <TextUtils.h>
|
|
|
|
#include <Resources.h>
|
|
|
|
#include <MacMemory.h>
|
2002-04-03 09:38:10 +02:00
|
|
|
#include <Events.h>
|
2002-04-02 15:43:29 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#define __PHYSICSFS_INTERNAL__
|
|
|
|
#include "physfs_internal.h"
|
|
|
|
|
|
|
|
|
|
|
|
const char *__PHYSFS_platformDirSeparator = ":";
|
|
|
|
|
|
|
|
|
|
|
|
int __PHYSFS_platformInit(void)
|
|
|
|
{
|
|
|
|
return(1); /* always succeeds. */
|
|
|
|
} /* __PHYSFS_platformInit */
|
|
|
|
|
|
|
|
|
|
|
|
int __PHYSFS_platformDeinit(void)
|
|
|
|
{
|
|
|
|
return(1); /* always succeed. */
|
|
|
|
} /* __PHYSFS_platformDeinit */
|
|
|
|
|
|
|
|
|
|
|
|
char **__PHYSFS_platformDetectAvailableCDs(void)
|
|
|
|
{
|
|
|
|
BAIL_MACRO(ERR_NOT_IMPLEMENTED, NULL);
|
|
|
|
} /* __PHYSFS_platformDetectAvailableCDs */
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
/* 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. */
|
|
|
|
memset(&infoPB, '\0', sizeof (CInfoPBRec));
|
2002-04-04 19:56:20 +02:00
|
|
|
infoPB.dirInfo.ioNamePtr = str255; /* put name in here. */
|
2002-04-02 15:43:29 +02:00
|
|
|
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
|
|
|
|
{
|
|
|
|
/* check parent dir of what we last looked at... */
|
|
|
|
infoPB.dirInfo.ioDrDirID = infoPB.dirInfo.ioDrParID;
|
2002-04-04 19:56:20 +02:00
|
|
|
if (PBGetCatInfoSync(&infoPB) != noErr)
|
2002-04-02 15:43:29 +02:00
|
|
|
{
|
|
|
|
if (retval != NULL)
|
|
|
|
free(retval);
|
|
|
|
BAIL_MACRO(ERR_OS_ERROR, NULL);
|
|
|
|
} /* if */
|
|
|
|
|
|
|
|
/* allocate more space for the retval... */
|
|
|
|
retLength += str255[0] + 1; /* + 1 for a ':' or null char... */
|
|
|
|
ptr = (char *) malloc(retLength);
|
|
|
|
if (ptr == NULL)
|
|
|
|
{
|
|
|
|
if (retval != NULL)
|
|
|
|
free(retval);
|
|
|
|
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
|
|
|
|
} /* if */
|
|
|
|
|
|
|
|
/* prepend new dir to retval and cleanup... */
|
|
|
|
memcpy(ptr, &str255[1], str255[0]);
|
|
|
|
ptr[str255[0]] = '\0'; /* null terminate it. */
|
|
|
|
if (retval != NULL)
|
|
|
|
{
|
|
|
|
strcat(ptr, ":");
|
|
|
|
strcat(ptr, retval);
|
|
|
|
free(retval);
|
|
|
|
} /* if */
|
|
|
|
retval = ptr;
|
|
|
|
} while (infoPB.dirInfo.ioDrDirID != fsRtDirID);
|
|
|
|
|
|
|
|
return(retval);
|
|
|
|
} /* __PHYSFS_platformCalcBaseDir */
|
|
|
|
|
|
|
|
|
|
|
|
char *__PHYSFS_platformGetUserName(void)
|
|
|
|
{
|
|
|
|
char *retval = NULL;
|
2002-04-02 16:33:08 +02:00
|
|
|
StringHandle strHandle;
|
|
|
|
short origResourceFile = CurResFile();
|
|
|
|
|
|
|
|
/* use the System resource file. */
|
|
|
|
UseResFile(0);
|
|
|
|
/* apparently, -16096 specifies the username. */
|
|
|
|
strHandle = GetString(-16096);
|
|
|
|
UseResFile(origResourceFile);
|
|
|
|
BAIL_IF_MACRO(strHandle == NULL, ERR_OS_ERROR, NULL);
|
|
|
|
|
|
|
|
HLock((Handle) strHandle);
|
|
|
|
retval = (char *) malloc((*strHandle)[0] + 1);
|
|
|
|
if (retval == NULL)
|
|
|
|
{
|
|
|
|
HUnlock((Handle) strHandle);
|
|
|
|
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
|
|
|
|
} /* if */
|
|
|
|
memcpy(retval, &(*strHandle)[1], (*strHandle)[0]);
|
|
|
|
retval[(*strHandle)[0]] = '\0'; /* null-terminate it. */
|
|
|
|
HUnlock((Handle) strHandle);
|
|
|
|
|
2002-04-02 15:43:29 +02:00
|
|
|
return(retval);
|
|
|
|
} /* __PHYSFS_platformGetUserName */
|
|
|
|
|
|
|
|
|
|
|
|
char *__PHYSFS_platformGetUserDir(void)
|
|
|
|
{
|
|
|
|
return(NULL); /* bah...use default behaviour, I guess. */
|
|
|
|
} /* __PHYSFS_platformGetUserDir */
|
|
|
|
|
|
|
|
|
|
|
|
PHYSFS_uint64 __PHYSFS_platformGetThreadID(void)
|
|
|
|
{
|
|
|
|
return(1); /* single threaded. */
|
|
|
|
} /* __PHYSFS_platformGetThreadID */
|
|
|
|
|
|
|
|
|
|
|
|
int __PHYSFS_platformStricmp(const char *x, const char *y)
|
|
|
|
{
|
|
|
|
extern int _stricmp(const char *, const char *);
|
|
|
|
return(_stricmp(x, y)); /* (*shrug*) */
|
|
|
|
} /* __PHYSFS_platformStricmp */
|
|
|
|
|
|
|
|
|
2002-04-04 19:56:20 +02:00
|
|
|
static OSErr fnameToFSSpec(const char *fname, FSSpec *spec)
|
|
|
|
{
|
2002-04-04 21:35:59 +02:00
|
|
|
OSErr err;
|
2002-04-04 19:56:20 +02:00
|
|
|
Str255 str255;
|
|
|
|
int len = strlen(fname);
|
|
|
|
if (len > 255)
|
|
|
|
return(bdNamErr);
|
|
|
|
|
|
|
|
/* !!! FIXME: What happens with relative pathnames? */
|
|
|
|
|
|
|
|
str255[0] = strlen(fname);
|
|
|
|
memcpy(&str255[1], fname, str255[0]);
|
2002-04-04 21:35:59 +02:00
|
|
|
err = FSMakeFSSpec(0, 0, str255, spec);
|
|
|
|
return(err);
|
2002-04-04 19:56:20 +02:00
|
|
|
} /* fnameToFSSpec */
|
|
|
|
|
|
|
|
|
2002-04-02 15:43:29 +02:00
|
|
|
int __PHYSFS_platformExists(const char *fname)
|
|
|
|
{
|
2002-04-04 19:56:20 +02:00
|
|
|
FSSpec spec;
|
|
|
|
return(fnameToFSSpec(fname, &spec) == noErr);
|
2002-04-02 15:43:29 +02:00
|
|
|
} /* __PHYSFS_platformExists */
|
|
|
|
|
|
|
|
|
|
|
|
int __PHYSFS_platformIsSymLink(const char *fname)
|
|
|
|
{
|
|
|
|
return(0); /* !!! FIXME: What happens if (fname) is an alias? */
|
|
|
|
} /* __PHYSFS_platformIsSymlink */
|
|
|
|
|
|
|
|
|
|
|
|
int __PHYSFS_platformIsDirectory(const char *fname)
|
|
|
|
{
|
2002-04-04 19:56:20 +02:00
|
|
|
FSSpec spec;
|
|
|
|
CInfoPBRec infoPB;
|
2002-04-04 21:35:59 +02:00
|
|
|
OSErr err;
|
2002-04-04 19:56:20 +02:00
|
|
|
|
|
|
|
BAIL_IF_MACRO(fnameToFSSpec(fname, &spec) != noErr, ERR_OS_ERROR, 0);
|
|
|
|
memset(&infoPB, '\0', sizeof (CInfoPBRec));
|
|
|
|
infoPB.dirInfo.ioNamePtr = spec.name; /* put name in here. */
|
|
|
|
infoPB.dirInfo.ioVRefNum = spec.vRefNum; /* ID of file's volume. */
|
2002-04-04 21:35:59 +02:00
|
|
|
infoPB.dirInfo.ioDrDirID = spec.parID; /* ID of bin's dir. */
|
2002-04-04 19:56:20 +02:00
|
|
|
infoPB.dirInfo.ioFDirIndex = 0; /* file (not parent) info. */
|
2002-04-04 21:35:59 +02:00
|
|
|
err = PBGetCatInfoSync(&infoPB);
|
|
|
|
BAIL_IF_MACRO((err != noErr) && (err != fnfErr), ERR_OS_ERROR, 0);
|
2002-04-04 19:56:20 +02:00
|
|
|
return((infoPB.dirInfo.ioFlAttrib & kioFlAttribDirMask) != 0);
|
2002-04-02 15:43:29 +02:00
|
|
|
} /* __PHYSFS_platformIsDirectory */
|
|
|
|
|
|
|
|
|
|
|
|
char *__PHYSFS_platformCvtToDependent(const char *prepend,
|
|
|
|
const char *dirName,
|
|
|
|
const char *append)
|
|
|
|
{
|
2002-04-03 09:38:10 +02:00
|
|
|
int len = ((prepend) ? strlen(prepend) : 0) +
|
|
|
|
((append) ? strlen(append) : 0) +
|
|
|
|
strlen(dirName) + 1;
|
|
|
|
const char *src;
|
|
|
|
char *dst;
|
|
|
|
char *retval = malloc(len);
|
|
|
|
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
|
|
|
|
|
|
|
|
if (prepend != NULL)
|
|
|
|
{
|
|
|
|
strcpy(retval, prepend);
|
|
|
|
dst = retval + strlen(retval);
|
|
|
|
} /* if */
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*retval = '\0';
|
|
|
|
dst = retval;
|
|
|
|
} /* else */
|
|
|
|
|
|
|
|
for (src = dirName; *src; src++, dst++)
|
|
|
|
*dst = ((*src == '/') ? ':' : *src);
|
|
|
|
|
|
|
|
*dst = '\0';
|
|
|
|
return(retval);
|
2002-04-02 15:43:29 +02:00
|
|
|
} /* __PHYSFS_platformCvtToDependent */
|
|
|
|
|
|
|
|
|
|
|
|
void __PHYSFS_platformTimeslice(void)
|
|
|
|
{
|
2002-04-03 09:38:10 +02:00
|
|
|
SystemTask();
|
2002-04-02 15:43:29 +02:00
|
|
|
} /* __PHYSFS_platformTimeslice */
|
|
|
|
|
|
|
|
|
|
|
|
LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname,
|
|
|
|
int omitSymLinks)
|
|
|
|
{
|
2002-04-04 19:56:20 +02:00
|
|
|
LinkedStringList *retval = NULL;
|
|
|
|
LinkedStringList *l = NULL;
|
|
|
|
LinkedStringList *prev = NULL;
|
|
|
|
UInt16 i = 0;
|
|
|
|
FSSpec spec;
|
|
|
|
CInfoPBRec infoPB;
|
|
|
|
Str255 str255;
|
|
|
|
|
|
|
|
BAIL_IF_MACRO(fnameToFSSpec(dirname, &spec) != noErr, ERR_OS_ERROR, 0);
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
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. */
|
2002-04-04 21:35:59 +02:00
|
|
|
infoPB.dirInfo.ioDrDirID = spec.parID; /* ID of bin's dir. */
|
2002-04-04 19:56:20 +02:00
|
|
|
infoPB.dirInfo.ioFDirIndex = ++i; /* file (not parent) info. */
|
|
|
|
if (PBGetCatInfoSync(&infoPB) != noErr)
|
|
|
|
break;
|
|
|
|
|
|
|
|
l = (LinkedStringList *) malloc(sizeof (LinkedStringList));
|
|
|
|
if (l == NULL)
|
|
|
|
break;
|
|
|
|
|
|
|
|
l->str = (char *) malloc(str255[0] + 1);
|
|
|
|
if (l->str == NULL)
|
|
|
|
{
|
|
|
|
free(l);
|
|
|
|
break;
|
|
|
|
} /* if */
|
|
|
|
|
|
|
|
memcpy(l->str, &str255[1], str255[0]);
|
|
|
|
l->str[str255[0]] = '\0';
|
|
|
|
|
|
|
|
if (retval == NULL)
|
|
|
|
retval = l;
|
|
|
|
else
|
|
|
|
prev->next = l;
|
|
|
|
|
|
|
|
prev = l;
|
|
|
|
l->next = NULL;
|
|
|
|
} /* while */
|
|
|
|
|
|
|
|
return(retval);
|
2002-04-02 15:43:29 +02:00
|
|
|
} /* __PHYSFS_platformEnumerateFiles */
|
|
|
|
|
|
|
|
|
|
|
|
char *__PHYSFS_platformCurrentDir(void)
|
|
|
|
{
|
2002-04-03 09:38:10 +02:00
|
|
|
/*
|
|
|
|
* I don't think MacOS has a concept of "current directory", beyond
|
|
|
|
* what is grafted on by a given standard C library implementation,
|
|
|
|
* so just return the base dir.
|
|
|
|
* We don't use this for anything crucial at the moment anyhow.
|
|
|
|
*/
|
|
|
|
return(__PHYSFS_platformCalcBaseDir(NULL));
|
2002-04-02 15:43:29 +02:00
|
|
|
} /* __PHYSFS_platformCurrentDir */
|
|
|
|
|
|
|
|
|
|
|
|
char *__PHYSFS_platformRealPath(const char *path)
|
|
|
|
{
|
|
|
|
/* !!! FIXME: This isn't nearly right. */
|
|
|
|
char *retval = (char *) malloc(strlen(path) + 1);
|
|
|
|
strcpy(retval, path);
|
|
|
|
return(retval);
|
|
|
|
} /* __PHYSFS_platformRealPath */
|
|
|
|
|
|
|
|
|
|
|
|
int __PHYSFS_platformMkDir(const char *path)
|
|
|
|
{
|
|
|
|
BAIL_MACRO(ERR_NOT_IMPLEMENTED, 0);
|
|
|
|
} /* __PHYSFS_platformMkDir */
|
|
|
|
|
|
|
|
|
|
|
|
void *__PHYSFS_platformOpenRead(const char *filename)
|
|
|
|
{
|
|
|
|
BAIL_MACRO(ERR_NOT_IMPLEMENTED, NULL);
|
|
|
|
} /* __PHYSFS_platformOpenRead */
|
|
|
|
|
|
|
|
|
|
|
|
void *__PHYSFS_platformOpenWrite(const char *filename)
|
|
|
|
{
|
|
|
|
BAIL_MACRO(ERR_NOT_IMPLEMENTED, NULL);
|
|
|
|
} /* __PHYSFS_platformOpenWrite */
|
|
|
|
|
|
|
|
|
|
|
|
void *__PHYSFS_platformOpenAppend(const char *filename)
|
|
|
|
{
|
|
|
|
BAIL_MACRO(ERR_NOT_IMPLEMENTED, NULL);
|
|
|
|
} /* __PHYSFS_platformOpenAppend */
|
|
|
|
|
|
|
|
|
|
|
|
PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buffer,
|
|
|
|
PHYSFS_uint32 size, PHYSFS_uint32 count)
|
|
|
|
{
|
|
|
|
BAIL_MACRO(ERR_NOT_IMPLEMENTED, -1);
|
|
|
|
} /* __PHYSFS_platformRead */
|
|
|
|
|
|
|
|
|
|
|
|
PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer,
|
|
|
|
PHYSFS_uint32 size, PHYSFS_uint32 count)
|
|
|
|
{
|
|
|
|
BAIL_MACRO(ERR_NOT_IMPLEMENTED, -1);
|
|
|
|
} /* __PHYSFS_platformWrite */
|
|
|
|
|
|
|
|
|
|
|
|
int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos)
|
|
|
|
{
|
|
|
|
BAIL_MACRO(ERR_NOT_IMPLEMENTED, -1);
|
|
|
|
} /* __PHYSFS_platformSeek */
|
|
|
|
|
|
|
|
|
|
|
|
PHYSFS_sint64 __PHYSFS_platformTell(void *opaque)
|
|
|
|
{
|
|
|
|
BAIL_MACRO(ERR_NOT_IMPLEMENTED, -1);
|
|
|
|
} /* __PHYSFS_platformTell */
|
|
|
|
|
|
|
|
|
|
|
|
PHYSFS_sint64 __PHYSFS_platformFileLength(void *opaque)
|
|
|
|
{
|
|
|
|
BAIL_MACRO(ERR_NOT_IMPLEMENTED, -1);
|
|
|
|
} /* __PHYSFS_platformFileLength */
|
|
|
|
|
|
|
|
|
|
|
|
int __PHYSFS_platformEOF(void *opaque)
|
|
|
|
{
|
|
|
|
BAIL_MACRO(ERR_NOT_IMPLEMENTED, -1);
|
|
|
|
} /* __PHYSFS_platformEOF */
|
|
|
|
|
|
|
|
|
|
|
|
int __PHYSFS_platformFlush(void *opaque)
|
|
|
|
{
|
|
|
|
BAIL_MACRO(ERR_NOT_IMPLEMENTED, 0);
|
|
|
|
} /* __PHYSFS_platformFlush */
|
|
|
|
|
|
|
|
|
|
|
|
int __PHYSFS_platformClose(void *opaque)
|
|
|
|
{
|
|
|
|
BAIL_MACRO(ERR_NOT_IMPLEMENTED, 0);
|
|
|
|
} /* __PHYSFS_platformClose */
|
|
|
|
|
|
|
|
|
|
|
|
int __PHYSFS_platformDelete(const char *path)
|
|
|
|
{
|
|
|
|
BAIL_MACRO(ERR_NOT_IMPLEMENTED, 0);
|
|
|
|
} /* __PHYSFS_platformDelete */
|
|
|
|
|
|
|
|
|
|
|
|
void *__PHYSFS_platformCreateMutex(void)
|
|
|
|
{
|
|
|
|
return((void *) 0x0001); /* no mutexes on MacOS Classic. */
|
|
|
|
} /* __PHYSFS_platformCreateMutex */
|
|
|
|
|
|
|
|
|
|
|
|
void __PHYSFS_platformDestroyMutex(void *mutex)
|
|
|
|
{
|
|
|
|
/* no mutexes on MacOS Classic. */
|
|
|
|
} /* __PHYSFS_platformDestroyMutex */
|
|
|
|
|
|
|
|
|
|
|
|
int __PHYSFS_platformGrabMutex(void *mutex)
|
|
|
|
{
|
|
|
|
return(1); /* no mutexes on MacOS Classic. */
|
|
|
|
} /* __PHYSFS_platformGrabMutex */
|
|
|
|
|
|
|
|
|
|
|
|
void __PHYSFS_platformReleaseMutex(void *mutex)
|
|
|
|
{
|
|
|
|
/* no mutexes on MacOS Classic. */
|
|
|
|
} /* __PHYSFS_platformReleaseMutex */
|
|
|
|
|
|
|
|
/* end of unix.c ... */
|
|
|
|
|