paragui-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[paragui-cvs] CVS: paragui/src/physfs/platform macclassic.c,NONE,1.1.2.1


From: Alexander Pipelka <address@hidden>
Subject: [paragui-cvs] CVS: paragui/src/physfs/platform macclassic.c,NONE,1.1.2.1 skeleton.c,NONE,1.1.2.1 unix_nocdrom.c,NONE,1.1.2.1 Makefile.am,1.1.1.1,1.1.1.1.6.1 unix.c,1.1.1.1,1.1.1.1.6.1 win32.c,1.1.1.1,1.1.1.1.6.1 darwin.c,1.1.1.1,NONE freebsd.c,1.1.1.1,NONE irix.c,1.1.1.1,NONE solaris.c,1.1.1.1,NONE
Date: Fri, 03 May 2002 06:15:36 -0400

Update of /cvsroot/paragui/paragui/src/physfs/platform
In directory subversions:/tmp/cvs-serv31128/src/physfs/platform

Modified Files:
      Tag: devel-1-0
        Makefile.am unix.c win32.c 
Added Files:
      Tag: devel-1-0
        macclassic.c skeleton.c unix_nocdrom.c 
Removed Files:
      Tag: devel-1-0
        darwin.c freebsd.c irix.c solaris.c 
Log Message:
updated physfs to version 0.1.5



--- NEW FILE ---
/*
 * 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>
#include <alloca.h>

/*
 * Most of the API calls in here are, according to ADC, available since
 *  MacOS 8.1. I don't think I used any MacOS 9 or CarbonLib-specific
 *  functions. There might be one or two 8.5 calls, and perhaps when the
 *  ADC docs say "Available in MacOS 8.1" they really mean "this works
 *  with System 6, but we don't want to hear about it at this point."
 *
 * IsAliasFile() showed up in MacOS 8.5. You can duplicate this code with
 *  PBGetCatInfoSync(), which is an older API, if you hope the bits in the
 *  catalog info never change (which they won't for, say, MacOS 8.1).
 *  See Apple Technote FL-30:
 *    http://developer.apple.com/technotes/fl/fl_30.html
 *
 * If you want to use weak pointers and Gestalt, and choose the correct
 *  code to use during __PHYSFS_platformInit(), I'll accept a patch, but
 *  chances are, it wasn't worth the time it took to write this, let alone
 *  implement that.
 */


/*
 * 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, especially since
 *  mutexes are no-ops in this file. Patches welcome.
 */
#ifdef __PHYSFS_CARBONIZED__  /* this is currently not defined anywhere. */
#include <Carbon.h>
#else
#include <OSUtils.h>
#include <Processes.h>
#include <Files.h>
#include <TextUtils.h>
#include <Resources.h>
#include <MacMemory.h>
#include <Events.h>
#include <DriverGestalt.h>
#include <Aliases.h>
#endif

#define __PHYSICSFS_INTERNAL__
#include "physfs_internal.h"


const char *__PHYSFS_platformDirSeparator = ":";

static struct ProcessInfoRec procInfo;
static FSSpec procfsspec;

int __PHYSFS_platformInit(void)
{
    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 */


int __PHYSFS_platformDeinit(void)
{
    return(1);  /* always succeed. */
} /* __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)
{
    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 */


static char *convFSSpecToPath(FSSpec *spec, int includeFile)
{
    char *ptr;
    char *retval = NULL;
    UInt32 retLength = 0;
    CInfoPBRec infoPB;
    Str255 str255;

    str255[0] = spec->name[0];
    memcpy(&str255[1], &spec->name[1], str255[0]);

    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 = (includeFile) ? 0 : -1;

    /* 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;
        if (PBGetCatInfoSync(&infoPB) != noErr)
        {
            if (retval != NULL)
                free(retval);
            BAIL_MACRO(ERR_OS_ERROR, NULL);
        } /* if */

        infoPB.dirInfo.ioFDirIndex = -1;  /* look at parent dir next time. */

        /* 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);
} /* convFSSpecToPath */


char *__PHYSFS_platformCalcBaseDir(const char *argv0)
{
    FSSpec spec;
    
    /* Get the name of the binary's parent directory. */
    FSMakeFSSpec(procfsspec.vRefNum, procfsspec.parID, procfsspec.name, &spec);
    return(convFSSpecToPath(&spec, 0));
} /* __PHYSFS_platformCalcBaseDir */


char *__PHYSFS_platformGetUserName(void)
{
    char *retval = NULL;
    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);

    return(retval);
} /* __PHYSFS_platformGetUserName */


char *__PHYSFS_platformGetUserDir(void)
{
#if 0
    return(NULL);  /* bah...use default behaviour, I guess. */
#else
    /* (Hmm. Default behaviour is broken in the base library.  :)  )  */
    return(__PHYSFS_platformCalcBaseDir(NULL));
#endif
} /* __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 */


static OSErr fnameToFSSpecNoAlias(const char *fname, FSSpec *spec)
{
    OSErr err;
    Str255 str255;
    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] = 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);
} /* fnameToFSSpecNoAlias */


/* !!! FIXME: This code is pretty heinous. */
static OSErr fnameToFSSpec(const char *fname, FSSpec *spec)
{
    Boolean alias = 0;
    Boolean folder = 0;
    OSErr err = fnameToFSSpecNoAlias(fname, spec);

    if (err == dirNFErr)  /* might be an alias in the middle of the path. */
    {
        /* 
         * Has to be at least two ':' chars, or we wouldn't get a
         *  dir-not-found condition. (no ':' means it was just a volume,
         *  just one ':' means we would have gotten a fnfErr, if anything.
         */
        char *ptr;
        char *start;
        char *path = alloca(strlen(fname) + 1);
        strcpy(path, fname);
        ptr = strchr(path, ':');
        BAIL_IF_MACRO(!ptr, ERR_FILE_NOT_FOUND, err); /* just in case */
        ptr = strchr(ptr + 1, ':');
        BAIL_IF_MACRO(!ptr, ERR_FILE_NOT_FOUND, err); /* just in case */
        *ptr = '\0';
        err = fnameToFSSpecNoAlias(path, spec); /* get first dir. */
        BAIL_IF_MACRO(err != noErr, ERR_OS_ERROR, err);
        start = ptr;
        ptr = strchr(start + 1, ':');

        do
        {
            CInfoPBRec infoPB;
            memset(&infoPB, '\0', sizeof (CInfoPBRec));
            infoPB.dirInfo.ioNamePtr = spec->name;
            infoPB.dirInfo.ioVRefNum = spec->vRefNum;
            infoPB.dirInfo.ioDrDirID = spec->parID;
            infoPB.dirInfo.ioFDirIndex = 0;
            err = PBGetCatInfoSync(&infoPB);
            if (err != noErr)  /* not an alias, really a bogus path. */
                return(fnameToFSSpecNoAlias(fname, spec)); /* reset */

            if ((infoPB.dirInfo.ioFlAttrib & kioFlAttribDirMask) != 0)
                spec->parID = infoPB.dirInfo.ioDrDirID;

            if (ptr != NULL)
                *ptr = '\0';
            *start = strlen(start + 1);  /* make it a pstring. */
            err = FSMakeFSSpec(spec->vRefNum, spec->parID,
                               (const unsigned char *) start, spec);
            if (err != noErr)  /* not an alias, really a bogus path. */
                return(fnameToFSSpecNoAlias(fname, spec)); /* reset */

            err = ResolveAliasFileWithMountFlags(spec, 1, &folder, &alias, 0);
            if (err != noErr)  /* not an alias, really a bogus path. */
                return(fnameToFSSpecNoAlias(fname, spec)); /* reset */
            start = ptr;
            if (ptr != NULL)
                ptr = strchr(start + 1, ':');                
        } while (start != NULL);
    } /* if */

    else /* there's something there; make sure final file is not an alias. */
    {
        BAIL_IF_MACRO(err != noErr, ERR_OS_ERROR, err);
        err = ResolveAliasFileWithMountFlags(spec, 1, &folder, &alias, 0);
        BAIL_IF_MACRO(err != noErr, ERR_OS_ERROR, err);
    } /* else */

    return(noErr);  /* w00t. */
} /* fnameToFSSpec */


int __PHYSFS_platformExists(const char *fname)
{
    FSSpec spec;
    return(fnameToFSSpec(fname, &spec) == noErr);
} /* __PHYSFS_platformExists */


int __PHYSFS_platformIsSymLink(const char *fname)
{
    OSErr err;
    FSSpec spec;
    Boolean a = 0;
    Boolean f = 0;
    CInfoPBRec infoPB;
    char *ptr;
    char *dir = alloca(strlen(fname) + 1);
    BAIL_IF_MACRO(dir == NULL, ERR_OUT_OF_MEMORY, 0);
    strcpy(dir, fname);
    ptr = strrchr(dir, ':');
    if (ptr == NULL)  /* just a volume name? Can't be a symlink. */
        return(0);

    /* resolve aliases up to the actual file... */
    *ptr = '\0';
    BAIL_IF_MACRO(fnameToFSSpec(dir, &spec) != noErr, ERR_OS_ERROR, 0);

    *ptr = strlen(ptr + 1);  /* ptr is now a pascal string. Yikes! */
    memset(&infoPB, '\0', sizeof (CInfoPBRec));
    infoPB.dirInfo.ioNamePtr = spec.name;
    infoPB.dirInfo.ioVRefNum = spec.vRefNum;
    infoPB.dirInfo.ioDrDirID = spec.parID;
    infoPB.dirInfo.ioFDirIndex = 0;
    BAIL_IF_MACRO(PBGetCatInfoSync(&infoPB) != noErr, ERR_OS_ERROR, 0);

    err = FSMakeFSSpec(spec.vRefNum, infoPB.dirInfo.ioDrDirID,
                       (const unsigned char *) ptr, &spec);
    BAIL_IF_MACRO(err != noErr, ERR_OS_ERROR, 0);
    BAIL_IF_MACRO(IsAliasFile(&spec, &a, &f) != noErr, ERR_OS_ERROR, 0);
    return(a);
} /* __PHYSFS_platformIsSymlink */


int __PHYSFS_platformIsDirectory(const char *fname)
{
    FSSpec spec;
    CInfoPBRec infoPB;
    OSErr err;

    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.    */ 
    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_OS_ERROR, 0);
    return((infoPB.dirInfo.ioFlAttrib & kioFlAttribDirMask) != 0);
} /* __PHYSFS_platformIsDirectory */


char *__PHYSFS_platformCvtToDependent(const char *prepend,
                                      const char *dirName,
                                      const char *append)
{
    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);
} /* __PHYSFS_platformCvtToDependent */


void __PHYSFS_platformTimeslice(void)
{
    SystemTask();
} /* __PHYSFS_platformTimeslice */


LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname,
                                                  int omitSymLinks)
{
    LinkedStringList *retval = NULL;
    LinkedStringList *l = NULL;
    LinkedStringList *prev = NULL;
    UInt16 i;
    UInt16 max;
    FSSpec spec;
    CInfoPBRec infoPB;
    Str255 str255;
    long dirID;

    BAIL_IF_MACRO(fnameToFSSpec(dirname, &spec) != noErr, ERR_OS_ERROR, 0);

    /* 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++)
    {
        FSSpec aliasspec;
        Boolean alias = 0;
        Boolean folder = 0;

        memset(&infoPB, '\0', sizeof (CInfoPBRec));
        str255[0] = 0;
        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)
            continue;  /* skip this file. Oh well. */

        if (FSMakeFSSpec(spec.vRefNum, dirID, str255, &aliasspec) != noErr)
            continue;  /* skip it. */

        if (IsAliasFile(&aliasspec, &alias, &folder) != noErr)
            continue;  /* skip it. */

        if ((alias) && (omitSymLinks))
            continue;

        /* still here? Add it to the list. */

        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;
    } /* for */

    return(retval);
} /* __PHYSFS_platformEnumerateFiles */


char *__PHYSFS_platformCurrentDir(void)
{
    /*
     * 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));
} /* __PHYSFS_platformCurrentDir */


char *__PHYSFS_platformRealPath(const char *path)
{
    /*
     * fnameToFSSpec() will resolve any symlinks to get to the real
     *  file's FSSpec, which, when converted, will contain the real
     *  direct path to a given file. convFSSpecToPath() mallocs a
     *  return value buffer.
     */

    FSSpec spec;
    BAIL_IF_MACRO(fnameToFSSpec(path, &spec) != noErr, ERR_OS_ERROR, NULL);
    return(convFSSpecToPath(&spec, 1));
} /* __PHYSFS_platformRealPath */


int __PHYSFS_platformMkDir(const char *path)
{
    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)
{
    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)
{
    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)
{
    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)
{
    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)
{
    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)
{
    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)
{
    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)
{
    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)
{
    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)
{
    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)
{
    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)
{
    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 */


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 macclassic.c ... */


--- NEW FILE ---
/*
 * Skeleton platform-dependent support routines for PhysicsFS.
 *
 * Please see the file LICENSE in the source's root directory.
 *
 *  This file written by Ryan C. Gordon.
 */

#define __PHYSICSFS_INTERNAL__
#include "physfs_internal.h"


#error DO NOT COMPILE THIS. IT IS JUST A SKELETON EXAMPLE FILE.


const char *__PHYSFS_platformDirSeparator = ":";


int __PHYSFS_platformInit(void)
{
    return(1);  /* always succeed. */
} /* __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)
{
    BAIL_MACRO(ERR_NOT_IMPLEMENTED, NULL);
} /* __PHYSFS_platformCalcBaseDir */


char *__PHYSFS_platformGetUserName(void)
{
    BAIL_MACRO(ERR_NOT_IMPLEMENTED, NULL);
} /* __PHYSFS_platformGetUserName */


char *__PHYSFS_platformGetUserDir(void)
{
    BAIL_MACRO(ERR_NOT_IMPLEMENTED, NULL);
} /* __PHYSFS_platformGetUserDir */


PHYSFS_uint64 __PHYSFS_platformGetThreadID(void)
{
    return(1);  /* single threaded. */
} /* __PHYSFS_platformGetThreadID */


int __PHYSFS_platformStricmp(const char *x, const char *y)
{
    BAIL_MACRO(ERR_NOT_IMPLEMENTED, 0);
} /* __PHYSFS_platformStricmp */


int __PHYSFS_platformExists(const char *fname)
{
    BAIL_MACRO(ERR_NOT_IMPLEMENTED, 0);
} /* __PHYSFS_platformExists */


int __PHYSFS_platformIsSymLink(const char *fname)
{
    BAIL_MACRO(ERR_NOT_IMPLEMENTED, 0);
} /* __PHYSFS_platformIsSymlink */


int __PHYSFS_platformIsDirectory(const char *fname)
{
    BAIL_MACRO(ERR_NOT_IMPLEMENTED, 0);
} /* __PHYSFS_platformIsDirectory */


char *__PHYSFS_platformCvtToDependent(const char *prepend,
                                      const char *dirName,
                                      const char *append)
{
    BAIL_MACRO(ERR_NOT_IMPLEMENTED, NULL);
} /* __PHYSFS_platformCvtToDependent */


void __PHYSFS_platformTimeslice(void)
{
} /* __PHYSFS_platformTimeslice */


LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname,
                                                  int omitSymLinks)
{
    BAIL_MACRO(ERR_NOT_IMPLEMENTED, NULL);
} /* __PHYSFS_platformEnumerateFiles */


char *__PHYSFS_platformCurrentDir(void)
{
    BAIL_MACRO(ERR_NOT_IMPLEMENTED, NULL);
} /* __PHYSFS_platformCurrentDir */


char *__PHYSFS_platformRealPath(const char *path)
{
    BAIL_MACRO(ERR_NOT_IMPLEMENTED, NULL);
} /* __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)
{
    BAIL_MACRO(ERR_NOT_IMPLEMENTED, NULL);
} /* __PHYSFS_platformCreateMutex */


void __PHYSFS_platformDestroyMutex(void *mutex)
{
} /* __PHYSFS_platformDestroyMutex */


int __PHYSFS_platformGrabMutex(void *mutex)
{
    /* not implemented, but can't call __PHYSFS_setError! */
    return(0);
} /* __PHYSFS_platformGrabMutex */


void __PHYSFS_platformReleaseMutex(void *mutex)
{
    /* not implemented, but can't call __PHYSFS_setError! */
} /* __PHYSFS_platformReleaseMutex */

/* end of skeleton.c ... */


--- NEW FILE ---
/*
 * Unix support routines for PhysicsFS.
 *
 * Please see the file LICENSE in the source's root directory.
 *
 *  This file written by Ryan C. Gordon.
 */

#if (defined __STRICT_ANSI__)
#define __PHYSFS_DOING_STRICT_ANSI__
#endif

/*
 * We cheat a little: I want the symlink version of stat() (lstat), and
 *  GCC/Linux will not declare it if compiled with the -ansi flag.
 *  If you are really lacking symlink support on your platform,
 *  you should #define __PHYSFS_NO_SYMLINKS__ before compiling this
 *  file. That will open a security hole, though, if you really DO have
 *  symlinks on your platform; it renders PHYSFS_permitSymbolicLinks(0)
 *  useless, since every symlink will be reported as a regular file/dir.
 */
#if (defined __PHYSFS_DOING_STRICT_ANSI__)
#undef __STRICT_ANSI__
#endif
#include <stdio.h>
#if (defined __PHYSFS_DOING_STRICT_ANSI__)
#define __STRICT_ANSI__
#endif

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <dirent.h>
#include <time.h>
#include <errno.h>

//#if (!defined __DARWIN__)
//#include <mntent.h>
//#else
//#include <sys/ucred.h>
//#endif

//#include <sys/mount.h>


#define __PHYSICSFS_INTERNAL__
#include "physfs_internal.h"


const char *__PHYSFS_platformDirSeparator = "/";


int __PHYSFS_platformInit(void)
{
    return(1);  /* always succeed. */
} /* __PHYSFS_platformInit */


int __PHYSFS_platformDeinit(void)
{
    return(1);  /* always succeed. */
} /* __PHYSFS_platformDeinit */


char **__PHYSFS_platformDetectAvailableCDs(void)
{
        return NULL;
} /* __PHYSFS_platformDetectAvailableCDs */


static char *copyEnvironmentVariable(const char *varname)
{
    const char *envr = getenv(varname);
    char *retval = NULL;

    if (envr != NULL)
    {
        retval = malloc(strlen(envr) + 1);
        if (retval != NULL)
            strcpy(retval, envr);
    } /* if */

    return(retval);
} /* copyEnvironmentVariable */


/* !!! this is ugly. */
char *__PHYSFS_platformCalcBaseDir(const char *argv0)
{
    /* If there isn't a path on argv0, then look through the $PATH for it. */

    char *retval = NULL;
    char *envr;
    char *start;
    char *ptr;
    char *exe;

    if (strchr(argv0, '/') != NULL)   /* default behaviour can handle this. */
        return(NULL);

    envr = copyEnvironmentVariable("PATH");
    BAIL_IF_MACRO(!envr, NULL, NULL);

    start = envr;
    do
    {
        ptr = strchr(start, ':');
        if (ptr)
            *ptr = '\0';

        exe = (char *) malloc(strlen(start) + strlen(argv0) + 2);
        if (!exe)
        {
            free(envr);
            BAIL_IF_MACRO(1, ERR_OUT_OF_MEMORY, NULL);
        } /* if */
        strcpy(exe, start);
        if (exe[strlen(exe) - 1] != '/')
            strcat(exe, "/");
        strcat(exe, argv0);
        if (access(exe, X_OK) != 0)
            free(exe);
        else
        {
            retval = exe;
            strcpy(retval, start);  /* i'm lazy. piss off. */
            break;
        } /* else */

        start = ptr + 1;
    } while (ptr != NULL);

    free(envr);
    return(retval);
} /* __PHYSFS_platformCalcBaseDir */


static char *getUserNameByUID(void)
{
    uid_t uid = getuid();
    struct passwd *pw;
    char *retval = NULL;

    pw = getpwuid(uid);
    if ((pw != NULL) && (pw->pw_name != NULL))
    {
        retval = malloc(strlen(pw->pw_name) + 1);
        if (retval != NULL)
            strcpy(retval, pw->pw_name);
    } /* if */
    
    return(retval);
} /* getUserNameByUID */


static char *getUserDirByUID(void)
{
    uid_t uid = getuid();
    struct passwd *pw;
    char *retval = NULL;

    pw = getpwuid(uid);
    if ((pw != NULL) && (pw->pw_dir != NULL))
    {
        retval = malloc(strlen(pw->pw_dir) + 1);
        if (retval != NULL)
            strcpy(retval, pw->pw_dir);
    } /* if */
    
    return(retval);
} /* getUserDirByUID */


char *__PHYSFS_platformGetUserName(void)
{
    char *retval = getUserNameByUID();
    if (retval == NULL)
        retval = copyEnvironmentVariable("USER");
    return(retval);
} /* __PHYSFS_platformGetUserName */


char *__PHYSFS_platformGetUserDir(void)
{
    char *retval = copyEnvironmentVariable("HOME");
    if (retval == NULL)
        retval = getUserDirByUID();
    return(retval);
} /* __PHYSFS_platformGetUserDir */


PHYSFS_uint64 __PHYSFS_platformGetThreadID(void)
{
    return((PHYSFS_uint64) ((PHYSFS_uint32) pthread_self()));
} /* __PHYSFS_platformGetThreadID */


/* -ansi and -pedantic flags prevent use of strcasecmp() on Linux. */
int __PHYSFS_platformStricmp(const char *x, const char *y)
{
    int ux, uy;

    do
    {
        ux = toupper((int) *x);
        uy = toupper((int) *y);
        if (ux > uy)
            return(1);
        else if (ux < uy)
            return(-1);
        x++;
        y++;
    } while ((ux) && (uy));

    return(0);
} /* __PHYSFS_platformStricmp */


int __PHYSFS_platformExists(const char *fname)
{
    struct stat statbuf;
    return(stat(fname, &statbuf) == 0);
} /* __PHYSFS_platformExists */


int __PHYSFS_platformIsSymLink(const char *fname)
{
#if (defined __PHYSFS_NO_SYMLINKS__)
    return(0);
#else

    struct stat statbuf;
    int retval = 0;

    if (lstat(fname, &statbuf) == 0)
    {
        if (S_ISLNK(statbuf.st_mode))
            retval = 1;
    } /* if */
    
    return(retval);

#endif
} /* __PHYSFS_platformIsSymlink */


int __PHYSFS_platformIsDirectory(const char *fname)
{
    struct stat statbuf;
    int retval = 0;

    if (stat(fname, &statbuf) == 0)
    {
        if (S_ISDIR(statbuf.st_mode))
            retval = 1;
    } /* if */
    
    return(retval);
} /* __PHYSFS_platformIsDirectory */


char *__PHYSFS_platformCvtToDependent(const char *prepend,
                                      const char *dirName,
                                      const char *append)
{
    int len = ((prepend) ? strlen(prepend) : 0) +
              ((append) ? strlen(append) : 0) +
              strlen(dirName) + 1;
    char *retval = malloc(len);

    BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);

    /* platform-independent notation is Unix-style already.  :)  */

    if (prepend)
        strcpy(retval, prepend);
    else
        retval[0] = '\0';

    strcat(retval, dirName);

    if (append)
        strcat(retval, append);

    return(retval);
} /* __PHYSFS_platformCvtToDependent */


/* Much like my college days, try to sleep for 10 milliseconds at a time... */
void __PHYSFS_platformTimeslice(void)
{
    usleep( 10 * 1000 );           /* don't care if it fails. */
} /* __PHYSFS_platformTimeslice */


LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname,
                                                  int omitSymLinks)
{
    LinkedStringList *retval = NULL;
    LinkedStringList *l = NULL;
    LinkedStringList *prev = NULL;
    DIR *dir;
    struct dirent *ent;
    int bufsize = 0;
    char *buf = NULL;
    int dlen = 0;

    if (omitSymLinks)
    {
        dlen = strlen(dirname);
        bufsize = dlen + 256;
        buf = malloc(bufsize);
        BAIL_IF_MACRO(buf == NULL, ERR_OUT_OF_MEMORY, NULL);
        strcpy(buf, dirname);
        if (buf[dlen - 1] != '/')
        {
            buf[dlen++] = '/';
            buf[dlen] = '\0';
        } /* if */
    } /* if */

    errno = 0;
    dir = opendir(dirname);
    if (dir == NULL)
    {
        if (buf != NULL)
            free(buf);
        BAIL_IF_MACRO(1, strerror(errno), NULL);
    } /* if */

    while (1)
    {
        ent = readdir(dir);
        if (ent == NULL)   /* we're done. */
            break;

        if (strcmp(ent->d_name, ".") == 0)
            continue;

        if (strcmp(ent->d_name, "..") == 0)
            continue;

        if (omitSymLinks)
        {
            char *p;
            int len = strlen(ent->d_name) + dlen + 1;
            if (len > bufsize)
            {
                p = realloc(buf, len);
                if (p == NULL)
                    continue;
                buf = p;
                bufsize = len;
            } /* if */

            strcpy(buf + dlen, ent->d_name);
            if (__PHYSFS_platformIsSymLink(buf))
                continue;
        } /* if */

        l = (LinkedStringList *) malloc(sizeof (LinkedStringList));
        if (l == NULL)
            break;

        l->str = (char *) malloc(strlen(ent->d_name) + 1);
        if (l->str == NULL)
        {
            free(l);
            break;
        } /* if */

        strcpy(l->str, ent->d_name);

        if (retval == NULL)
            retval = l;
        else
            prev->next = l;

        prev = l;
        l->next = NULL;
    } /* while */

    if (buf != NULL)
        free(buf);

    closedir(dir);
    return(retval);
} /* __PHYSFS_platformEnumerateFiles */


char *__PHYSFS_platformCurrentDir(void)
{
    int allocSize = 0;
    char *retval = NULL;
    char *ptr;

    do
    {
        allocSize += 100;
        ptr = (char *) realloc(retval, allocSize);
        if (ptr == NULL)
        {
            if (retval != NULL)
                free(retval);
            BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
        } /* if */

        retval = ptr;
        ptr = getcwd(retval, allocSize);
    } while (ptr == NULL && errno == ERANGE);

    if (ptr == NULL && errno)
    {
            /*
             * getcwd() failed for some reason, for example current
             * directory not existing.
             */
        if (retval != NULL)
            free(retval);
        BAIL_MACRO(ERR_NO_SUCH_FILE, NULL);
    } /* if */

    return(retval);
} /* __PHYSFS_platformCurrentDir */


char *__PHYSFS_platformRealPath(const char *path)
{
    char resolved_path[MAXPATHLEN];
    char *retval = NULL;

    errno = 0;
    BAIL_IF_MACRO(!realpath(path, resolved_path), strerror(errno), NULL);
    retval = malloc(strlen(resolved_path) + 1);
    BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
    strcpy(retval, resolved_path);
    return(retval);
} /* __PHYSFS_platformRealPath */


int __PHYSFS_platformMkDir(const char *path)
{
    int rc;
    errno = 0;
    rc = mkdir(path, S_IRWXU);
    BAIL_IF_MACRO(rc == -1, strerror(errno), 0);
    return(1);
} /* __PHYSFS_platformMkDir */


static void *doOpen(const char *filename, const char *mode)
{
    FILE *retval;
    errno = 0;

    retval = fopen(filename, mode);
    if (retval == NULL)
        __PHYSFS_setError(strerror(errno));

    return((void *) retval);
} /* doOpen */


void *__PHYSFS_platformOpenRead(const char *filename)
{
    return(doOpen(filename, "rb"));
} /* __PHYSFS_platformOpenRead */


void *__PHYSFS_platformOpenWrite(const char *filename)
{
    return(doOpen(filename, "wb"));
} /* __PHYSFS_platformOpenWrite */


void *__PHYSFS_platformOpenAppend(const char *filename)
{
    return(doOpen(filename, "wb+"));
} /* __PHYSFS_platformOpenAppend */


PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buffer,
                                    PHYSFS_uint32 size, PHYSFS_uint32 count)
{
    FILE *io = (FILE *) opaque;
    int rc = fread(buffer, size, count, io);
    if (rc < count)
    {
        int err = errno;
        BAIL_IF_MACRO(ferror(io), strerror(err), rc);
        BAIL_MACRO(ERR_PAST_EOF, rc);
    } /* if */

    return(rc);
} /* __PHYSFS_platformRead */


PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer,
                                     PHYSFS_uint32 size, PHYSFS_uint32 count)
{
    FILE *io = (FILE *) opaque;
    int rc = fwrite((void *) buffer, size, count, io);
    if (rc < count)
        __PHYSFS_setError(strerror(errno));

    return(rc);
} /* __PHYSFS_platformWrite */


int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos)
{
    FILE *io = (FILE *) opaque;

    /* !!! FIXME: Use llseek where available. */
    errno = 0;
    BAIL_IF_MACRO(fseek(io, pos, SEEK_SET) != 0, strerror(errno), 0);

    return(1);
} /* __PHYSFS_platformSeek */


PHYSFS_sint64 __PHYSFS_platformTell(void *opaque)
{
    FILE *io = (FILE *) opaque;
    PHYSFS_sint64 retval = ftell(io);
    BAIL_IF_MACRO(retval == -1, strerror(errno), -1);
    return(retval);
} /* __PHYSFS_platformTell */


PHYSFS_sint64 __PHYSFS_platformFileLength(void *opaque)
{
    FILE *io = (FILE *) opaque;
    struct stat statbuf;
    errno = 0;
    BAIL_IF_MACRO(fstat(fileno(io), &statbuf) == -1, strerror(errno), -1);
    return((PHYSFS_sint64) statbuf.st_size);
} /* __PHYSFS_platformFileLength */


int __PHYSFS_platformEOF(void *opaque)
{
    return(feof((FILE *) opaque));
} /* __PHYSFS_platformEOF */


int __PHYSFS_platformFlush(void *opaque)
{
    errno = 0;
    BAIL_IF_MACRO(fflush((FILE *) opaque) == EOF, strerror(errno), 0);
    return(1);
} /* __PHYSFS_platformFlush */


int __PHYSFS_platformClose(void *opaque)
{
    errno = 0;
    BAIL_IF_MACRO(fclose((FILE *) opaque) == EOF, strerror(errno), 0);
    return(1);
} /* __PHYSFS_platformClose */


int __PHYSFS_platformDelete(const char *path)
{
    errno = 0;
    BAIL_IF_MACRO(remove(path) == -1, strerror(errno), 0);
    return(1);
} /* __PHYSFS_platformDelete */


void *__PHYSFS_platformCreateMutex(void)
{
    int rc;
    pthread_mutex_t *m = (pthread_mutex_t *) malloc(sizeof (pthread_mutex_t));
    BAIL_IF_MACRO(m == NULL, ERR_OUT_OF_MEMORY, NULL);
    rc = pthread_mutex_init(m, NULL);
    if (rc != 0)
    {
        free(m);
        BAIL_MACRO(strerror(rc), NULL);
    } /* if */

    return((void *) m);
} /* __PHYSFS_platformCreateMutex */


void __PHYSFS_platformDestroyMutex(void *mutex)
{
    pthread_mutex_destroy((pthread_mutex_t *) mutex);
    free(mutex);
} /* __PHYSFS_platformDestroyMutex */


int __PHYSFS_platformGrabMutex(void *mutex)
{
    return(pthread_mutex_lock((pthread_mutex_t *) mutex) == 0);    
} /* __PHYSFS_platformGrabMutex */


void __PHYSFS_platformReleaseMutex(void *mutex)
{
    pthread_mutex_unlock((pthread_mutex_t *) mutex);
} /* __PHYSFS_platformReleaseMutex */

/* end of unix.c ... */


Index: Makefile.am
===================================================================
RCS file: /cvsroot/paragui/paragui/src/physfs/platform/Makefile.am,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.6.1
diff -C2 -r1.1.1.1 -r1.1.1.1.6.1
*** Makefile.am 15 Apr 2002 13:22:14 -0000      1.1.1.1
--- Makefile.am 3 May 2002 10:15:33 -0000       1.1.1.1.6.1
***************
*** 1,7 ****
  EXTRA_DIST = \
        beos.c \
!       freebsd.c \
!       irix.c \
!       solaris.c \
        unix.c \
        win32.c
--- 1,7 ----
  EXTRA_DIST = \
        beos.c \
!       skeleton.c \
!       macclassic.c \
        unix.c \
+       unix_nocdrom.c \
        win32.c

Index: unix.c
===================================================================
RCS file: /cvsroot/paragui/paragui/src/physfs/platform/unix.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.6.1
diff -C2 -r1.1.1.1 -r1.1.1.1.6.1
*** unix.c      15 Apr 2002 13:22:14 -0000      1.1.1.1
--- unix.c      3 May 2002 10:15:33 -0000       1.1.1.1.6.1
***************
*** 7,10 ****
--- 7,16 ----
   */
  
+ #if ((defined __APPLE__) && (defined __MACH__))
+ #  if (!defined __DARWIN__)
+ #    define __DARWIN__
+ #  endif
+ #endif
+ 
  #if (defined __STRICT_ANSI__)
  #define __PHYSFS_DOING_STRICT_ANSI__
***************
*** 40,44 ****
--- 46,58 ----
  #include <time.h>
  #include <errno.h>
+ 
+ #if (!defined __DARWIN__)
  #include <mntent.h>
+ #else
+ #include <sys/ucred.h>
+ #endif
+ 
+ #include <sys/mount.h>
+ 
  
  #define __PHYSICSFS_INTERNAL__
***************
*** 48,51 ****
--- 62,129 ----
  const char *__PHYSFS_platformDirSeparator = "/";
  
+ 
+ int __PHYSFS_platformInit(void)
+ {
+     return(1);  /* always succeed. */
+ } /* __PHYSFS_platformInit */
+ 
+ 
+ int __PHYSFS_platformDeinit(void)
+ {
+     return(1);  /* always succeed. */
+ } /* __PHYSFS_platformDeinit */
+ 
+ 
+ 
+ #if (defined __DARWIN__)
+ 
+ char **__PHYSFS_platformDetectAvailableCDs(void)
+ {
+     char **retval = (char **) malloc(sizeof (char *));
+     int cd_count = 1;  /* We count the NULL entry. */
+     struct statfs* mntbufp = NULL;
+     int mounts;
+     int ii;
+ 
+     BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
+ 
+     mounts = getmntinfo( &mntbufp, MNT_WAIT );
+ 
+     for ( ii=0; ii < mounts; ++ii ) {
+         int add_it = 0;
+ 
+         if ( strcmp( mntbufp[ii].f_fstypename, "iso9660") == 0 )
+             add_it = 1;
+         else if ( strcmp( mntbufp[ii].f_fstypename, "cd9660") == 0 )
+             add_it = 1;
+         /* !!! other mount types? */
+ 
+         if (add_it)
+         {
+             char **tmp = realloc(retval, sizeof (char *) * cd_count + 1);
+             if (tmp)
+             {
+                 retval = tmp;
+                 retval[cd_count-1] = (char *)
+                                 malloc(strlen(mntbufp[ ii ].f_mntonname) + 1);
+                 if (retval[cd_count-1])
+                 {
+                     strcpy(retval[cd_count-1], mntbufp[ ii ].f_mntonname);
+                     cd_count++;
+                 } /* if */
+             } /* if */
+         } /* if */
+     }
+ 
+     free( mntbufp );
+ 
+     retval[cd_count - 1] = NULL;
+     return(retval);
+ } /* __PHYSFS_platformDetectAvailableCDs */
+ 
+ 
+ #else  /* non-Darwin implementation... */
+ 
+ 
  char **__PHYSFS_platformDetectAvailableCDs(void)
  {
***************
*** 55,58 ****
--- 133,138 ----
      struct mntent *ent = NULL;
  
+     BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
+ 
      *retval = NULL;
      mounts = setmntent("/etc/mtab", "r");
***************
*** 86,90 ****
      retval[cd_count - 1] = NULL;
      return(retval);
! } /* __PHYSFS_detectAvailableCDs */
  
  
--- 166,172 ----
      retval[cd_count - 1] = NULL;
      return(retval);
! } /* __PHYSFS_platformDetectAvailableCDs */
! 
! #endif
  
  
***************
*** 210,216 ****
  
  
! int __PHYSFS_platformGetThreadID(void)
  {
!     return((int) pthread_self());
  } /* __PHYSFS_platformGetThreadID */
  
--- 292,298 ----
  
  
! PHYSFS_uint64 __PHYSFS_platformGetThreadID(void)
  {
!     return((PHYSFS_uint64) ((PHYSFS_uint32) pthread_self()));
  } /* __PHYSFS_platformGetThreadID */
  
***************
*** 310,317 ****
  void __PHYSFS_platformTimeslice(void)
  {
!     struct timespec napTime;
!     napTime.tv_sec = 0;
!     napTime.tv_nsec = 10 * 1000 * 1000;  /* specified in nanoseconds. */
!     nanosleep(&napTime, NULL);           /* don't care if it fails. */
  } /* __PHYSFS_platformTimeslice */
  
--- 392,396 ----
  void __PHYSFS_platformTimeslice(void)
  {
!     usleep( 10 * 1000 );           /* don't care if it fails. */
  } /* __PHYSFS_platformTimeslice */
  
***************
*** 412,424 ****
  
  
- int __PHYSFS_platformFileLength(FILE *handle)
- {
-     struct stat statbuf;
-     errno = 0;
-     BAIL_IF_MACRO(fstat(fileno(handle), &statbuf) == -1, strerror(errno), -1);
-     return(statbuf.st_size);
- } /* __PHYSFS_platformFileLength */
- 
- 
  char *__PHYSFS_platformCurrentDir(void)
  {
--- 491,494 ----
***************
*** 435,452 ****
              if (retval != NULL)
                  free(retval);
!             BAIL_IF_MACRO(1, ERR_OUT_OF_MEMORY, NULL);
          } /* if */
!       
          retval = ptr;
          ptr = getcwd(retval, allocSize);
      } while (ptr == NULL && errno == ERANGE);
!     if(ptr == NULL && errno) {
!       /* getcwd() failed for some reason, for example current
!        * directory not existing.
!        */
!       if (retval != NULL)
!           free(retval);
!       BAIL_IF_MACRO(1, ERR_NO_SUCH_FILE, NULL);
!     }
      return(retval);
  } /* __PHYSFS_platformCurrentDir */
--- 505,526 ----
              if (retval != NULL)
                  free(retval);
!             BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
          } /* if */
! 
          retval = ptr;
          ptr = getcwd(retval, allocSize);
      } while (ptr == NULL && errno == ERANGE);
! 
!     if (ptr == NULL && errno)
!     {
!             /*
!              * getcwd() failed for some reason, for example current
!              * directory not existing.
!              */
!         if (retval != NULL)
!             free(retval);
!         BAIL_MACRO(ERR_NO_SUCH_FILE, NULL);
!     } /* if */
! 
      return(retval);
  } /* __PHYSFS_platformCurrentDir */
***************
*** 475,478 ****
--- 549,707 ----
      return(1);
  } /* __PHYSFS_platformMkDir */
+ 
+ 
+ static void *doOpen(const char *filename, const char *mode)
+ {
+     FILE *retval;
+     errno = 0;
+ 
+     retval = fopen(filename, mode);
+     if (retval == NULL)
+         __PHYSFS_setError(strerror(errno));
+ 
+     return((void *) retval);
+ } /* doOpen */
+ 
+ 
+ void *__PHYSFS_platformOpenRead(const char *filename)
+ {
+     return(doOpen(filename, "rb"));
+ } /* __PHYSFS_platformOpenRead */
+ 
+ 
+ void *__PHYSFS_platformOpenWrite(const char *filename)
+ {
+     return(doOpen(filename, "wb"));
+ } /* __PHYSFS_platformOpenWrite */
+ 
+ 
+ void *__PHYSFS_platformOpenAppend(const char *filename)
+ {
+     return(doOpen(filename, "wb+"));
+ } /* __PHYSFS_platformOpenAppend */
+ 
+ 
+ PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buffer,
+                                     PHYSFS_uint32 size, PHYSFS_uint32 count)
+ {
+     FILE *io = (FILE *) opaque;
+     int rc = fread(buffer, size, count, io);
+     if (rc < count)
+     {
+         int err = errno;
+         BAIL_IF_MACRO(ferror(io), strerror(err), rc);
+         BAIL_MACRO(ERR_PAST_EOF, rc);
+     } /* if */
+ 
+     return(rc);
+ } /* __PHYSFS_platformRead */
+ 
+ 
+ PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer,
+                                      PHYSFS_uint32 size, PHYSFS_uint32 count)
+ {
+     FILE *io = (FILE *) opaque;
+     int rc = fwrite((void *) buffer, size, count, io);
+     if (rc < count)
+         __PHYSFS_setError(strerror(errno));
+ 
+     return(rc);
+ } /* __PHYSFS_platformWrite */
+ 
+ 
+ int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos)
+ {
+     FILE *io = (FILE *) opaque;
+ 
+     /* !!! FIXME: Use llseek where available. */
+     errno = 0;
+     BAIL_IF_MACRO(fseek(io, pos, SEEK_SET) != 0, strerror(errno), 0);
+ 
+     return(1);
+ } /* __PHYSFS_platformSeek */
+ 
+ 
+ PHYSFS_sint64 __PHYSFS_platformTell(void *opaque)
+ {
+     FILE *io = (FILE *) opaque;
+     PHYSFS_sint64 retval = ftell(io);
+     BAIL_IF_MACRO(retval == -1, strerror(errno), -1);
+     return(retval);
+ } /* __PHYSFS_platformTell */
+ 
+ 
+ PHYSFS_sint64 __PHYSFS_platformFileLength(void *opaque)
+ {
+     FILE *io = (FILE *) opaque;
+     struct stat statbuf;
+     errno = 0;
+     BAIL_IF_MACRO(fstat(fileno(io), &statbuf) == -1, strerror(errno), -1);
+     return((PHYSFS_sint64) statbuf.st_size);
+ } /* __PHYSFS_platformFileLength */
+ 
+ 
+ int __PHYSFS_platformEOF(void *opaque)
+ {
+     return(feof((FILE *) opaque));
+ } /* __PHYSFS_platformEOF */
+ 
+ 
+ int __PHYSFS_platformFlush(void *opaque)
+ {
+     errno = 0;
+     BAIL_IF_MACRO(fflush((FILE *) opaque) == EOF, strerror(errno), 0);
+     return(1);
+ } /* __PHYSFS_platformFlush */
+ 
+ 
+ int __PHYSFS_platformClose(void *opaque)
+ {
+     errno = 0;
+     BAIL_IF_MACRO(fclose((FILE *) opaque) == EOF, strerror(errno), 0);
+     return(1);
+ } /* __PHYSFS_platformClose */
+ 
+ 
+ int __PHYSFS_platformDelete(const char *path)
+ {
+     errno = 0;
+     BAIL_IF_MACRO(remove(path) == -1, strerror(errno), 0);
+     return(1);
+ } /* __PHYSFS_platformDelete */
+ 
+ 
+ void *__PHYSFS_platformCreateMutex(void)
+ {
+     int rc;
+     pthread_mutex_t *m = (pthread_mutex_t *) malloc(sizeof (pthread_mutex_t));
+     BAIL_IF_MACRO(m == NULL, ERR_OUT_OF_MEMORY, NULL);
+     rc = pthread_mutex_init(m, NULL);
+     if (rc != 0)
+     {
+         free(m);
+         BAIL_MACRO(strerror(rc), NULL);
+     } /* if */
+ 
+     return((void *) m);
+ } /* __PHYSFS_platformCreateMutex */
+ 
+ 
+ void __PHYSFS_platformDestroyMutex(void *mutex)
+ {
+     pthread_mutex_destroy((pthread_mutex_t *) mutex);
+     free(mutex);
+ } /* __PHYSFS_platformDestroyMutex */
+ 
+ 
+ int __PHYSFS_platformGrabMutex(void *mutex)
+ {
+     return(pthread_mutex_lock((pthread_mutex_t *) mutex) == 0);    
+ } /* __PHYSFS_platformGrabMutex */
+ 
+ 
+ void __PHYSFS_platformReleaseMutex(void *mutex)
+ {
+     pthread_mutex_unlock((pthread_mutex_t *) mutex);
+ } /* __PHYSFS_platformReleaseMutex */
  
  /* end of unix.c ... */

Index: win32.c
===================================================================
RCS file: /cvsroot/paragui/paragui/src/physfs/platform/win32.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.6.1
diff -C2 -r1.1.1.1 -r1.1.1.1.6.1
*** win32.c     15 Apr 2002 13:22:14 -0000      1.1.1.1
--- win32.c     3 May 2002 10:15:33 -0000       1.1.1.1.6.1
***************
*** 4,15 ****
   * Please see the file LICENSE in the source's root directory.
   *
!  *  This file written by Ryan C. Gordon.
   */
  
- #if (defined __STRICT_ANSI__)
- #define __PHYSFS_DOING_STRICT_ANSI__
- #endif
- 
  #include <windows.h>
  #include <stdio.h>
  #include <stdlib.h>
--- 4,12 ----
   * Please see the file LICENSE in the source's root directory.
   *
!  *  This file written by Ryan C. Gordon, and made sane by Gregory S. Read.
   */
  
  #include <windows.h>
+ #include <userenv.h>
  #include <stdio.h>
  #include <stdlib.h>
***************
*** 19,25 ****
--- 16,32 ----
  #include "physfs_internal.h"
  
+ #define LOWORDER_UINT64(pos)       (PHYSFS_uint32)(pos & 0x00000000FFFFFFFF)
+ #define HIGHORDER_UINT64(pos)      (PHYSFS_uint32)(pos & 0xFFFFFFFF00000000)
  
  const char *__PHYSFS_platformDirSeparator = "\\";
  
+ static HANDLE ProcessHandle = NULL;     /* Current process handle */
+ static HANDLE AccessTokenHandle = NULL; /* Security handle to process */
+ static DWORD ProcessID;                 /* ID assigned to current process */
+ static int runningNT;                   /* TRUE if NT derived OS */
+ static OSVERSIONINFO OSVersionInfo;     /* Information about the OS */
+ 
+ /* NT specific information */
+ static char *ProfileDirectory = NULL;   /* User profile folder */
  
  static const char *win32strerror(void)
***************
*** 52,55 ****
--- 59,65 ----
          if (GetDriveType(drive_str) == DRIVE_CDROM)
          {
+ 
+             /* !!! FIXME: Make sure there's really a disc in the drive? */
+ 
              char **tmp = realloc(retval, sizeof (char *) * cd_count + 1);
              if (tmp)
***************
*** 71,85 ****
  
  
! char *__PHYSFS_platformCalcBaseDir(const char *argv0)
  {
-     DWORD buflen = 0;
-     char *retval = NULL;
      char *filepart = NULL;
! 
!     if (strchr(argv0, '\\') != NULL)   /* default behaviour can handle this. 
*/
!         return(NULL);
! 
!     retval = (char *) malloc(sizeof (TCHAR) * (MAX_PATH + 1));
!     buflen = GetModuleFileName(NULL, retval, MAX_PATH + 1);
      retval[buflen] = '\0';  /* does API always null-terminate the string? */
  
--- 81,89 ----
  
  
! static char *getExePath(const char *argv0)
  {
      char *filepart = NULL;
!     char *retval = (char *) malloc(sizeof (TCHAR) * (MAX_PATH + 1));
!     DWORD buflen = GetModuleFileName(NULL, retval, MAX_PATH + 1);
      retval[buflen] = '\0';  /* does API always null-terminate the string? */
  
***************
*** 106,109 ****
--- 110,122 ----
  
      return(retval);
+ } /* getExePath */
+ 
+ 
+ char *__PHYSFS_platformCalcBaseDir(const char *argv0)
+ {
+     if (strchr(argv0, '\\') != NULL)   /* default behaviour can handle this. 
*/
+         return(NULL);
+ 
+     return(getExePath(argv0));
  } /* __PHYSFS_platformCalcBaseDir */
  
***************
*** 129,180 ****
  
  
- static char *copyEnvironmentVariable(const char *varname)
- {
-     const char *envr = getenv(varname);
-     char *retval = NULL;
- 
-     if (envr != NULL)
-     {
-         retval = malloc(strlen(envr) + 1);
-         if (retval != NULL)
-             strcpy(retval, envr);
-     } /* if */
- 
-     return(retval);
- } /* copyEnvironmentVariable */
- 
- 
  char *__PHYSFS_platformGetUserDir(void)
  {
!     char *home = copyEnvironmentVariable("HOME");
!     const char *homedrive = getenv("HOMEDRIVE");
!     const char *homepath = getenv("HOMEPATH");
  
!     if (home != NULL)
!         return(home);
! 
!     if ((homedrive != NULL) && (homepath != NULL))
      {
!         char *retval = (char *) malloc(strlen(homedrive)+strlen(homepath)+2);
!         if (retval != NULL)
!         {
!             strcpy(retval, homedrive);
!             if ((homepath[0] != '\\') &&
!                 (homedrive[strlen(homedrive)-1] != '\\'))
!             {
!                 strcat(retval, "\\");
!             } /* if */
!             strcat(retval, homepath);
!             return(retval);
!         } /* if */
!     } /* if */
  
!     return(NULL);
  } /* __PHYSFS_platformGetUserDir */
  
  
! int __PHYSFS_platformGetThreadID(void)
  {
!     return((int) GetCurrentThreadId());
  } /* __PHYSFS_platformGetThreadID */
  
--- 142,165 ----
  
  
  char *__PHYSFS_platformGetUserDir(void)
  {
!     char *userdir = NULL;
  
!     if (runningNT)
      {
!         userdir = ProfileDirectory;
!     }
!     else
!     {
!         /*!!!TODO - Need to return something for Win9x/ME */
!     }
  
!     return userdir;
  } /* __PHYSFS_platformGetUserDir */
  
  
! PHYSFS_uint64 __PHYSFS_platformGetThreadID(void)
  {
!     return((PHYSFS_uint64)GetCurrentThreadId());
  } /* __PHYSFS_platformGetThreadID */
  
***************
*** 183,186 ****
--- 168,174 ----
  int __PHYSFS_platformStricmp(const char *x, const char *y)
  {
+ #if (defined _MSC_VER)
+     return(stricmp(x, y));
+ #else
      int ux, uy;
  
***************
*** 198,201 ****
--- 186,190 ----
  
      return(0);
+ #endif
  } /* __PHYSFS_platformStricmp */
  
***************
*** 267,271 ****
      BAIL_IF_MACRO(dir == INVALID_HANDLE_VALUE, win32strerror(), NULL);
  
!     for (; FindNextFile(dir, &ent) != 0; )
      {
          if (strcmp(ent.cFileName, ".") == 0)
--- 256,260 ----
      BAIL_IF_MACRO(dir == INVALID_HANDLE_VALUE, win32strerror(), NULL);
  
!     while (FindNextFile(dir, &ent) != 0)
      {
          if (strcmp(ent.cFileName, ".") == 0)
***************
*** 302,318 ****
  
  
- int __PHYSFS_platformFileLength(FILE *handle)
- {
-     fpos_t curpos;
-     int retval;
- 
-     fgetpos(handle, &curpos);
-     fseek(handle, 0, SEEK_END);
-     retval = ftell(handle);
-     fsetpos(handle, &curpos);
-     return(retval);
- } /* __PHYSFS_platformFileLength */
- 
- 
  char *__PHYSFS_platformCurrentDir(void)
  {
--- 291,294 ----
***************
*** 349,356 ****
           */
      if ((path[0] == '\\') && (path[1] == '\\'))
-     {
-         BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
          strcpy(retval, path);
-     } /* if */
  
      else
--- 325,329 ----
***************
*** 462,465 ****
--- 435,878 ----
      return(1);
  } /* __PHYSFS_platformMkDir */
+ 
+ /*
+  * Initialize any NT specific stuff.  This includes any OS based on NT.
+  *
+  * Return zero if there was a catastrophic failure and non-zero otherwise.
+  */
+ static int doNTInit(void)
+ {
+     DWORD pathsize = 0;
+     char TempProfileDirectory[1];
+ 
+     /* Create a process access token handle */
+     if(!OpenProcessToken(ProcessHandle, TOKEN_QUERY, &AccessTokenHandle))
+     {
+         /* Access token is required by other win32 functions */
+         return 0;
+     }
+ 
+     /* Should fail.  Will write the size of the profile path in pathsize*/
+     /*!!! Second parameter can't be NULL or the function fails??? */
+     if(!GetUserProfileDirectory(AccessTokenHandle, TempProfileDirectory, 
&pathsize))
+     {
+         /* Allocate memory for the profile directory */
+         ProfileDirectory = (char *)malloc(pathsize);
+         BAIL_IF_MACRO(ProfileDirectory == NULL, ERR_OUT_OF_MEMORY, 0);
+         /* Try to get the profile directory */
+         if(!GetUserProfileDirectory(AccessTokenHandle, ProfileDirectory, 
&pathsize))
+         {
+             free(ProfileDirectory);
+             return 0;
+         }
+     }
+ 
+     /* Everything initialized okay */
+     return 1;
+ }
+ 
+ /* 
+  * Get OS info and save it.
+  *
+  * Returns non-zero if successful, otherwise it returns zero on failure.
+  */
+ int getOSInfo(void)
+ {
+     /* Get OS info */
+     OSVersionInfo.dwOSVersionInfoSize = sizeof(OSVersionInfo);
+     if(!GetVersionEx(&OSVersionInfo))
+     {
+         return 0;
+     }
+ 
+     /* Set to TRUE if we are runnign a WinNT based OS 4.0 or greater */
+     runningNT = (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) &&
+         (OSVersionInfo.dwMajorVersion > 3);
+ 
+     return 1;
+ }
+ 
+ int __PHYSFS_platformInit(void)
+ {
+     if(!getOSInfo())
+     {
+         return 0;
+     }
+ 
+     /* Get Windows ProcessID associated with the current process */
+     ProcessID = GetCurrentProcessId();
+     /* Create a process handle associated with the current process ID */
+     ProcessHandle = GetCurrentProcess();
+ 
+     if(ProcessHandle == NULL)
+     {
+         /* Process handle is required by other win32 functions */
+         return 0;
+     }
+ 
+     /* If running an NT system (NT/Win2k/XP, etc...) */
+     if(runningNT)
+     {
+         if(!doNTInit())
+         {
+             /* Error initializing NT stuff */
+             return 0;
+         }
+     }
+ 
+     /* It's all good */
+     return 1;
+ }
+ 
+ /*
+  * Uninitialize any NT specific stuff done in doNTInit().
+  *
+  * Return zero if there was a catastrophic failure and non-zero otherwise.
+  */
+ static int doNTDeinit(void)
+ {
+     if(CloseHandle(AccessTokenHandle) != S_OK)
+     {
+         return 0;
+     }
+ 
+     free(ProfileDirectory);
+ 
+     /* It's all good */
+     return 1;
+ }
+ 
+ int __PHYSFS_platformDeinit(void)
+ {
+     if(!doNTDeinit())
+         return 0;
+ 
+     if(CloseHandle(ProcessHandle) != S_OK)
+         return 0;
+ 
+     /* It's all good */
+     return 1;
+ }
+ 
+ void *__PHYSFS_platformOpenRead(const char *filename)
+ {
+     HANDLE FileHandle;
+     
+     /* Open an existing file for read only. File can be opened by others
+        who request read access on the file only. */
+     FileHandle = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, 
+         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ 
+     /* If CreateFile() failed */
+     if(FileHandle == INVALID_HANDLE_VALUE)
+         return NULL;
+ 
+     return (void *)FileHandle;
+ }
+ 
+ void *__PHYSFS_platformOpenWrite(const char *filename)
+ {
+     HANDLE FileHandle;
+     
+     /* Open an existing file for write only.  File can be opened by others
+        who request read access to the file only */
+     FileHandle = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL, 
+         CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ 
+     /* If CreateFile() failed */
+     if(FileHandle == INVALID_HANDLE_VALUE)
+         return NULL;
+ 
+     return (void *)FileHandle;
+ }
+ 
+ void *__PHYSFS_platformOpenAppend(const char *filename)
+ {
+     HANDLE FileHandle;
+     
+     /* Open an existing file for appending only.  File can be opened by others
+        who request read access to the file only. */
+     FileHandle = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL, 
+         TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ 
+     /* If CreateFile() failed */
+     if(FileHandle == INVALID_HANDLE_VALUE)
+         /* CreateFile might have failed because the file doesn't exist, so
+            we'll just create a new file for writing then */
+         return __PHYSFS_platformOpenWrite(filename);
+ 
+     return (void *)FileHandle;
+ }
+ 
+ PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buffer,
+                                     PHYSFS_uint32 size, PHYSFS_uint32 count)
+ {
+     HANDLE FileHandle;
+     DWORD CountOfBytesRead;
+     PHYSFS_sint64 retval;
+ 
+     /* Cast the generic handle to a Win32 handle */
+     FileHandle = (HANDLE)opaque;
+ 
+     /* Read data from the file */
+     /*!!! - uint32 might be a greater # than DWORD */
+     if(!ReadFile(FileHandle, buffer, count * size, &CountOfBytesRead, NULL))
+     {
+         /* Set the error to GetLastError */
+         __PHYSFS_setError(win32strerror());
+         /* We errored out */
+         retval = -1;
+     }
+     else
+     {
+         /* Return the number of "objects" read. */
+         /* !!! - What if not the right amount of bytes was read to make an 
object? */
+         retval = CountOfBytesRead / size;
+     }
+ 
+     return retval;
+ }
+ 
+ PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, void *buffer,
+                                      PHYSFS_uint32 size, PHYSFS_uint32 count)
+ {
+     HANDLE FileHandle;
+     DWORD CountOfBytesWritten;
+     PHYSFS_sint64 retval;
+ 
+     /* Cast the generic handle to a Win32 handle */
+     FileHandle = (HANDLE)opaque;
+ 
+     /* Read data from the file */
+     /*!!! - uint32 might be a greater # than DWORD */
+     if(!WriteFile(FileHandle, buffer, count * size, &CountOfBytesWritten, 
NULL))
+     {
+         /* Set the error to GetLastError */
+         __PHYSFS_setError(win32strerror());
+         /* We errored out */
+         retval = -1;
+     }
+     else
+     {
+         /* Return the number of "objects" read. */
+         /*!!! - What if not the right number of bytes was written? */
+         retval = CountOfBytesWritten / size;
+     }
+ 
+     return retval;
+ }
+ 
+ int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos)
+ {
+     HANDLE FileHandle;
+     int retval;
+     DWORD HighOrderPos;
+ 
+     /* Cast the generic handle to a Win32 handle */
+     FileHandle = (HANDLE)opaque;
+ 
+     /* Get the high order 32-bits of the position */
+     HighOrderPos = HIGHORDER_UINT64(pos);
+ 
+     /*!!! SetFilePointer needs a signed 64-bit value. */
+     /* Move pointer "pos" count from start of file */
+     if((SetFilePointer(FileHandle, LOWORDER_UINT64(pos), &HighOrderPos, 
FILE_BEGIN)
+         == INVALID_SET_FILE_POINTER) && (GetLastError() != NO_ERROR))
+     {
+         /* An error occured.  Set the error to GetLastError */
+         __PHYSFS_setError(win32strerror());
+ 
+         retval = 0;
+     }
+     else
+     {
+         /* No error occured */
+         retval = 1;
+     }
+ 
+     return retval;
+ }
+ 
+ PHYSFS_sint64 __PHYSFS_platformTell(void *opaque)
+ {
+     HANDLE FileHandle;
+     DWORD HighOrderPos = 0; 
+     DWORD LowOrderPos;
+     PHYSFS_sint64 retval;
+ 
+     /* Cast the generic handle to a Win32 handle */
+     FileHandle = (HANDLE)opaque;
+ 
+     /* Get current position */
+     if(((LowOrderPos = SetFilePointer(FileHandle, 0, &HighOrderPos, 
FILE_CURRENT))
+         == INVALID_SET_FILE_POINTER) && (GetLastError() != NO_ERROR))
+     {
+         /* Combine the high/low order to create the 64-bit position value */
+         retval = HighOrderPos;
+         retval = retval << 32;
+         retval |= LowOrderPos;
+     }
+     else
+     {
+         /* Set the error to GetLastError */
+         __PHYSFS_setError(win32strerror());
+         /* We errored out */
+         retval = 0;
+     }
+ 
+     /*!!! Can't find a file pointer routine?!?!?!!?!?*/
+     return retval;
+ }
+ 
+ PHYSFS_sint64 __PHYSFS_platformFileLength(void *handle)
+ {
+     HANDLE FileHandle;
+     DWORD FileSizeHigh;
+     DWORD FileSizeLow;
+     PHYSFS_sint64 retval;
+ 
+     /* Cast the generic handle to a Win32 handle */
+     FileHandle = (HANDLE)handle;
+     
+     if(((FileSizeLow = GetFileSize(FileHandle, &FileSizeHigh))
+         == INVALID_SET_FILE_POINTER) && (GetLastError() != NO_ERROR))
+     {
+         /* Combine the high/low order to create the 64-bit position value */
+         retval = FileSizeHigh;
+         retval = retval << 32;
+         retval |= FileSizeLow;
+     }
+     else
+     {
+         /* Set the error to GetLastError */
+         __PHYSFS_setError(win32strerror());
+ 
+         retval = -1;
+     }
+ 
+     return retval;
+ }
+ 
+ int __PHYSFS_platformEOF(void *opaque)
+ {
+     HANDLE FileHandle;
+     PHYSFS_sint64 FilePosition;
+     int retval = 0;
+ 
+     /* Cast the generic handle to a Win32 handle */
+     FileHandle = (HANDLE)opaque;
+ 
+     /* Get the current position in the file */
+     if((FilePosition = __PHYSFS_platformTell(opaque)) != 0)
+     {
+         /* Non-zero if EOF is equal to the file length - 1 */
+         retval = FilePosition == __PHYSFS_platformFileLength(opaque) - 1;
+     }
+ 
+     return retval;
+ }
+ 
+ int __PHYSFS_platformFlush(void *opaque)
+ {
+     HANDLE FileHandle;
+     int retval;
+ 
+     /* Cast the generic handle to a Win32 handle */
+     FileHandle = (HANDLE)opaque;
+ 
+     /* Close the file */
+     if(!(retval = FlushFileBuffers(FileHandle)))
+     {
+         /* Set the error to GetLastError */
+         __PHYSFS_setError(win32strerror());
+     }
+ 
+     return retval;
+ }
+ 
+ int __PHYSFS_platformClose(void *opaque)
+ {
+     HANDLE FileHandle;
+     int retval;
+ 
+     /* Cast the generic handle to a Win32 handle */
+     FileHandle = (HANDLE)opaque;
+ 
+     /* Close the file */
+     if(!(retval = CloseHandle(FileHandle)))
+     {
+         /* Set the error to GetLastError */
+         __PHYSFS_setError(win32strerror());
+     }
+ 
+     return retval;
+ }
+ 
+ /*
+  * Remove a file or directory entry in the actual filesystem. (path) is
+  *  specified in platform-dependent notation. Note that this deletes files
+  *  _and_ directories, so you might need to do some determination.
+  *  Non-empty directories should report an error and not delete themselves
+  *  or their contents.
+  *
+  * Deleting a symlink should remove the link, not what it points to.
+  *
+  * On error, return zero and set the error message. Return non-zero on 
success.
+  */
+ int __PHYSFS_platformDelete(const char *path)
+ {
+     int retval;
+ 
+     /* If filename is a folder */
+     if(GetFileAttributes(path) == FILE_ATTRIBUTE_DIRECTORY)
+     {
+         retval = RemoveDirectory(path);
+     }
+     else
+     {
+         retval = DeleteFile(path);
+     }
+ 
+     if(!retval)
+     {
+             /* Set the error to GetLastError */
+         __PHYSFS_setError(win32strerror());
+     }
+ 
+     return retval;
+ }
+ 
+ void *__PHYSFS_platformCreateMutex(void)
+ {
+     return (void *)CreateMutex(NULL, FALSE, NULL);
+ }
+ 
+ void __PHYSFS_platformDestroyMutex(void *mutex)
+ {
+     CloseHandle((HANDLE)mutex);
+ }
+ 
+ int __PHYSFS_platformGrabMutex(void *mutex)
+ {
+     int retval;
+ 
+     if(WaitForSingleObject((HANDLE)mutex, INFINITE) == WAIT_FAILED)
+     {
+         /* Our wait failed for some unknown reason */
+         retval = 1;
+     }
+     else
+     {
+         /* Good to go */
+         retval = 0;
+     }
+ 
+     return retval;
+ }
+ 
+ void __PHYSFS_platformReleaseMutex(void *mutex)
+ {
+     ReleaseMutex((HANDLE)mutex);
+ }
  
  /* end of win32.c ... */

--- darwin.c DELETED ---

--- freebsd.c DELETED ---

--- irix.c DELETED ---

--- solaris.c DELETED ---




reply via email to

[Prev in Thread] Current Thread [Next in Thread]