More mountpoint work and other cleanups.
This commit is contained in:
parent
ae093ff0fc
commit
a2cc461727
|
@ -2,6 +2,7 @@
|
|||
* CHANGELOG.
|
||||
*/
|
||||
|
||||
03132005 - More mount work, added PHYSFS_getMountPoint() and more cleanups.
|
||||
03122005 - Added evil GOTO_*_MACRO_* macros. Fixed unix.c to compile again on
|
||||
MacOS X. Added PHYSFS_mount() (thanks, Philip!). Cleaned up the
|
||||
INSTALL and CREDITS files a little. Split off start of
|
||||
|
|
157
physfs.c
157
physfs.c
|
@ -535,6 +535,44 @@ static int sanitizePlatformIndependentPath(const char *src, char *dst)
|
|||
} /* sanitizePlatformIndependentPath */
|
||||
|
||||
|
||||
/*
|
||||
* Figure out if (fname) is part of (h)'s mountpoint. (fname) must be an
|
||||
* output from sanitizePlatformIndependentPath(), so that it is in a known
|
||||
* state.
|
||||
*
|
||||
* This only finds legitimate segments of a mountpoint. If the mountpoint is
|
||||
* "/a/b/c" and (fname) is "/a/b/c", "/", or "/a/b/c/d", then the results are
|
||||
* all zero. "/a/b" will succeed, though.
|
||||
*/
|
||||
static int partOfMountPoint(DirHandle *h, char *fname)
|
||||
{
|
||||
/* !!! FIXME: This code feels gross. */
|
||||
int rc;
|
||||
size_t len, mntpntlen;
|
||||
|
||||
if (h->mountPoint == NULL)
|
||||
return(0);
|
||||
else if (*fname == '\0')
|
||||
return(1);
|
||||
|
||||
len = strlen(fname);
|
||||
mntpntlen = strlen(h->mountPoint);
|
||||
if (len > mntpntlen) /* can't be a subset of mountpoint. */
|
||||
return(0);
|
||||
|
||||
/* if true, must be not a match or a complete match, but not a subset. */
|
||||
if ((len + 1) == mntpntlen)
|
||||
return(0);
|
||||
|
||||
rc = strncmp(fname, h->mountPoint, len); /* !!! FIXME: case insensitive? */
|
||||
if (rc != 0)
|
||||
return(0); /* not a match. */
|
||||
|
||||
/* make sure /a/b matches /a/b/ and not /a/bc ... */
|
||||
return(h->mountPoint[len] == '/');
|
||||
} /* partOfMountPoint */
|
||||
|
||||
|
||||
static DirHandle *createDirHandle(const char *newDir,
|
||||
const char *mountPoint,
|
||||
int forWriting)
|
||||
|
@ -594,6 +632,7 @@ static int freeDirHandle(DirHandle *dh, FileHandle *openList)
|
|||
|
||||
dh->funcs->dirClose(dh->opaque);
|
||||
free(dh->dirName);
|
||||
free(dh->mountPoint);
|
||||
free(dh);
|
||||
return(1);
|
||||
} /* freeDirHandle */
|
||||
|
@ -1023,6 +1062,25 @@ char **PHYSFS_getSearchPath(void)
|
|||
} /* PHYSFS_getSearchPath */
|
||||
|
||||
|
||||
const char *PHYSFS_getMountPoint(const char *dir)
|
||||
{
|
||||
DirHandle *i;
|
||||
__PHYSFS_platformGrabMutex(stateLock);
|
||||
for (i = searchPath; i != NULL; i = i->next)
|
||||
{
|
||||
if (strcmp(i->dirName, dir) == 0)
|
||||
{
|
||||
const char *retval = ((i->mountPoint) ? i->mountPoint : "/");
|
||||
__PHYSFS_platformReleaseMutex(stateLock);
|
||||
return(retval);
|
||||
} /* if */
|
||||
} /* for */
|
||||
__PHYSFS_platformReleaseMutex(stateLock);
|
||||
|
||||
BAIL_MACRO(ERR_NOT_IN_SEARCH_PATH, NULL);
|
||||
} /* PHYSFS_getMountPoint */
|
||||
|
||||
|
||||
void PHYSFS_getSearchPathCallback(PHYSFS_StringCallback callback, void *data)
|
||||
{
|
||||
DirHandle *i;
|
||||
|
@ -1216,17 +1274,20 @@ char * __PHYSFS_convertToDependent(const char *prepend,
|
|||
* With some exceptions (like PHYSFS_mkdir(), which builds multiple subdirs
|
||||
* at a time), you should always pass zero for "allowMissing" for efficiency.
|
||||
*
|
||||
* (fname) must be an output fromsanitizePlatformIndependentPath(), since it
|
||||
* will make sure that path names are in the right format for passing certain
|
||||
* checks. It will also do checks for "insecure" pathnames like ".." which
|
||||
* should be done once instead of once per archive. This also gives us
|
||||
* license to treat (fname) as scratch space in this function.
|
||||
* (fname) must point to an output from sanitizePlatformIndependentPath(),
|
||||
* since it will make sure that path names are in the right format for
|
||||
* passing certain checks. It will also do checks for "insecure" pathnames
|
||||
* like ".." which should be done once instead of once per archive. This also
|
||||
* gives us license to treat (fname) as scratch space in this function.
|
||||
*
|
||||
* Returns non-zero if string is safe, zero if there's a security issue.
|
||||
* PHYSFS_getLastError() will specify what was wrong.
|
||||
* PHYSFS_getLastError() will specify what was wrong. (*fname) will be
|
||||
* updated to point past any mount point elements so it is prepared to
|
||||
* be used with the archiver directly.
|
||||
*/
|
||||
int __PHYSFS_verifySecurity(DirHandle *h, char *fname, int allowMissing)
|
||||
static int verifyPath(DirHandle *h, char **_fname, int allowMissing)
|
||||
{
|
||||
char *fname = *_fname;
|
||||
int retval = 1;
|
||||
char *start;
|
||||
char *end;
|
||||
|
@ -1234,18 +1295,24 @@ int __PHYSFS_verifySecurity(DirHandle *h, char *fname, int allowMissing)
|
|||
if (*fname == '\0') /* quick rejection. */
|
||||
return(1);
|
||||
|
||||
/* !!! FIXME: This codeblock sucks. */
|
||||
if (h->mountPoint != NULL) /* NULL mountpoint means "/". */
|
||||
{
|
||||
/* !!! FIXME: Case insensitive? */
|
||||
size_t mntpntlen = strlen(h->mountPoint);
|
||||
assert(mntpntlen > 1); /* root mount points should be NULL. */
|
||||
size_t len = strlen(fname);
|
||||
/* not under the mountpoint, so skip this archive. */
|
||||
BAIL_IF_MACRO(len < mntpntlen, ERR_NO_SUCH_PATH, 0);
|
||||
retval = strncmp(h->mountPoint, fname, mntpntlen);
|
||||
BAIL_IF_MACRO(len < mntpntlen-1, ERR_NO_SUCH_PATH, 0);
|
||||
/* !!! FIXME: Case insensitive? */
|
||||
retval = strncmp(h->mountPoint, fname, mntpntlen-1);
|
||||
BAIL_IF_MACRO(retval != 0, ERR_NO_SUCH_PATH, 0);
|
||||
fname += mntpntlen; /* move to start of actual archive path. */
|
||||
retval = 1;
|
||||
if (len > mntpntlen-1) /* corner case... */
|
||||
BAIL_IF_MACRO(fname[mntpntlen-1] != '/', ERR_NO_SUCH_PATH, 0);
|
||||
fname += mntpntlen-1; /* move to start of actual archive path. */
|
||||
if (*fname == '/')
|
||||
fname++;
|
||||
*_fname = fname; /* skip mountpoint for later use. */
|
||||
retval = 1; /* may be reset, below. */
|
||||
} /* if */
|
||||
|
||||
start = fname;
|
||||
|
@ -1282,7 +1349,7 @@ int __PHYSFS_verifySecurity(DirHandle *h, char *fname, int allowMissing)
|
|||
} /* if */
|
||||
|
||||
return(retval);
|
||||
} /* __PHYSFS_verifySecurity */
|
||||
} /* verifyPath */
|
||||
|
||||
|
||||
int PHYSFS_mkdir(const char *_dname)
|
||||
|
@ -1301,9 +1368,9 @@ int PHYSFS_mkdir(const char *_dname)
|
|||
__PHYSFS_platformGrabMutex(stateLock);
|
||||
BAIL_IF_MACRO_MUTEX(writeDir == NULL, ERR_NO_WRITE_DIR, stateLock, 0);
|
||||
h = writeDir;
|
||||
BAIL_IF_MACRO_MUTEX(!__PHYSFS_verifySecurity(h,dname,1),NULL,stateLock,0);
|
||||
start = dname;
|
||||
BAIL_IF_MACRO_MUTEX(!verifyPath(h, &dname, 1), NULL, stateLock, 0);
|
||||
|
||||
start = dname;
|
||||
while (1)
|
||||
{
|
||||
end = strchr(start, '/');
|
||||
|
@ -1345,7 +1412,7 @@ int PHYSFS_delete(const char *_fname)
|
|||
|
||||
BAIL_IF_MACRO_MUTEX(writeDir == NULL, ERR_NO_WRITE_DIR, stateLock, 0);
|
||||
h = writeDir;
|
||||
BAIL_IF_MACRO_MUTEX(!__PHYSFS_verifySecurity(h,fname,0),NULL,stateLock,0);
|
||||
BAIL_IF_MACRO_MUTEX(!verifyPath(h, &fname, 0), NULL, stateLock, 0);
|
||||
retval = h->funcs->remove(h->opaque, fname);
|
||||
|
||||
__PHYSFS_platformReleaseMutex(stateLock);
|
||||
|
@ -1365,9 +1432,12 @@ const char *PHYSFS_getRealDir(const char *_fname)
|
|||
__PHYSFS_platformGrabMutex(stateLock);
|
||||
for (i = searchPath; ((i != NULL) && (retval == NULL)); i = i->next)
|
||||
{
|
||||
if (__PHYSFS_verifySecurity(i, fname, 0))
|
||||
char *arcfname = fname;
|
||||
if (partOfMountPoint(i, arcfname))
|
||||
retval = i->dirName;
|
||||
else if (verifyPath(i, &arcfname, 0))
|
||||
{
|
||||
if (i->funcs->exists(i->opaque, fname))
|
||||
if (i->funcs->exists(i->opaque, arcfname))
|
||||
retval = i->dirName;
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
@ -1484,8 +1554,22 @@ void PHYSFS_enumerateFilesCallback(const char *_fname,
|
|||
noSyms = !allowSymLinks;
|
||||
for (i = searchPath; i != NULL; i = i->next)
|
||||
{
|
||||
if (__PHYSFS_verifySecurity(i, fname, 0))
|
||||
i->funcs->enumerateFiles(i->opaque, fname, noSyms, callback, data);
|
||||
char *arcfname = fname;
|
||||
if (partOfMountPoint(i, arcfname))
|
||||
{
|
||||
size_t len = strlen(arcfname);
|
||||
char *ptr = i->mountPoint + ((len) ? len + 1 : 0);
|
||||
char *end = strchr(ptr, '/');
|
||||
assert(end); /* should always find a terminating '/'. */
|
||||
*end = '\0'; /* !!! FIXME: not safe in a callback... */
|
||||
callback(data, ptr);
|
||||
*end = '/'; /* !!! FIXME: not safe in a callback... */
|
||||
} /* if */
|
||||
|
||||
else if (verifyPath(i, &arcfname, 0))
|
||||
{
|
||||
i->funcs->enumerateFiles(i->opaque,arcfname,noSyms,callback,data);
|
||||
} /* else if */
|
||||
} /* for */
|
||||
__PHYSFS_platformReleaseMutex(stateLock);
|
||||
} /* PHYSFS_enumerateFilesCallback */
|
||||
|
@ -1513,8 +1597,12 @@ PHYSFS_sint64 PHYSFS_getLastModTime(const char *_fname)
|
|||
__PHYSFS_platformGrabMutex(stateLock);
|
||||
for (i = searchPath; ((i != NULL) && (!fileExists)); i = i->next)
|
||||
{
|
||||
if (__PHYSFS_verifySecurity(i, fname, 0))
|
||||
retval = i->funcs->getLastModTime(i->opaque, fname, &fileExists);
|
||||
char *arcfname = fname;
|
||||
fileExists = partOfMountPoint(i, arcfname);
|
||||
if (fileExists)
|
||||
retval = 1; /* !!! FIXME: What's the right value? */
|
||||
else if (verifyPath(i, &arcfname, 0))
|
||||
retval = i->funcs->getLastModTime(i->opaque,arcfname,&fileExists);
|
||||
} /* for */
|
||||
__PHYSFS_platformReleaseMutex(stateLock);
|
||||
|
||||
|
@ -1536,8 +1624,11 @@ int PHYSFS_isDirectory(const char *_fname)
|
|||
__PHYSFS_platformGrabMutex(stateLock);
|
||||
for (i = searchPath; ((i != NULL) && (!fileExists)); i = i->next)
|
||||
{
|
||||
if (__PHYSFS_verifySecurity(i, fname, 0))
|
||||
retval = i->funcs->isDirectory(i->opaque, fname, &fileExists);
|
||||
char *arcfname = fname;
|
||||
if ((fileExists = partOfMountPoint(i, arcfname)) != 0)
|
||||
retval = 1;
|
||||
else if (verifyPath(i, &arcfname, 0))
|
||||
retval = i->funcs->isDirectory(i->opaque, arcfname, &fileExists);
|
||||
} /* for */
|
||||
__PHYSFS_platformReleaseMutex(stateLock);
|
||||
|
||||
|
@ -1562,8 +1653,11 @@ int PHYSFS_isSymbolicLink(const char *_fname)
|
|||
__PHYSFS_platformGrabMutex(stateLock);
|
||||
for (i = searchPath; ((i != NULL) && (!fileExists)); i = i->next)
|
||||
{
|
||||
if (__PHYSFS_verifySecurity(i, fname, 0))
|
||||
retval = i->funcs->isSymLink(i->opaque, fname, &fileExists);
|
||||
char *arcfname = fname;
|
||||
if ((fileExists = partOfMountPoint(i, arcfname)) != 0)
|
||||
retval = 0; /* virtual dir...not a symlink. */
|
||||
else if (verifyPath(i, &arcfname, 0))
|
||||
retval = i->funcs->isSymLink(i->opaque, arcfname, &fileExists);
|
||||
} /* for */
|
||||
__PHYSFS_platformReleaseMutex(stateLock);
|
||||
|
||||
|
@ -1586,8 +1680,7 @@ static PHYSFS_File *doOpenWrite(const char *_fname, int appending)
|
|||
BAIL_IF_MACRO_MUTEX(!writeDir, ERR_NO_WRITE_DIR, stateLock, NULL);
|
||||
|
||||
h = writeDir;
|
||||
BAIL_IF_MACRO_MUTEX(!__PHYSFS_verifySecurity(h, fname, 0), NULL,
|
||||
stateLock, NULL);
|
||||
BAIL_IF_MACRO_MUTEX(!verifyPath(h, &fname, 0), NULL, stateLock, NULL);
|
||||
|
||||
f = h->funcs;
|
||||
if (appending)
|
||||
|
@ -1642,15 +1735,19 @@ PHYSFS_File *PHYSFS_openRead(const char *_fname)
|
|||
BAIL_IF_MACRO(!sanitizePlatformIndependentPath(_fname, fname), NULL, 0);
|
||||
|
||||
__PHYSFS_platformGrabMutex(stateLock);
|
||||
|
||||
/* !!! FIXME: should probably be ERR_PATH_NOT_FOUND */
|
||||
BAIL_IF_MACRO_MUTEX(!searchPath, ERR_NOT_IN_SEARCH_PATH, stateLock, NULL);
|
||||
|
||||
/* !!! FIXME: Why aren't we using a for loop here? */
|
||||
i = searchPath;
|
||||
|
||||
do
|
||||
{
|
||||
if (__PHYSFS_verifySecurity(i, fname, 0))
|
||||
char *arcfname = fname;
|
||||
if (verifyPath(i, &arcfname, 0))
|
||||
{
|
||||
opaque = i->funcs->openRead(i->opaque, fname, &fileExists);
|
||||
opaque = i->funcs->openRead(i->opaque, arcfname, &fileExists);
|
||||
if (opaque)
|
||||
break;
|
||||
} /* if */
|
||||
|
|
139
physfs.h
139
physfs.h
|
@ -493,13 +493,17 @@ __EXPORT__ void PHYSFS_freeList(void *listVar);
|
|||
* \fn const char *PHYSFS_getLastError(void)
|
||||
* \brief Get human-readable error information.
|
||||
*
|
||||
* Get the last PhysicsFS error message as a null-terminated string.
|
||||
* This will be NULL if there's been no error since the last call to this
|
||||
* function. The pointer returned by this call points to an internal buffer.
|
||||
* Each thread has a unique error state associated with it, but each time
|
||||
* a new error message is set, it will overwrite the previous one associated
|
||||
* with that thread. It is safe to call this function at anytime, even
|
||||
* before PHYSFS_init().
|
||||
* Get the last PhysicsFS error message as a human-readable, null-terminated
|
||||
* string. This will be NULL if there's been no error since the last call to
|
||||
* this function. The pointer returned by this call points to an internal
|
||||
* buffer. Each thread has a unique error state associated with it, but each
|
||||
* time a new error message is set, it will overwrite the previous one
|
||||
* associated with that thread. It is safe to call this function at anytime,
|
||||
* even before PHYSFS_init().
|
||||
*
|
||||
* It is not wise to expect a specific string of characters here, since the
|
||||
* error message may be localized into an unfamiliar language. These strings
|
||||
* are meant to be passed on directly to the user.
|
||||
*
|
||||
* \return READ ONLY string of last error message.
|
||||
*/
|
||||
|
@ -584,6 +588,8 @@ __EXPORT__ void PHYSFS_permitSymbolicLinks(int allow);
|
|||
* resources by calling PHYSFS_freeList() with the returned pointer.
|
||||
*
|
||||
* \return Null-terminated array of null-terminated strings.
|
||||
*
|
||||
* \sa PHYSFS_getCdRomDirsCallback
|
||||
*/
|
||||
__EXPORT__ char **PHYSFS_getCdRomDirs(void);
|
||||
|
||||
|
@ -668,54 +674,17 @@ __EXPORT__ const char *PHYSFS_getWriteDir(void);
|
|||
__EXPORT__ int PHYSFS_setWriteDir(const char *newDir);
|
||||
|
||||
|
||||
/**
|
||||
* \fn int PHYSFS_mount(const char *newDir, const char *mountPoint, int appendToPath);
|
||||
* \brief Add an archive or directory to the search path.
|
||||
*
|
||||
* If this is a duplicate, the entry is not added again, even though the
|
||||
* function succeeds. You may not add the same archive to two different
|
||||
* mountpoints: duplicate checking is done against the archive and not the
|
||||
* mountpoint.
|
||||
*
|
||||
* When you mount an archive, it is added to a virtual file system...all files
|
||||
* in all of the archives are interpolated into a single hierachical file
|
||||
* tree. Two archives mounted at the same place (or an archive with files
|
||||
* overlapping another mountpoint) may have overlapping files: in such a case,
|
||||
* the file earliest in the search path is selected, and the other files are
|
||||
* inaccessible to the application. This allows archives to be used to
|
||||
* override previous revisions; you can use the mounting mechanism to place
|
||||
* archives at a specific point in the file tree and prevent overlap; this
|
||||
* is useful for downloadable mods that might trample over application data
|
||||
* or each other, for example.
|
||||
*
|
||||
* The mountpoint does not need to exist prior to mounting, which is different
|
||||
* than those familiar with the Unix concept of "mounting" may not expect.
|
||||
* As well, more than one archive can be mounted to the same mountpoint, or
|
||||
* mountpoints and archive contents can overlap...the interpolation mechanism
|
||||
* still functions as usual.
|
||||
*
|
||||
* \param newDir directory or archive to add to the path, in
|
||||
* platform-dependent notation.
|
||||
* \param mountPoint Location in the interpolated tree that this archive
|
||||
* will be "mounted", in platform-independent notation.
|
||||
* NULL or "" is equivalent to "/".
|
||||
* \param appendToPath nonzero to append to search path, zero to prepend.
|
||||
* \return nonzero if added to path, zero on failure (bogus archive, dir
|
||||
* missing, etc). Specifics of the error can be
|
||||
* gleaned from PHYSFS_getLastError().
|
||||
*/
|
||||
__EXPORT__ int PHYSFS_mount(const char *newDir, const char *mountPoint, int appendToPath);
|
||||
|
||||
|
||||
/**
|
||||
* \fn int PHYSFS_addToSearchPath(const char *newDir, int appendToPath)
|
||||
* \brief Add an archive or directory to the search path.
|
||||
*
|
||||
* This is a legacy call, equivalent to:
|
||||
* This is a legacy call in PhysicsFS 2.0, equivalent to:
|
||||
* PHYSFS_mount(newDir, NULL, appendToPath);
|
||||
*
|
||||
* You must use this and not PHYSFS_mount if binary compatibility with
|
||||
* PhysicsFS 1.0 is important (which it may not be for many people).
|
||||
*
|
||||
* \sa PHYSFS_mount
|
||||
* \sa PHYSFS_unmount
|
||||
* \sa PHYSFS_removeFromSearchPath
|
||||
* \sa PHYSFS_getSearchPath
|
||||
*/
|
||||
|
@ -764,6 +733,7 @@ __EXPORT__ int PHYSFS_removeFromSearchPath(const char *oldDir);
|
|||
* \return Null-terminated array of null-terminated strings. NULL if there
|
||||
* was a problem (read: OUT OF MEMORY).
|
||||
*
|
||||
* \sa PHYSFS_getSearchPathCallback
|
||||
* \sa PHYSFS_addToSearchPath
|
||||
* \sa PHYSFS_removeFromSearchPath
|
||||
*/
|
||||
|
@ -910,6 +880,10 @@ __EXPORT__ int PHYSFS_delete(const char *filename);
|
|||
* permitted symlinks, then it will be ignored, and the search for a match
|
||||
* will continue.
|
||||
*
|
||||
* If you specify a fake directory that only exists as a mount point, it'll
|
||||
* be associated with the first archive mounted there, even though that
|
||||
* directory isn't necessarily contained in a real archive.
|
||||
*
|
||||
* \param filename file to look for.
|
||||
* \return READ ONLY string of element of search path containing the
|
||||
* the file in question. NULL if not found.
|
||||
|
@ -952,6 +926,8 @@ __EXPORT__ const char *PHYSFS_getRealDir(const char *filename);
|
|||
*
|
||||
* \param dir directory in platform-independent notation to enumerate.
|
||||
* \return Null-terminated array of null-terminated strings.
|
||||
*
|
||||
* \sa PHYSFS_enumerateFilesCallback
|
||||
*/
|
||||
__EXPORT__ char **PHYSFS_enumerateFiles(const char *dir);
|
||||
|
||||
|
@ -1921,6 +1897,73 @@ typedef struct
|
|||
__EXPORT__ int PHYSFS_setAllocator(PHYSFS_Allocator *allocator);
|
||||
|
||||
|
||||
/**
|
||||
* \fn int PHYSFS_mount(const char *newDir, const char *mountPoint, int appendToPath);
|
||||
* \brief Add an archive or directory to the search path.
|
||||
*
|
||||
* If this is a duplicate, the entry is not added again, even though the
|
||||
* function succeeds. You may not add the same archive to two different
|
||||
* mountpoints: duplicate checking is done against the archive and not the
|
||||
* mountpoint.
|
||||
*
|
||||
* When you mount an archive, it is added to a virtual file system...all files
|
||||
* in all of the archives are interpolated into a single hierachical file
|
||||
* tree. Two archives mounted at the same place (or an archive with files
|
||||
* overlapping another mountpoint) may have overlapping files: in such a case,
|
||||
* the file earliest in the search path is selected, and the other files are
|
||||
* inaccessible to the application. This allows archives to be used to
|
||||
* override previous revisions; you can use the mounting mechanism to place
|
||||
* archives at a specific point in the file tree and prevent overlap; this
|
||||
* is useful for downloadable mods that might trample over application data
|
||||
* or each other, for example.
|
||||
*
|
||||
* The mountpoint does not need to exist prior to mounting, which is different
|
||||
* than those familiar with the Unix concept of "mounting" may not expect.
|
||||
* As well, more than one archive can be mounted to the same mountpoint, or
|
||||
* mountpoints and archive contents can overlap...the interpolation mechanism
|
||||
* still functions as usual.
|
||||
*
|
||||
* \param newDir directory or archive to add to the path, in
|
||||
* platform-dependent notation.
|
||||
* \param mountPoint Location in the interpolated tree that this archive
|
||||
* will be "mounted", in platform-independent notation.
|
||||
* NULL or "" is equivalent to "/".
|
||||
* \param appendToPath nonzero to append to search path, zero to prepend.
|
||||
* \return nonzero if added to path, zero on failure (bogus archive, dir
|
||||
* missing, etc). Specifics of the error can be
|
||||
* gleaned from PHYSFS_getLastError().
|
||||
*
|
||||
* \sa PHYSFS_removeFromSearchPath
|
||||
* \sa PHYSFS_getSearchPath
|
||||
* \sa PHYSFS_getMountPoint
|
||||
*/
|
||||
__EXPORT__ int PHYSFS_mount(const char *newDir, const char *mountPoint, int appendToPath);
|
||||
|
||||
/**
|
||||
* \fn int PHYSFS_getMountPoint(const char *dir);
|
||||
* \brief Determine a mounted archive's mountpoint.
|
||||
*
|
||||
* You give this function the name of an archive or dir you successfully
|
||||
* added to the search path, and it reports the location in the interpolated
|
||||
* tree where it is mounted. Files mounted with a NULL mountpoint or through
|
||||
* PHYSFS_addToSearchPath() will report "/". The return value is READ ONLY
|
||||
* and valid until the archive is removed from the search path.
|
||||
*
|
||||
* \param dir directory or archive previously added to the path, in
|
||||
* platform-dependent notation. This must match the string
|
||||
* used when adding, even if your string would also reference
|
||||
* the same file with a different string of characters.
|
||||
* \return READ-ONLY string of mount point if added to path, NULL on failure
|
||||
* (bogus archive, etc) Specifics of the error can be gleaned from
|
||||
* PHYSFS_getLastError().
|
||||
*
|
||||
* \sa PHYSFS_removeFromSearchPath
|
||||
* \sa PHYSFS_getSearchPath
|
||||
* \sa PHYSFS_getMountPoint
|
||||
*/
|
||||
__EXPORT__ const char *PHYSFS_getMountPoint(const char *dir);
|
||||
|
||||
|
||||
/*
|
||||
* it is not safe to call physfs functions in these callbacks, as they may
|
||||
* be holding non recursive mutexes.
|
||||
|
|
Loading…
Reference in New Issue