Now handles Finder aliases as if they were symlinks.
This commit is contained in:
parent
ada7128625
commit
c0b501934a
|
@ -8,13 +8,35 @@
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.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
|
* 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,
|
* 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.
|
* 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__
|
#ifdef __PHYSFS_CARBONIZED__ /* this is currently not defined anywhere. */
|
||||||
#include <Carbon.h>
|
#include <Carbon.h>
|
||||||
#else
|
#else
|
||||||
#include <OSUtils.h>
|
#include <OSUtils.h>
|
||||||
|
@ -25,6 +47,7 @@
|
||||||
#include <MacMemory.h>
|
#include <MacMemory.h>
|
||||||
#include <Events.h>
|
#include <Events.h>
|
||||||
#include <DriverGestalt.h>
|
#include <DriverGestalt.h>
|
||||||
|
#include <Aliases.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define __PHYSICSFS_INTERNAL__
|
#define __PHYSICSFS_INTERNAL__
|
||||||
|
@ -218,7 +241,7 @@ int __PHYSFS_platformStricmp(const char *x, const char *y)
|
||||||
} /* __PHYSFS_platformStricmp */
|
} /* __PHYSFS_platformStricmp */
|
||||||
|
|
||||||
|
|
||||||
static OSErr fnameToFSSpec(const char *fname, FSSpec *spec)
|
static OSErr fnameToFSSpecNoAlias(const char *fname, FSSpec *spec)
|
||||||
{
|
{
|
||||||
OSErr err;
|
OSErr err;
|
||||||
Str255 str255;
|
Str255 str255;
|
||||||
|
@ -238,6 +261,77 @@ static OSErr fnameToFSSpec(const char *fname, FSSpec *spec)
|
||||||
|
|
||||||
err = FSMakeFSSpec(0, 0, str255, spec);
|
err = FSMakeFSSpec(0, 0, str255, spec);
|
||||||
return(err);
|
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 */
|
} /* fnameToFSSpec */
|
||||||
|
|
||||||
|
|
||||||
|
@ -250,7 +344,36 @@ int __PHYSFS_platformExists(const char *fname)
|
||||||
|
|
||||||
int __PHYSFS_platformIsSymLink(const char *fname)
|
int __PHYSFS_platformIsSymLink(const char *fname)
|
||||||
{
|
{
|
||||||
return(0); /* !!! FIXME: What happens if (fname) is an alias? */
|
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 */
|
} /* __PHYSFS_platformIsSymlink */
|
||||||
|
|
||||||
|
|
||||||
|
@ -340,6 +463,10 @@ LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname,
|
||||||
|
|
||||||
for (i = 1; i <= max; i++)
|
for (i = 1; i <= max; i++)
|
||||||
{
|
{
|
||||||
|
FSSpec aliasspec;
|
||||||
|
Boolean alias = 0;
|
||||||
|
Boolean folder = 0;
|
||||||
|
|
||||||
memset(&infoPB, '\0', sizeof (CInfoPBRec));
|
memset(&infoPB, '\0', sizeof (CInfoPBRec));
|
||||||
str255[0] = 0;
|
str255[0] = 0;
|
||||||
infoPB.dirInfo.ioNamePtr = str255; /* store name in here. */
|
infoPB.dirInfo.ioNamePtr = str255; /* store name in here. */
|
||||||
|
@ -349,6 +476,17 @@ LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname,
|
||||||
if (PBGetCatInfoSync(&infoPB) != noErr)
|
if (PBGetCatInfoSync(&infoPB) != noErr)
|
||||||
continue; /* skip this file. Oh well. */
|
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));
|
l = (LinkedStringList *) malloc(sizeof (LinkedStringList));
|
||||||
if (l == NULL)
|
if (l == NULL)
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue