⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 macclassic.c

📁 嵌入式环境下的GUI
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * MacOS Classic support routines for PhysicsFS. * * Please see the file LICENSE in the source's root directory. * *  This file written by Ryan C. Gordon. */#if HAVE_CONFIG_H#  include <config.h>#endif#include <stdio.h>#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 const char *get_macos_error_string(OSErr err){    if (err == noErr)        return(NULL);    switch (err)    {        case fnfErr: return(ERR_NO_SUCH_FILE);        case notOpenErr: return(ERR_NO_SUCH_VOLUME);        case dirFulErr: return(ERR_DIRECTORY_FULL);        case dskFulErr: return(ERR_DISK_FULL);        case nsvErr: return(ERR_NO_SUCH_VOLUME);        case ioErr: return(ERR_IO_ERROR);        case bdNamErr: return(ERR_BAD_FILENAME);        case fnOpnErr: return(ERR_NOT_A_HANDLE);        case eofErr: return(ERR_PAST_EOF);        case posErr: return(ERR_SEEK_OUT_OF_RANGE);        case tmfoErr: return(ERR_TOO_MANY_HANDLES);        case wPrErr: return(ERR_VOL_LOCKED_HW);        case fLckdErr: return(ERR_FILE_LOCKED);        case vLckdErr: return(ERR_VOL_LOCKED_SW);        case fBsyErr: return(ERR_FILE_OR_DIR_BUSY);        case dupFNErr: return(ERR_FILE_EXISTS);        case opWrErr: return(ERR_FILE_ALREADY_OPEN_W);        case rfNumErr: return(ERR_INVALID_REFNUM);        case gfpErr: return(ERR_GETTING_FILE_POS);        case volOffLinErr: return(ERR_VOLUME_OFFLINE);        case permErr: return(ERR_PERMISSION_DENIED);        case volOnLinErr: return(ERR_VOL_ALREADY_ONLINE);        case nsDrvErr: return(ERR_NO_SUCH_DRIVE);        case noMacDskErr: return(ERR_NOT_MAC_DISK);        case extFSErr: return(ERR_VOL_EXTERNAL_FS);        case fsRnErr: return(ERR_PROBLEM_RENAME);        case badMDBErr: return(ERR_BAD_MASTER_BLOCK);        case wrPermErr: return(ERR_PERMISSION_DENIED);        case memFullErr: return(ERR_OUT_OF_MEMORY);        case dirNFErr: return(ERR_NO_SUCH_PATH);        case tmwdoErr: return(ERR_TOO_MANY_HANDLES);        case badMovErr: return(ERR_CANT_MOVE_FORBIDDEN);        case wrgVolTypErr: return(ERR_WRONG_VOL_TYPE);        case volGoneErr: return(ERR_SERVER_VOL_LOST);        case errFSNameTooLong: return(ERR_BAD_FILENAME);        case errFSNotAFolder: return(ERR_NOT_A_DIR);        /*case errFSNotAFile: return(ERR_NOT_A_FILE);*/        case fidNotFound: return(ERR_FILE_ID_NOT_FOUND);        case fidExists: return(ERR_FILE_ID_EXISTS);        case afpAccessDenied: return(ERR_ACCESS_DENIED);        case afpNoServer: return(ERR_SERVER_NO_RESPOND);        case afpUserNotAuth: return(ERR_USER_AUTH_FAILED);        case afpPwdExpiredErr: return(ERR_PWORD_EXPIRED);        case paramErr:        case errFSBadFSRef:        case errFSBadBuffer:        case errFSMissingName:        case errFSBadPosMode:        case errFSBadAllocFlags:        case errFSBadItemCount:        case errFSBadSearchParams:        case afpDenyConflict:            return(ERR_PHYSFS_BAD_OS_CALL);        default: return(ERR_MACOS_GENERIC);    } /* switch */    return(NULL);} /* get_macos_error_string */static OSErr oserr(OSErr retval){    char buf[sizeof (ERR_MACOS_GENERIC) + 32];    const char *errstr = get_macos_error_string(retval);    if (strcmp(errstr, ERR_MACOS_GENERIC) == 0)    {        snprintf(buf, sizeof (buf), ERR_MACOS_GENERIC, (int) retval);        errstr = buf;    } /* if */    if (errstr != NULL)        __PHYSFS_setError(errstr);    return(retval);} /* oserr */static struct ProcessInfoRec procInfo;static FSSpec procfsspec;int __PHYSFS_platformInit(void){    OSErr err;    ProcessSerialNumber psn;    BAIL_IF_MACRO(oserr(GetCurrentProcess(&psn)) != noErr, NULL, 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(oserr(err) != noErr, NULL, 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 (oserr(PBGetCatInfoSync(&infoPB)) != noErr)        {            if (retval != NULL)                free(retval);            return(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, NULL, 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 = oserr(FSMakeFSSpec(0, 0, str255, spec));    return(err);} /* fnameToFSSpecNoAlias */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_NO_SUCH_FILE, err); /* just in case */        ptr = strchr(ptr + 1, ':');        BAIL_IF_MACRO(!ptr, ERR_NO_SUCH_FILE, err); /* just in case */        *ptr = '\0';        err = fnameToFSSpecNoAlias(path, spec); /* get first dir. */        BAIL_IF_MACRO(oserr(err) != noErr, NULL, err);        start = ptr;        ptr = strchr(start + 1, ':');        /* Now check each element of the path for aliases... */        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 just a bogus path. */                return(fnameToFSSpecNoAlias(fname, spec)); /* reset */            if ((infoPB.dirInfo.ioFlAttrib & kioFlAttribDirMask) != 0)                spec->parID = infoPB.dirInfo.ioDrDirID;            if (ptr != NULL)  /* terminate string after next element. */                *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;  /* move to the next element. */            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(oserr(err) != noErr, NULL, err);        err = ResolveAliasFileWithMountFlags(spec, 1, &folder, &alias, 0);        BAIL_IF_MACRO(oserr(err) != noErr, NULL, err);    } /* else */    return(noErr);  /* w00t. */} /* fnameToFSSpec */int __PHYSFS_platformExists(const char *fname){    FSSpec spec;    return(fnameToFSSpec(fname, &spec) == noErr);} /* __PHYSFS_platformExists */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -