First chunk of PHYSFS_mount() implementation. Incomplete!
This commit is contained in:
parent
389a4d826a
commit
93adbf1d88
2
TODO
2
TODO
|
@ -45,6 +45,8 @@ Some might be dupes, some might be done already.
|
||||||
- Should file enumeration return an error or set error state?
|
- Should file enumeration return an error or set error state?
|
||||||
- Ryanify pocketpc.c ...
|
- Ryanify pocketpc.c ...
|
||||||
- Update internal zlib?
|
- Update internal zlib?
|
||||||
|
- Split verifySecurity() off into sanitizePath() and hook it into mount point
|
||||||
|
initialization.
|
||||||
- Get svn hooks working.
|
- Get svn hooks working.
|
||||||
- maybe other stuff.
|
- maybe other stuff.
|
||||||
|
|
||||||
|
|
65
physfs.c
65
physfs.c
|
@ -25,6 +25,7 @@ typedef struct __PHYSFS_DIRHANDLE__
|
||||||
{
|
{
|
||||||
void *opaque; /* Instance data unique to the archiver. */
|
void *opaque; /* Instance data unique to the archiver. */
|
||||||
char *dirName; /* Path to archive in platform-dependent notation. */
|
char *dirName; /* Path to archive in platform-dependent notation. */
|
||||||
|
char *mountPoint; /* Mountpoint in virtual file tree. */
|
||||||
const PHYSFS_Archiver *funcs; /* Ptr to archiver info for this handle. */
|
const PHYSFS_Archiver *funcs; /* Ptr to archiver info for this handle. */
|
||||||
struct __PHYSFS_DIRHANDLE__ *next; /* linked list stuff. */
|
struct __PHYSFS_DIRHANDLE__ *next; /* linked list stuff. */
|
||||||
} DirHandle;
|
} DirHandle;
|
||||||
|
@ -440,6 +441,7 @@ static DirHandle *tryOpenDir(const PHYSFS_Archiver *funcs,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memset(retval, '\0', sizeof (DirHandle));
|
memset(retval, '\0', sizeof (DirHandle));
|
||||||
|
retval->mountPoint = NULL;
|
||||||
retval->funcs = funcs;
|
retval->funcs = funcs;
|
||||||
retval->opaque = opaque;
|
retval->opaque = opaque;
|
||||||
} /* else */
|
} /* else */
|
||||||
|
@ -487,25 +489,41 @@ static DirHandle *openDirectory(const char *d, int forWriting)
|
||||||
} /* openDirectory */
|
} /* openDirectory */
|
||||||
|
|
||||||
|
|
||||||
static DirHandle *createDirHandle(const char *newDir, int forWriting)
|
static DirHandle *createDirHandle(const char *newDir,
|
||||||
|
const char *mountPoint,
|
||||||
|
int forWriting)
|
||||||
{
|
{
|
||||||
DirHandle *dirHandle = NULL;
|
DirHandle *dirHandle = NULL;
|
||||||
|
GOTO_IF_MACRO(!newDir, ERR_INVALID_ARGUMENT, badDirHandle);
|
||||||
BAIL_IF_MACRO(newDir == NULL, ERR_INVALID_ARGUMENT, NULL);
|
|
||||||
|
|
||||||
dirHandle = openDirectory(newDir, forWriting);
|
dirHandle = openDirectory(newDir, forWriting);
|
||||||
BAIL_IF_MACRO(dirHandle == NULL, NULL, NULL);
|
GOTO_IF_MACRO(!dirHandle, NULL, badDirHandle);
|
||||||
|
|
||||||
dirHandle->dirName = (char *) malloc(strlen(newDir) + 1);
|
dirHandle->dirName = (char *) malloc(strlen(newDir) + 1);
|
||||||
if (dirHandle->dirName == NULL)
|
GOTO_IF_MACRO(!dirHandle->dirName, ERR_OUT_OF_MEMORY, badDirHandle);
|
||||||
|
strcpy(dirHandle->dirName, newDir);
|
||||||
|
|
||||||
|
if ((mountPoint != NULL) && (*mountPoint != '\0'))
|
||||||
{
|
{
|
||||||
dirHandle->funcs->dirClose(dirHandle->opaque);
|
/* !!! FIXME: Sanitize the string here. */
|
||||||
free(dirHandle);
|
dirHandle->mountPoint = (char *) malloc(strlen(mountPoint) + 2);
|
||||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
|
GOTO_IF_MACRO(!dirHandle->mountPoint, ERR_OUT_OF_MEMORY, badDirHandle);
|
||||||
|
strcpy(dirHandle->mountPoint, mountPoint);
|
||||||
|
strcat(dirHandle->mountPoint, "/");
|
||||||
} /* if */
|
} /* if */
|
||||||
|
|
||||||
strcpy(dirHandle->dirName, newDir);
|
|
||||||
return(dirHandle);
|
return(dirHandle);
|
||||||
|
|
||||||
|
badDirHandle:
|
||||||
|
if (dirHandle != NULL)
|
||||||
|
{
|
||||||
|
dirHandle->funcs->dirClose(dirHandle->opaque);
|
||||||
|
free(dirHandle->dirName);
|
||||||
|
free(dirHandle->mountPoint);
|
||||||
|
free(dirHandle);
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
return(NULL);
|
||||||
} /* createDirHandle */
|
} /* createDirHandle */
|
||||||
|
|
||||||
|
|
||||||
|
@ -859,7 +877,7 @@ int PHYSFS_setWriteDir(const char *newDir)
|
||||||
|
|
||||||
if (newDir != NULL)
|
if (newDir != NULL)
|
||||||
{
|
{
|
||||||
writeDir = createDirHandle(newDir, 1);
|
writeDir = createDirHandle(newDir, NULL, 1);
|
||||||
retval = (writeDir != NULL);
|
retval = (writeDir != NULL);
|
||||||
} /* if */
|
} /* if */
|
||||||
|
|
||||||
|
@ -869,12 +887,15 @@ int PHYSFS_setWriteDir(const char *newDir)
|
||||||
} /* PHYSFS_setWriteDir */
|
} /* PHYSFS_setWriteDir */
|
||||||
|
|
||||||
|
|
||||||
int PHYSFS_addToSearchPath(const char *newDir, int appendToPath)
|
int PHYSFS_mount(const char *newDir, const char *mountPoint, int appendToPath)
|
||||||
{
|
{
|
||||||
DirHandle *dh;
|
DirHandle *dh;
|
||||||
DirHandle *prev = NULL;
|
DirHandle *prev = NULL;
|
||||||
DirHandle *i;
|
DirHandle *i;
|
||||||
|
|
||||||
|
BAIL_IF_MACRO(newDir == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||||
|
BAIL_IF_MACRO(mountPoint == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||||
|
|
||||||
__PHYSFS_platformGrabMutex(stateLock);
|
__PHYSFS_platformGrabMutex(stateLock);
|
||||||
|
|
||||||
for (i = searchPath; i != NULL; i = i->next)
|
for (i = searchPath; i != NULL; i = i->next)
|
||||||
|
@ -884,7 +905,7 @@ int PHYSFS_addToSearchPath(const char *newDir, int appendToPath)
|
||||||
prev = i;
|
prev = i;
|
||||||
} /* for */
|
} /* for */
|
||||||
|
|
||||||
dh = createDirHandle(newDir, 0);
|
dh = createDirHandle(newDir, mountPoint, 0);
|
||||||
BAIL_IF_MACRO_MUTEX(dh == NULL, NULL, stateLock, 0);
|
BAIL_IF_MACRO_MUTEX(dh == NULL, NULL, stateLock, 0);
|
||||||
|
|
||||||
if (appendToPath)
|
if (appendToPath)
|
||||||
|
@ -902,6 +923,12 @@ int PHYSFS_addToSearchPath(const char *newDir, int appendToPath)
|
||||||
|
|
||||||
__PHYSFS_platformReleaseMutex(stateLock);
|
__PHYSFS_platformReleaseMutex(stateLock);
|
||||||
return(1);
|
return(1);
|
||||||
|
} /* PHYSFS_mount */
|
||||||
|
|
||||||
|
|
||||||
|
int PHYSFS_addToSearchPath(const char *newDir, int appendToPath)
|
||||||
|
{
|
||||||
|
return(PHYSFS_mount(newDir, "/", appendToPath));
|
||||||
} /* PHYSFS_addToSearchPath */
|
} /* PHYSFS_addToSearchPath */
|
||||||
|
|
||||||
|
|
||||||
|
@ -1130,7 +1157,8 @@ char * __PHYSFS_convertToDependent(const char *prepend,
|
||||||
* Verify that (fname) (in platform-independent notation), in relation
|
* Verify that (fname) (in platform-independent notation), in relation
|
||||||
* to (h) is secure. That means that each element of fname is checked
|
* to (h) is secure. That means that each element of fname is checked
|
||||||
* for symlinks (if they aren't permitted). Also, elements such as
|
* for symlinks (if they aren't permitted). Also, elements such as
|
||||||
* ".", "..", or ":" are flagged.
|
* ".", "..", or ":" are flagged. This also allows for quick rejection of
|
||||||
|
* files that exist outside an archive's mountpoint.
|
||||||
*
|
*
|
||||||
* With some exceptions (like PHYSFS_mkdir(), which builds multiple subdirs
|
* With some exceptions (like PHYSFS_mkdir(), which builds multiple subdirs
|
||||||
* at a time), you should always pass zero for "allowMissing" for efficiency.
|
* at a time), you should always pass zero for "allowMissing" for efficiency.
|
||||||
|
@ -1148,6 +1176,17 @@ int __PHYSFS_verifySecurity(DirHandle *h, const char *fname, int allowMissing)
|
||||||
if (*fname == '\0') /* quick rejection. */
|
if (*fname == '\0') /* quick rejection. */
|
||||||
return(1);
|
return(1);
|
||||||
|
|
||||||
|
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. */
|
||||||
|
if (strncmp(h->mountPoint, fname, mntpntlen) != 0)
|
||||||
|
return(0); /* not under the mountpoint, so skip this archive. */
|
||||||
|
|
||||||
|
fname += mntpntlen; /* move to start of actual archive path. */
|
||||||
|
} /* if */
|
||||||
|
|
||||||
/* !!! FIXME: Can we ditch this malloc()? */
|
/* !!! FIXME: Can we ditch this malloc()? */
|
||||||
start = str = malloc(strlen(fname) + 1);
|
start = str = malloc(strlen(fname) + 1);
|
||||||
BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, 0);
|
BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||||
|
|
70
physfs.h
70
physfs.h
|
@ -78,13 +78,13 @@
|
||||||
* it correctly.
|
* it correctly.
|
||||||
*
|
*
|
||||||
* Files opened through PhysicsFS may NOT contain "." or ".." or ":" as dir
|
* Files opened through PhysicsFS may NOT contain "." or ".." or ":" as dir
|
||||||
* elements. Not only are these meaningless on MacOS and/or Unix, they are a
|
* elements. Not only are these meaningless on MacOS Classic and/or Unix,
|
||||||
* security hole. Also, symbolic links (which can be found in some archive
|
* they are a security hole. Also, symbolic links (which can be found in
|
||||||
* types and directly in the filesystem on Unix platforms) are NOT followed
|
* some archive types and directly in the filesystem on Unix platforms) are
|
||||||
* until you call PHYSFS_permitSymbolicLinks(). That's left to your own
|
* NOT followed until you call PHYSFS_permitSymbolicLinks(). That's left to
|
||||||
* discretion, as following a symlink can allow for access outside the write
|
* your own discretion, as following a symlink can allow for access outside
|
||||||
* dir and search paths. There is no mechanism for creating new symlinks in
|
* the write dir and search paths. For portability, there is no mechanism for
|
||||||
* PhysicsFS.
|
* creating new symlinks in PhysicsFS.
|
||||||
*
|
*
|
||||||
* The write dir is not included in the search path unless you specifically
|
* The write dir is not included in the search path unless you specifically
|
||||||
* add it. While you CAN change the write dir as many times as you like,
|
* add it. While you CAN change the write dir as many times as you like,
|
||||||
|
@ -110,6 +110,18 @@
|
||||||
* PHYSFS_getBaseDir(), and PHYSFS_getUserDir() for info on what those
|
* PHYSFS_getBaseDir(), and PHYSFS_getUserDir() for info on what those
|
||||||
* are and how they can help you determine an optimal search path.
|
* are and how they can help you determine an optimal search path.
|
||||||
*
|
*
|
||||||
|
* PhysicsFS 2.0 adds the concept of "mounting" archives to arbitrary points
|
||||||
|
* in the search path. If a zipfile contains "maps/level.map" and you mount
|
||||||
|
* that archive at "mods/mymod", then you would have to open
|
||||||
|
* "mods/mymod/maps/level.map" to access the file, even though "mods/mymod"
|
||||||
|
* isn't actually specified in the .zip file. Unlike the Unix mentality of
|
||||||
|
* mounting a filesystem, "mods/mymod" doesn't actually have to exist when
|
||||||
|
* mounting the zipfile. It's a "virtual" directory. The mounting mechanism
|
||||||
|
* allows the developer to seperate archives in the tree and avoid trampling
|
||||||
|
* over files when added new archives, such as including mod support in a
|
||||||
|
* game...keeping external content on a tight leash in this manner can be of
|
||||||
|
* utmost importance to some applications.
|
||||||
|
*
|
||||||
* PhysicsFS is mostly thread safe. The error messages returned by
|
* PhysicsFS is mostly thread safe. The error messages returned by
|
||||||
* PHYSFS_getLastError are unique by thread, and library-state-setting
|
* PHYSFS_getLastError are unique by thread, and library-state-setting
|
||||||
* functions are mutex'd. For efficiency, individual file accesses are
|
* functions are mutex'd. For efficiency, individual file accesses are
|
||||||
|
@ -124,7 +136,7 @@
|
||||||
* Note that archives need not be named as such: if you have a ZIP file and
|
* Note that archives need not be named as such: if you have a ZIP file and
|
||||||
* rename it with a .PKG extension, the file will still be recognized as a
|
* rename it with a .PKG extension, the file will still be recognized as a
|
||||||
* ZIP archive by PhysicsFS; the file's contents are used to determine its
|
* ZIP archive by PhysicsFS; the file's contents are used to determine its
|
||||||
* type.
|
* type where possible.
|
||||||
*
|
*
|
||||||
* Currently supported archive types:
|
* Currently supported archive types:
|
||||||
* - .ZIP (pkZip/WinZip/Info-ZIP compatible)
|
* - .ZIP (pkZip/WinZip/Info-ZIP compatible)
|
||||||
|
@ -133,12 +145,13 @@
|
||||||
* - .HOG (Descent I/II HOG file archives)
|
* - .HOG (Descent I/II HOG file archives)
|
||||||
* - .MVL (Descent II movielib archives)
|
* - .MVL (Descent II movielib archives)
|
||||||
* - .WAD (DOOM engine archives)
|
* - .WAD (DOOM engine archives)
|
||||||
|
* - .MIX (Older Westwood games archives)
|
||||||
*
|
*
|
||||||
* Please see the file LICENSE in the source's root directory for licensing
|
* Please see the file LICENSE in the source's root directory for licensing
|
||||||
* and redistribution rights.
|
* and redistribution rights.
|
||||||
*
|
*
|
||||||
* Please see the file CREDITS in the source's root directory for a complete
|
* Please see the file CREDITS in the source's root directory for a more or
|
||||||
* list of who's responsible for this.
|
* less complete list of who's responsible for this.
|
||||||
*
|
*
|
||||||
* \author Ryan C. Gordon.
|
* \author Ryan C. Gordon.
|
||||||
*/
|
*/
|
||||||
|
@ -656,19 +669,52 @@ __EXPORT__ int PHYSFS_setWriteDir(const char *newDir);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \fn int PHYSFS_addToSearchPath(const char *newDir, int appendToPath)
|
* \fn int PHYSFS_mount(const char *newDir, const char *mountPoint, int appendToPath);
|
||||||
* \brief Add an archive or directory to the search path.
|
* \brief Add an archive or directory to the search path.
|
||||||
*
|
*
|
||||||
* If this is a duplicate, the entry is not added again, even though the
|
* If this is a duplicate, the entry is not added again, even though the
|
||||||
* function succeeds.
|
* 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
|
* \param newDir directory or archive to add to the path, in
|
||||||
* platform-dependent notation.
|
* platform-dependent notation.
|
||||||
|
* \param mountPoint Location in the interpolated tree that this archive
|
||||||
|
* will be "mounted", in platform-independent notation.
|
||||||
* \param appendToPath nonzero to append to search path, zero to prepend.
|
* \param appendToPath nonzero to append to search path, zero to prepend.
|
||||||
* \return nonzero if added to path, zero on failure (bogus archive, dir
|
* \return nonzero if added to path, zero on failure (bogus archive, dir
|
||||||
* missing, etc). Specifics of the error can be
|
* missing, etc). Specifics of the error can be
|
||||||
* gleaned from PHYSFS_getLastError().
|
* 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:
|
||||||
|
* PHYSFS_mount(newDir, "/", appendToPath);
|
||||||
|
*
|
||||||
|
* \sa PHYSFS_mount
|
||||||
|
* \sa PHYSFS_unmount
|
||||||
* \sa PHYSFS_removeFromSearchPath
|
* \sa PHYSFS_removeFromSearchPath
|
||||||
* \sa PHYSFS_getSearchPath
|
* \sa PHYSFS_getSearchPath
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue