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?
|
||||
- Ryanify pocketpc.c ...
|
||||
- Update internal zlib?
|
||||
- Split verifySecurity() off into sanitizePath() and hook it into mount point
|
||||
initialization.
|
||||
- Get svn hooks working.
|
||||
- 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. */
|
||||
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. */
|
||||
struct __PHYSFS_DIRHANDLE__ *next; /* linked list stuff. */
|
||||
} DirHandle;
|
||||
|
@ -440,6 +441,7 @@ static DirHandle *tryOpenDir(const PHYSFS_Archiver *funcs,
|
|||
else
|
||||
{
|
||||
memset(retval, '\0', sizeof (DirHandle));
|
||||
retval->mountPoint = NULL;
|
||||
retval->funcs = funcs;
|
||||
retval->opaque = opaque;
|
||||
} /* else */
|
||||
|
@ -487,25 +489,41 @@ static DirHandle *openDirectory(const char *d, int forWriting)
|
|||
} /* openDirectory */
|
||||
|
||||
|
||||
static DirHandle *createDirHandle(const char *newDir, int forWriting)
|
||||
static DirHandle *createDirHandle(const char *newDir,
|
||||
const char *mountPoint,
|
||||
int forWriting)
|
||||
{
|
||||
DirHandle *dirHandle = NULL;
|
||||
|
||||
BAIL_IF_MACRO(newDir == NULL, ERR_INVALID_ARGUMENT, NULL);
|
||||
GOTO_IF_MACRO(!newDir, ERR_INVALID_ARGUMENT, badDirHandle);
|
||||
|
||||
dirHandle = openDirectory(newDir, forWriting);
|
||||
BAIL_IF_MACRO(dirHandle == NULL, NULL, NULL);
|
||||
GOTO_IF_MACRO(!dirHandle, NULL, badDirHandle);
|
||||
|
||||
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);
|
||||
free(dirHandle);
|
||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
|
||||
/* !!! FIXME: Sanitize the string here. */
|
||||
dirHandle->mountPoint = (char *) malloc(strlen(mountPoint) + 2);
|
||||
GOTO_IF_MACRO(!dirHandle->mountPoint, ERR_OUT_OF_MEMORY, badDirHandle);
|
||||
strcpy(dirHandle->mountPoint, mountPoint);
|
||||
strcat(dirHandle->mountPoint, "/");
|
||||
} /* if */
|
||||
|
||||
strcpy(dirHandle->dirName, newDir);
|
||||
return(dirHandle);
|
||||
|
||||
badDirHandle:
|
||||
if (dirHandle != NULL)
|
||||
{
|
||||
dirHandle->funcs->dirClose(dirHandle->opaque);
|
||||
free(dirHandle->dirName);
|
||||
free(dirHandle->mountPoint);
|
||||
free(dirHandle);
|
||||
} /* if */
|
||||
|
||||
return(NULL);
|
||||
} /* createDirHandle */
|
||||
|
||||
|
||||
|
@ -859,7 +877,7 @@ int PHYSFS_setWriteDir(const char *newDir)
|
|||
|
||||
if (newDir != NULL)
|
||||
{
|
||||
writeDir = createDirHandle(newDir, 1);
|
||||
writeDir = createDirHandle(newDir, NULL, 1);
|
||||
retval = (writeDir != NULL);
|
||||
} /* if */
|
||||
|
||||
|
@ -869,12 +887,15 @@ int PHYSFS_setWriteDir(const char *newDir)
|
|||
} /* PHYSFS_setWriteDir */
|
||||
|
||||
|
||||
int PHYSFS_addToSearchPath(const char *newDir, int appendToPath)
|
||||
int PHYSFS_mount(const char *newDir, const char *mountPoint, int appendToPath)
|
||||
{
|
||||
DirHandle *dh;
|
||||
DirHandle *prev = NULL;
|
||||
DirHandle *i;
|
||||
|
||||
BAIL_IF_MACRO(newDir == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||
BAIL_IF_MACRO(mountPoint == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||
|
||||
__PHYSFS_platformGrabMutex(stateLock);
|
||||
|
||||
for (i = searchPath; i != NULL; i = i->next)
|
||||
|
@ -884,7 +905,7 @@ int PHYSFS_addToSearchPath(const char *newDir, int appendToPath)
|
|||
prev = i;
|
||||
} /* for */
|
||||
|
||||
dh = createDirHandle(newDir, 0);
|
||||
dh = createDirHandle(newDir, mountPoint, 0);
|
||||
BAIL_IF_MACRO_MUTEX(dh == NULL, NULL, stateLock, 0);
|
||||
|
||||
if (appendToPath)
|
||||
|
@ -902,6 +923,12 @@ int PHYSFS_addToSearchPath(const char *newDir, int appendToPath)
|
|||
|
||||
__PHYSFS_platformReleaseMutex(stateLock);
|
||||
return(1);
|
||||
} /* PHYSFS_mount */
|
||||
|
||||
|
||||
int PHYSFS_addToSearchPath(const char *newDir, int appendToPath)
|
||||
{
|
||||
return(PHYSFS_mount(newDir, "/", appendToPath));
|
||||
} /* PHYSFS_addToSearchPath */
|
||||
|
||||
|
||||
|
@ -1130,7 +1157,8 @@ char * __PHYSFS_convertToDependent(const char *prepend,
|
|||
* Verify that (fname) (in platform-independent notation), in relation
|
||||
* to (h) is secure. That means that each element of fname is checked
|
||||
* 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
|
||||
* 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. */
|
||||
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()? */
|
||||
start = str = malloc(strlen(fname) + 1);
|
||||
BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
|
|
70
physfs.h
70
physfs.h
|
@ -78,13 +78,13 @@
|
|||
* it correctly.
|
||||
*
|
||||
* 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
|
||||
* security hole. Also, symbolic links (which can be found in some archive
|
||||
* types and directly in the filesystem on Unix platforms) are NOT followed
|
||||
* until you call PHYSFS_permitSymbolicLinks(). That's left to your own
|
||||
* discretion, as following a symlink can allow for access outside the write
|
||||
* dir and search paths. There is no mechanism for creating new symlinks in
|
||||
* PhysicsFS.
|
||||
* elements. Not only are these meaningless on MacOS Classic and/or Unix,
|
||||
* they are a security hole. Also, symbolic links (which can be found in
|
||||
* some archive types and directly in the filesystem on Unix platforms) are
|
||||
* NOT followed until you call PHYSFS_permitSymbolicLinks(). That's left to
|
||||
* your own discretion, as following a symlink can allow for access outside
|
||||
* the write dir and search paths. For portability, there is no mechanism for
|
||||
* creating new symlinks in PhysicsFS.
|
||||
*
|
||||
* 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,
|
||||
|
@ -110,6 +110,18 @@
|
|||
* PHYSFS_getBaseDir(), and PHYSFS_getUserDir() for info on what those
|
||||
* 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
|
||||
* PHYSFS_getLastError are unique by thread, and library-state-setting
|
||||
* 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
|
||||
* 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
|
||||
* type.
|
||||
* type where possible.
|
||||
*
|
||||
* Currently supported archive types:
|
||||
* - .ZIP (pkZip/WinZip/Info-ZIP compatible)
|
||||
|
@ -133,12 +145,13 @@
|
|||
* - .HOG (Descent I/II HOG file archives)
|
||||
* - .MVL (Descent II movielib archives)
|
||||
* - .WAD (DOOM engine archives)
|
||||
* - .MIX (Older Westwood games archives)
|
||||
*
|
||||
* Please see the file LICENSE in the source's root directory for licensing
|
||||
* and redistribution rights.
|
||||
*
|
||||
* Please see the file CREDITS in the source's root directory for a complete
|
||||
* list of who's responsible for this.
|
||||
* Please see the file CREDITS in the source's root directory for a more or
|
||||
* less complete list of who's responsible for this.
|
||||
*
|
||||
* \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.
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
* \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:
|
||||
* PHYSFS_mount(newDir, "/", appendToPath);
|
||||
*
|
||||
* \sa PHYSFS_mount
|
||||
* \sa PHYSFS_unmount
|
||||
* \sa PHYSFS_removeFromSearchPath
|
||||
* \sa PHYSFS_getSearchPath
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue