Tons of updates. Mostly implemented. Mostly compiling.
This commit is contained in:
parent
7be11ab27d
commit
a197f30eef
525
physfs.c
525
physfs.c
|
@ -25,16 +25,16 @@ typedef struct __PHYSFS_ERRMSGTYPE__
|
|||
struct __PHYSFS_ERRMSGTYPE__ *next;
|
||||
} ErrMsg;
|
||||
|
||||
typedef struct __PHYSFS_SEARCHDIRINFO__
|
||||
typedef struct __PHYSFS_DIRINFO__
|
||||
{
|
||||
char *dirName;
|
||||
DirReader *reader;
|
||||
struct __PHYSFS_SEARCHDIRINFO__ *next;
|
||||
} SearchDirInfo;
|
||||
DirHandle *dirHandle;
|
||||
struct __PHYSFS_DIRINFO__ *next;
|
||||
} DirInfo;
|
||||
|
||||
typedef struct __PHYSFS_FILEHANDLELIST__
|
||||
{
|
||||
FileHandle *handle;
|
||||
PHYSFS_file *handle;
|
||||
struct __PHYSFS_FILEHANDLELIST__ *next;
|
||||
} FileHandleList;
|
||||
|
||||
|
@ -73,12 +73,12 @@ static const DirFunctions *dirFunctions[] =
|
|||
|
||||
static int initialized = 0;
|
||||
static ErrMsg *errorMessages = NULL;
|
||||
static SearchDirInfo *searchPath = NULL;
|
||||
static DirInfo *searchPath = NULL;
|
||||
static DirInfo *writeDir = NULL;
|
||||
static FileHandleList *openWriteList = NULL;
|
||||
static FileHandleList *openReadList = NULL;
|
||||
static char *baseDir = NULL;
|
||||
static char *userDir = NULL;
|
||||
static char *writeDir = NULL;
|
||||
static int allowSymLinks = 0;
|
||||
|
||||
|
||||
|
@ -107,7 +107,12 @@ static ErrMsg *findErrorForCurrentThread(void)
|
|||
|
||||
void __PHYSFS_setError(const char *str)
|
||||
{
|
||||
ErrMsg *err = findErrorForCurrentThread();
|
||||
ErrMsg *err;
|
||||
|
||||
if (str == NULL)
|
||||
return;
|
||||
|
||||
err = findErrorForCurrentThread();
|
||||
|
||||
if (err == NULL)
|
||||
{
|
||||
|
@ -126,6 +131,19 @@ void __PHYSFS_setError(const char *str)
|
|||
} /* __PHYSFS_setError */
|
||||
|
||||
|
||||
static void freeErrorMessages(void)
|
||||
{
|
||||
ErrMsg *i;
|
||||
ErrMsg *next;
|
||||
|
||||
for (i = errorMessages; i != NULL; i = next)
|
||||
{
|
||||
next = i;
|
||||
free(i);
|
||||
} /* for */
|
||||
} /* freeErrorMessages */
|
||||
|
||||
|
||||
const char *PHYSFS_getLastError(void)
|
||||
{
|
||||
ErrMsg *err = findErrorForCurrentThread();
|
||||
|
@ -149,22 +167,88 @@ void PHYSFS_getLinkedVersion(PHYSFS_Version *ver)
|
|||
} /* PHYSFS_getLinkedVersion */
|
||||
|
||||
|
||||
static const char *calculateUserDir(void)
|
||||
static DirHandle *openDirectory(const char *d, int forWriting)
|
||||
{
|
||||
const DirFunctions **i;
|
||||
|
||||
for (i = dirFunctions; *i != NULL; i++)
|
||||
{
|
||||
if ((*i)->isArchive(d, forWriting))
|
||||
return( (*i)->openArchive(d, forWriting) );
|
||||
} /* for */
|
||||
|
||||
__PHYSFS_setError(ERR_UNSUPPORTED_ARCHIVE);
|
||||
return(NULL);
|
||||
} /* openDirectory */
|
||||
|
||||
|
||||
static DirInfo *buildDirInfo(const char *newDir, int forWriting)
|
||||
{
|
||||
DirHandle *dirHandle = NULL;
|
||||
DirInfo *di = NULL;
|
||||
|
||||
BAIL_IF_MACRO(newDir == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||
|
||||
dirHandle = openDirectory(newDir, forWriting);
|
||||
BAIL_IF_MACRO(dirHandle == NULL, NULL, 0);
|
||||
|
||||
di = (DirInfo *) malloc(sizeof (DirInfo));
|
||||
if (di == NULL)
|
||||
dirHandle->funcs->close(dirHandle);
|
||||
BAIL_IF_MACRO(di == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
|
||||
di->dirName = (char *) malloc(strlen(newDir) + 1);
|
||||
if (di->dirName == NULL)
|
||||
{
|
||||
free(di);
|
||||
dirHandle->funcs->close(dirHandle);
|
||||
__PHYSFS_setError(ERR_OUT_OF_MEMORY);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
di->next = NULL;
|
||||
di->dirHandle = dirHandle;
|
||||
strcpy(di->dirName, newDir);
|
||||
return(di);
|
||||
} /* buildDirInfo */
|
||||
|
||||
|
||||
static int freeDirInfo(DirInfo *di, FileHandleList *openList)
|
||||
{
|
||||
FileHandleList *i;
|
||||
|
||||
if (di == NULL)
|
||||
return(1);
|
||||
|
||||
for (i = openList; i != NULL; i = i->next)
|
||||
{
|
||||
const DirHandle *h = ((FileHandle *) i->handle->opaque)->dirHandle;
|
||||
BAIL_IF_MACRO(h == di->dirHandle, ERR_FILES_STILL_OPEN, 0);
|
||||
} /* for */
|
||||
|
||||
di->dirHandle->funcs->close(di->dirHandle);
|
||||
free(di->dirName);
|
||||
free(di);
|
||||
return(1);
|
||||
} /* freeDirInfo */
|
||||
|
||||
|
||||
static char *calculateUserDir(void)
|
||||
{
|
||||
char *retval = NULL;
|
||||
const char *str = NULL;
|
||||
|
||||
str = __PHYSFS_platformGetUserDir();
|
||||
if (str != NULL)
|
||||
retval = str;
|
||||
retval = (char *) str;
|
||||
else
|
||||
{
|
||||
const char *dirsep = PHYSFS_getDirSeparator();
|
||||
const char *uname = __PHYSFS_platformGetUserName();
|
||||
|
||||
str = (uname != NULL) ? uname : "default";
|
||||
retval = malloc(strlen(baseDir) + strlen(str) +
|
||||
(strlen(dirsep) * 2) + 6);
|
||||
retval = (char *) malloc(strlen(baseDir) + strlen(str) +
|
||||
(strlen(dirsep) * 2) + 6);
|
||||
|
||||
if (retval == NULL)
|
||||
__PHYSFS_setError(ERR_OUT_OF_MEMORY);
|
||||
|
@ -172,21 +256,26 @@ static const char *calculateUserDir(void)
|
|||
sprintf(retval, "%s%susers%s%s", baseDir, dirsep, dirsep, str);
|
||||
|
||||
if (uname != NULL)
|
||||
free(uname);
|
||||
free((void *) uname);
|
||||
} /* else */
|
||||
|
||||
return(retval);
|
||||
} /* calculateUserDir */
|
||||
|
||||
|
||||
static char *calculateBaseDir(const char *argv0)
|
||||
{
|
||||
assert(0); return(NULL);
|
||||
} /* calculateBaseDir */
|
||||
|
||||
|
||||
int PHYSFS_init(const char *argv0)
|
||||
{
|
||||
BAIL_IF_MACRO(initialized, ERR_IS_INITIALIZED, 0);
|
||||
BAIL_IF_MACRO(argv0 == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||
|
||||
baseDir = calculateBaseDir(argv0);
|
||||
if (baseDir == NULL)
|
||||
return(0);
|
||||
BAIL_IF_MACRO(baseDir == NULL, NULL, 0);
|
||||
|
||||
userDir = calculateUserDir();
|
||||
if (userDir == NULL)
|
||||
|
@ -201,42 +290,35 @@ int PHYSFS_init(const char *argv0)
|
|||
} /* PHYSFS_init */
|
||||
|
||||
|
||||
static void freeSearchDir(SearchDirInfo *sdi)
|
||||
{
|
||||
FileHandleList *i;
|
||||
|
||||
assert(sdi != NULL);
|
||||
for (i = openReadList; i != NULL; i = i->next)
|
||||
{
|
||||
BAIL_IF_MACRO(i->handle->dirReader == sdi->reader,
|
||||
ERR_FILES_OPEN_READ, 0);
|
||||
} /* for */
|
||||
|
||||
sdi->reader->close(sdi->reader);
|
||||
free(sdi->dirName);
|
||||
free(sdi);
|
||||
} /* freeSearchDir */
|
||||
|
||||
|
||||
static void closeFileHandleList(FileHandleList **list)
|
||||
static int closeFileHandleList(FileHandleList **list)
|
||||
{
|
||||
FileHandleList *i;
|
||||
FileHandleList *next = NULL;
|
||||
FileHandle *h;
|
||||
|
||||
for (i = *list; i != NULL; i = next)
|
||||
{
|
||||
next = i->next;
|
||||
i->handle->close(i->handle);
|
||||
h = (FileHandle *) (i->handle->opaque);
|
||||
if (!h->funcs->close(i->handle->opaque))
|
||||
{
|
||||
*list = i;
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
free(i->handle);
|
||||
free(i);
|
||||
} /* for */
|
||||
|
||||
*list = NULL;
|
||||
} /* closeAllFiles */
|
||||
return(1);
|
||||
} /* closeFileHandleList */
|
||||
|
||||
|
||||
static void freeSearchPath(void)
|
||||
{
|
||||
SearchDirInfo *i;
|
||||
SearchDirInfo *next = NULL;
|
||||
DirInfo *i;
|
||||
DirInfo *next = NULL;
|
||||
|
||||
closeFileHandleList(&openReadList);
|
||||
|
||||
|
@ -245,19 +327,20 @@ static void freeSearchPath(void)
|
|||
for (i = searchPath; i != NULL; i = next)
|
||||
{
|
||||
next = i;
|
||||
freeSearchDir(i);
|
||||
freeDirInfo(i, openReadList);
|
||||
} /* for */
|
||||
searchPath = NULL;
|
||||
} /* if */
|
||||
} /* freeSearchPath */
|
||||
|
||||
|
||||
void PHYSFS_deinit(void)
|
||||
int PHYSFS_deinit(void)
|
||||
{
|
||||
BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0);
|
||||
|
||||
closeFileHandleList(&openWriteList);
|
||||
PHYSFS_setWriteDir(NULL);
|
||||
BAIL_IF_MACRO(!PHYSFS_setWriteDir(NULL), ERR_FILES_STILL_OPEN, 0);
|
||||
|
||||
freeSearchPath();
|
||||
freeErrorMessages();
|
||||
|
||||
|
@ -297,7 +380,7 @@ void PHYSFS_freeList(void *list)
|
|||
|
||||
const char *PHYSFS_getDirSeparator(void)
|
||||
{
|
||||
return(__PHYSFS_pathSeparator);
|
||||
return(__PHYSFS_platformDirSeparator);
|
||||
} /* PHYSFS_getDirSeparator */
|
||||
|
||||
|
||||
|
@ -321,96 +404,55 @@ const char *PHYSFS_getUserDir(void)
|
|||
|
||||
const char *PHYSFS_getWriteDir(void)
|
||||
{
|
||||
return(writeDir);
|
||||
if (writeDir == NULL)
|
||||
return(NULL);
|
||||
|
||||
return(writeDir->dirName);
|
||||
} /* PHYSFS_getWriteDir */
|
||||
|
||||
|
||||
int PHYSFS_setWriteDir(const char *newDir)
|
||||
{
|
||||
BAIL_IF_MACRO(openWriteList != NULL, ERR_FILES_OPEN_WRITE, 0);
|
||||
|
||||
if (writeDir != NULL)
|
||||
{
|
||||
free(writeDir);
|
||||
BAIL_IF_MACRO(!freeDirInfo(writeDir, openWriteList), NULL, 0);
|
||||
writeDir = NULL;
|
||||
} /* if */
|
||||
|
||||
if (newDir != NULL)
|
||||
{
|
||||
BAIL_IF_MACRO(!createDirs_dependent(newDir), ERR_NO_DIR_CREATE, 0);
|
||||
|
||||
writeDir = malloc(strlen(newDir) + 1);
|
||||
BAIL_IF_MACRO(writeDir == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
|
||||
strcpy(writeDir, newDir);
|
||||
writeDir = buildDirInfo(newDir, 1);
|
||||
return(writeDir != NULL);
|
||||
} /* if */
|
||||
|
||||
return(1);
|
||||
} /* PHYSFS_setWriteDir */
|
||||
|
||||
|
||||
static DirReader *getDirReader(const char *d)
|
||||
{
|
||||
DirFunctions **i;
|
||||
|
||||
for (i = dirFunctions; *i != NULL; i++)
|
||||
{
|
||||
if ((*i)->isArchive(d))
|
||||
return( (*i)->openArchive(d) );
|
||||
} /* for */
|
||||
|
||||
__PHYSFS_setError(ERR_UNSUPPORTED_ARCHIVE);
|
||||
return(NULL);
|
||||
} /* getDirReader */
|
||||
|
||||
|
||||
int PHYSFS_addToSearchPath(const char *newDir, int appendToPath)
|
||||
{
|
||||
char *str = NULL;
|
||||
SearchDirInfo *sdi = NULL;
|
||||
DirReader *dirReader = NULL;
|
||||
DirInfo *di = buildDirInfo(newDir, 0);
|
||||
|
||||
BAIL_IF_MACRO(newDir == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||
|
||||
reader = getDirReader(newDir); /* This sets the error message. */
|
||||
if (reader == NULL)
|
||||
return(0);
|
||||
|
||||
sdi = (SearchDirInfo *) malloc(sizeof (SearchDirInfo));
|
||||
if (sdi == NULL)
|
||||
reader->close(reader);
|
||||
BAIL_IF_MACRO(sdi == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
|
||||
sdi->dirName = (char *) malloc(strlen(newDir) + 1);
|
||||
if (sdi->dirName == NULL)
|
||||
{
|
||||
free(sdi);
|
||||
reader->close(reader);
|
||||
__PHYSFS_setError(ERR_OUT_OF_MEMORY);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
sdi->dirReader = dirReader;
|
||||
strcpy(sdi->dirName, newDir);
|
||||
BAIL_IF_MACRO(di == NULL, NULL, 0);
|
||||
|
||||
if (appendToPath)
|
||||
{
|
||||
sdi->next = searchPath;
|
||||
searchPath = sdi;
|
||||
di->next = searchPath;
|
||||
searchPath = di;
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
SearchDirInfo *i = searchPath;
|
||||
SearchDirInfo *prev = NULL;
|
||||
DirInfo *i = searchPath;
|
||||
DirInfo *prev = NULL;
|
||||
|
||||
sdi->next = NULL;
|
||||
di->next = NULL;
|
||||
while (i != NULL)
|
||||
prev = i;
|
||||
|
||||
if (prev == NULL)
|
||||
searchPath = sdi;
|
||||
searchPath = di;
|
||||
else
|
||||
prev->next = sdi;
|
||||
prev->next = di;
|
||||
} /* else */
|
||||
|
||||
return(1);
|
||||
|
@ -419,9 +461,9 @@ int PHYSFS_addToSearchPath(const char *newDir, int appendToPath)
|
|||
|
||||
int PHYSFS_removeFromSearchPath(const char *oldDir)
|
||||
{
|
||||
SearchDirInfo *i;
|
||||
SearchDirInfo *prev = NULL;
|
||||
SearchDirInfo *next = NULL;
|
||||
DirInfo *i;
|
||||
DirInfo *prev = NULL;
|
||||
DirInfo *next = NULL;
|
||||
|
||||
BAIL_IF_MACRO(oldDir == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||
|
||||
|
@ -430,8 +472,7 @@ int PHYSFS_removeFromSearchPath(const char *oldDir)
|
|||
if (strcmp(i->dirName, oldDir) == 0)
|
||||
{
|
||||
next = i->next;
|
||||
if (!freeSearchDir(i))
|
||||
return(0);
|
||||
BAIL_IF_MACRO(!freeDirInfo(i, openReadList), NULL, 0);
|
||||
|
||||
if (prev == NULL)
|
||||
searchPath = next;
|
||||
|
@ -452,7 +493,7 @@ char **PHYSFS_getSearchPath(void)
|
|||
{
|
||||
int count = 1;
|
||||
int x;
|
||||
SearchDirInfo *i;
|
||||
DirInfo *i;
|
||||
char **retval;
|
||||
|
||||
for (i = searchPath; i != NULL; i = i->next)
|
||||
|
@ -501,13 +542,12 @@ int PHYSFS_setSaneConfig(const char *appName, const char *archiveExt,
|
|||
BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
sprintf(str, "%s%s.%s", userdir, dirsep, appName);
|
||||
rc = PHYSFS_setWriteDir(str);
|
||||
if (!rc)
|
||||
return(0); /* error set by PHYSFS_setWriteDir() ... */
|
||||
BAIL_IF_MACRO(!rc, NULL, 0);
|
||||
|
||||
/* Put write dir related dirs on search path... */
|
||||
PHYSFS_addToSearchPath(str, 1);
|
||||
PHYSFS_mkdir(appName); /* don't care if this fails. */
|
||||
strcat(str, dirSep);
|
||||
strcat(str, dirsep);
|
||||
strcat(str, appName);
|
||||
PHYSFS_addToSearchPath(str, 1);
|
||||
free(str);
|
||||
|
@ -530,12 +570,12 @@ int PHYSFS_setSaneConfig(const char *appName, const char *archiveExt,
|
|||
char **i;
|
||||
for (i = cds; *i != NULL; i++)
|
||||
{
|
||||
PHYSFS_addToSearchPath(*i);
|
||||
PHYSFS_addToSearchPath(*i, 1);
|
||||
str = malloc(strlen(*i) + strlen(appName) + strlen(dirsep) + 1);
|
||||
if (str != NULL)
|
||||
{
|
||||
sprintf(str, "%s%s%s", *i, dirsep, appName);
|
||||
PHYSFS_addToSearchPath(str);
|
||||
PHYSFS_addToSearchPath(str, 1);
|
||||
free(str);
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
@ -563,7 +603,7 @@ int PHYSFS_setSaneConfig(const char *appName, const char *archiveExt,
|
|||
if (str != NULL)
|
||||
{
|
||||
sprintf(str, "%s%s%s", d, dirsep, *i);
|
||||
PHYSFS_addToSearchPath(d, str);
|
||||
PHYSFS_addToSearchPath(str, archivesFirst == 0);
|
||||
free(str);
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
@ -577,11 +617,16 @@ int PHYSFS_setSaneConfig(const char *appName, const char *archiveExt,
|
|||
} /* PHYSFS_setSaneConfig */
|
||||
|
||||
|
||||
void PHYSFS_permitSymbolicLinks(int allow)
|
||||
{
|
||||
allowSymLinks = allow;
|
||||
} /* PHYSFS_permitSymbolicLinks */
|
||||
|
||||
|
||||
/* string manipulation in C makes my ass itch. */
|
||||
/* be sure to free this crap after you're done with it. */
|
||||
static char *convertToDependentNotation(const char *prepend,
|
||||
const char *dirName,
|
||||
const char *append)
|
||||
char *__PHYSFS_convertToDependentNotation(const char *prepend,
|
||||
const char *dirName,
|
||||
const char *append)
|
||||
{
|
||||
const char *dirsep = PHYSFS_getDirSeparator();
|
||||
int sepsize = strlen(dirsep);
|
||||
|
@ -590,7 +635,7 @@ static char *convertToDependentNotation(const char *prepend,
|
|||
char *i2;
|
||||
size_t allocSize;
|
||||
|
||||
allocSize = strlen(dirName) + strlen(writeDir) + sepsize + 1;
|
||||
allocSize = strlen(dirName) + 1;
|
||||
if (prepend != NULL)
|
||||
allocSize += strlen(prepend) + sepsize;
|
||||
if (append != NULL)
|
||||
|
@ -599,11 +644,16 @@ static char *convertToDependentNotation(const char *prepend,
|
|||
/* make sure there's enough space if the dir separator is bigger. */
|
||||
if (sepsize > 1)
|
||||
{
|
||||
for (str = dirName; *str != '\0'; str++)
|
||||
str = (char *) dirName;
|
||||
do
|
||||
{
|
||||
if (*str == '/')
|
||||
str = strchr(str, '/');
|
||||
if (str != NULL)
|
||||
{
|
||||
allocSize += (sepsize - 1);
|
||||
} /* for */
|
||||
str++;
|
||||
} /* if */
|
||||
} while (str != NULL);
|
||||
} /* if */
|
||||
|
||||
str = (char *) malloc(allocSize);
|
||||
|
@ -616,7 +666,7 @@ static char *convertToDependentNotation(const char *prepend,
|
|||
strcat(str, dirsep);
|
||||
} /* if */
|
||||
|
||||
for (i1 = dirName, i2 = str + strlen(str); *i1 != '\0'; i1++, i2++)
|
||||
for (i1 = (char *) dirName, i2 = str + strlen(str); *i1; i1++, i2++)
|
||||
{
|
||||
if (*i1 == '/')
|
||||
{
|
||||
|
@ -637,78 +687,123 @@ static char *convertToDependentNotation(const char *prepend,
|
|||
} /* if */
|
||||
|
||||
return(str);
|
||||
} /* convertToDependentNotation */
|
||||
} /* __PHYSFS_convertToDependentNotation */
|
||||
|
||||
|
||||
int __PHYSFS_verifySecurity(DirHandle *h, const char *fname)
|
||||
{
|
||||
int retval = 1;
|
||||
char *start;
|
||||
char *end;
|
||||
char *str;
|
||||
|
||||
start = str = malloc(strlen(fname) + 1);
|
||||
BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
strcpy(str, fname);
|
||||
|
||||
while (1)
|
||||
{
|
||||
end = strchr(start, '/');
|
||||
if (end != NULL)
|
||||
*end = '\0';
|
||||
|
||||
if ( (strcmp(start, ".") == 0) ||
|
||||
(strcmp(start, "..") == 0) ||
|
||||
(strchr(start, ':') != NULL) )
|
||||
{
|
||||
__PHYSFS_setError(ERR_INSECURE_FNAME);
|
||||
retval = 0;
|
||||
break;
|
||||
} /* if */
|
||||
|
||||
if ((!allowSymLinks) && (h->funcs->isSymLink(h, str)))
|
||||
{
|
||||
__PHYSFS_setError(ERR_SYMLINK_DISALLOWED);
|
||||
retval = 0;
|
||||
break;
|
||||
} /* if */
|
||||
|
||||
if (end == NULL)
|
||||
break;
|
||||
|
||||
*end = '/';
|
||||
start = end + 1;
|
||||
} /* while */
|
||||
|
||||
free(str);
|
||||
return(retval);
|
||||
} /* __PHYSFS_verifySecurity */
|
||||
|
||||
|
||||
int PHYSFS_mkdir(const char *dirName)
|
||||
{
|
||||
DirHandle *h;
|
||||
char *str;
|
||||
int rc;
|
||||
char *start;
|
||||
char *end;
|
||||
int retval = 0;
|
||||
|
||||
BAIL_IF_MACRO(writeDir == NULL, ERR_NO_WRITE_DIR, NULL);
|
||||
BAIL_IF_MACRO(writeDir == NULL, ERR_NO_WRITE_DIR, 0);
|
||||
h = writeDir->dirHandle;
|
||||
BAIL_IF_MACRO(h->funcs->mkdir == NULL, ERR_NOT_SUPPORTED, 0);
|
||||
BAIL_IF_MACRO(!__PHYSFS_verifySecurity(h, dirName), NULL, 0);
|
||||
|
||||
str = convertToDependentNotation(writeDir, dirName, NULL);
|
||||
if (str == NULL) /* __PHYSFS_setError is called in convert call. */
|
||||
return(0);
|
||||
start = str = malloc(strlen(dirName) + 1);
|
||||
BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
strcpy(str, dirName);
|
||||
|
||||
while (1)
|
||||
{
|
||||
end = strchr(start, '/');
|
||||
if (end != NULL)
|
||||
*end = '\0';
|
||||
|
||||
retval = h->funcs->mkdir(h, str);
|
||||
if (!retval)
|
||||
break;
|
||||
|
||||
if (end == NULL)
|
||||
break;
|
||||
|
||||
*end = '/';
|
||||
start = end + 1;
|
||||
} /* while */
|
||||
|
||||
rc = createDirs_dependent(str);
|
||||
free(str);
|
||||
return(rc);
|
||||
return(retval);
|
||||
} /* PHYSFS_mkdir */
|
||||
|
||||
|
||||
int PHYSFS_delete(const char *filename)
|
||||
int PHYSFS_delete(const char *fname)
|
||||
{
|
||||
char *str;
|
||||
int rc;
|
||||
|
||||
BAIL_IF_MACRO(writeDir == NULL, ERR_NO_WRITE_DIR, NULL);
|
||||
|
||||
str = convertToDependentNotation(writeDir, fileName, NULL);
|
||||
if (str == NULL) /* __PHYSFS_setError is called in convert call. */
|
||||
return(0);
|
||||
|
||||
rc = remove(str);
|
||||
free(str);
|
||||
|
||||
rc = (rc == 0);
|
||||
if (!rc)
|
||||
__PHYSFS_setError(strerror(errno));
|
||||
|
||||
return(rc);
|
||||
DirHandle *h;
|
||||
BAIL_IF_MACRO(writeDir == NULL, ERR_NO_WRITE_DIR, 0);
|
||||
h = writeDir->dirHandle;
|
||||
BAIL_IF_MACRO(h->funcs->remove == NULL, ERR_NOT_SUPPORTED, 0);
|
||||
BAIL_IF_MACRO(!__PHYSFS_verifySecurity(h, fname), NULL, 0);
|
||||
return(h->funcs->remove(h, fname));
|
||||
} /* PHYSFS_delete */
|
||||
|
||||
|
||||
void PHYSFS_permitSymbolicLinks(int allow)
|
||||
{
|
||||
allowSymLinks = allow;
|
||||
} /* PHYSFS_permitSymbolicLinks */
|
||||
|
||||
|
||||
/**
|
||||
* Figure out where in the search path a file resides. The file is specified
|
||||
* in platform-independent notation. The returned filename will be the
|
||||
* element of the search path where the file was found, which may be a
|
||||
* directory, or an archive. Even if there are multiple matches in different
|
||||
* parts of the search path, only the first one found is used, just like
|
||||
* when opening a file.
|
||||
*
|
||||
* So, if you look for "maps/level1.map", and C:\mygame is in your search
|
||||
* path and C:\mygame\maps\level1.map exists, then "C:\mygame" is returned.
|
||||
*
|
||||
* If a match is a symbolic link, and you've not explicitly permitted symlinks,
|
||||
* then it will be ignored, and the search for a match will continue.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
const char *PHYSFS_getRealDir(const char *filename)
|
||||
{
|
||||
DirInfo *i;
|
||||
|
||||
for (i = searchPath; i != NULL; i = i->next)
|
||||
{
|
||||
DirHandle *h = i->dirHandle;
|
||||
if (__PHYSFS_verifySecurity(h, filename))
|
||||
{
|
||||
if (h->funcs->exists(h, filename))
|
||||
return(i->dirName);
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
||||
return(NULL);
|
||||
} /* PHYSFS_getRealDir */
|
||||
|
||||
|
||||
static void countList(LinkedStringList *list)
|
||||
static int countList(LinkedStringList *list)
|
||||
{
|
||||
int retval = 0;
|
||||
LinkedStringList *i;
|
||||
|
@ -797,16 +892,19 @@ static void interpolateStringLists(LinkedStringList **final,
|
|||
|
||||
char **PHYSFS_enumerateFiles(const char *path)
|
||||
{
|
||||
SearchDirInfo *i;
|
||||
DirInfo *i;
|
||||
char **retval = NULL;
|
||||
LinkedStringList *rc;
|
||||
LinkedStringList *finalList = NULL;
|
||||
|
||||
for (i = searchPath; i != NULL; i = i->next)
|
||||
{
|
||||
assert(i->reader->funcs->enumerateFiles != NULL);
|
||||
rc = i->reader->funcs->enumerateFiles(path);
|
||||
interpolateStringLists(&finalList, rc);
|
||||
DirHandle *h = i->dirHandle;
|
||||
if (__PHYSFS_verifySecurity(h, path))
|
||||
{
|
||||
rc = h->funcs->enumerateFiles(h, path);
|
||||
interpolateStringLists(&finalList, rc);
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
||||
retval = convertStringListToPhysFSList(finalList);
|
||||
|
@ -814,6 +912,50 @@ char **PHYSFS_enumerateFiles(const char *path)
|
|||
} /* PHYSFS_enumerateFiles */
|
||||
|
||||
|
||||
int PHYSFS_exists(const char *fname)
|
||||
{
|
||||
return(PHYSFS_getRealDir(fname) != NULL);
|
||||
} /* PHYSFS_exists */
|
||||
|
||||
|
||||
int PHYSFS_isDirectory(const char *fname)
|
||||
{
|
||||
DirInfo *i;
|
||||
|
||||
for (i = searchPath; i != NULL; i = i->next)
|
||||
{
|
||||
DirHandle *h = i->dirHandle;
|
||||
if (__PHYSFS_verifySecurity(h, fname))
|
||||
{
|
||||
if (h->funcs->exists(h, fname))
|
||||
return(h->funcs->isDirectory(h, fname));
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
||||
return(0);
|
||||
} /* PHYSFS_isDirectory */
|
||||
|
||||
|
||||
int PHYSFS_isSymbolicLink(const char *fname)
|
||||
{
|
||||
DirInfo *i;
|
||||
|
||||
if (!allowSymLinks)
|
||||
return(0);
|
||||
|
||||
for (i = searchPath; i != NULL; i = i->next)
|
||||
{
|
||||
DirHandle *h = i->dirHandle;
|
||||
if (__PHYSFS_verifySecurity(h, fname))
|
||||
{
|
||||
if (h->funcs->exists(h, fname))
|
||||
return(h->funcs->isSymLink(h, fname));
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
||||
return(0);
|
||||
} /* PHYSFS_isSymbolicLink */
|
||||
|
||||
/**
|
||||
* Open a file for writing, in platform-independent notation and in relation
|
||||
* to the write path as the root of the writable filesystem. The specified
|
||||
|
@ -826,6 +968,7 @@ char **PHYSFS_enumerateFiles(const char *path)
|
|||
*/
|
||||
PHYSFS_file *PHYSFS_openWrite(const char *filename)
|
||||
{
|
||||
return NULL;
|
||||
} /* PHYSFS_openWrite */
|
||||
|
||||
|
||||
|
@ -842,6 +985,7 @@ PHYSFS_file *PHYSFS_openWrite(const char *filename)
|
|||
*/
|
||||
PHYSFS_file *PHYSFS_openAppend(const char *filename)
|
||||
{
|
||||
return NULL;
|
||||
} /* PHYSFS_openAppend */
|
||||
|
||||
|
||||
|
@ -857,44 +1001,31 @@ PHYSFS_file *PHYSFS_openAppend(const char *filename)
|
|||
*/
|
||||
PHYSFS_file *PHYSFS_openRead(const char *filename)
|
||||
{
|
||||
return NULL;
|
||||
} /* PHYSFS_openRead */
|
||||
|
||||
|
||||
/**
|
||||
* Close a PhysicsFS filehandle. This call is capable of failing if the
|
||||
* operating system was buffering writes to this file, and (now forced to
|
||||
* write those changes to physical media) can not store the data for any
|
||||
* reason. In such a case, the filehandle stays open. A well-written program
|
||||
* should ALWAYS check the return value from the close call in addition to
|
||||
* every writing call!
|
||||
*
|
||||
* @param handle handle returned from PHYSFS_open*().
|
||||
* @return nonzero on success, zero on error. Specifics of the error can be
|
||||
* gleaned from PHYSFS_getLastError().
|
||||
*/
|
||||
int PHYSFS_close(PHYSFS_file *handle)
|
||||
{
|
||||
FileHandle *h = (FileHandle *) handle->opaque;
|
||||
FileHandleList *i;
|
||||
FileHandleList **lists[] = { &openWriteList, &openReadList, NULL };
|
||||
FileHandleList *prev;
|
||||
FileHandleList **_lists[] = { &openWriteList, &openReadList, NULL };
|
||||
FileHandleList ***lists = _lists; /* gay. */
|
||||
int rc;
|
||||
|
||||
assert(h != NULL);
|
||||
assert(h->funcs != NULL);
|
||||
assert(h->funcs->close != NULL);
|
||||
|
||||
while (lists != NULL)
|
||||
{
|
||||
for (i = *(*lists); i != NULL; i = i->next)
|
||||
for (i = *(*lists), prev = NULL; i != NULL; prev = i, i = i->next)
|
||||
{
|
||||
if (i->handle == h)
|
||||
if (((FileHandle *) i->handle->opaque) == h)
|
||||
{
|
||||
rc = h->close(h);
|
||||
rc = h->funcs->close(h);
|
||||
if (!rc)
|
||||
return(0);
|
||||
|
||||
if (prev == NULL)
|
||||
*lists = i->next;
|
||||
*(*lists) = i->next;
|
||||
else
|
||||
prev->next = i->next;
|
||||
free(i);
|
||||
|
@ -905,7 +1036,8 @@ int PHYSFS_close(PHYSFS_file *handle)
|
|||
lists++;
|
||||
} /* while */
|
||||
|
||||
assert(0); /* shouldn't EVER hit this. */
|
||||
__PHYSFS_setError(ERR_NOT_A_HANDLE);
|
||||
return(0);
|
||||
} /* PHYSFS_close */
|
||||
|
||||
|
||||
|
@ -960,5 +1092,6 @@ int PHYSFS_seek(PHYSFS_file *handle, int pos)
|
|||
return(h->funcs->seek(h, pos));
|
||||
} /* PHYSFS_seek */
|
||||
|
||||
|
||||
/* end of physfs.c ... */
|
||||
|
||||
|
|
121
physfs.h
121
physfs.h
|
@ -211,16 +211,22 @@ int PHYSFS_init(const char *argv0);
|
|||
* Shutdown PhysicsFS. This closes any files opened via PhysicsFS, blanks the
|
||||
* search/write paths, frees memory, and invalidates all of your handles.
|
||||
*
|
||||
* Once deinitialized, PHYSFS_init() can be called again to restart the
|
||||
* subsystem.
|
||||
* Note that this call can FAIL if there's a file open for writing that
|
||||
* refuses to close (for example, the underlying operating system was
|
||||
* buffering writes to network filesystem, and the fileserver has crashed,
|
||||
* or a hard drive has failed, etc). It is usually best to close all write
|
||||
* handles yourself before calling this function, so that you can gracefully
|
||||
* handle a specific failure.
|
||||
*
|
||||
* This function can be used with atexit(), if you feel it's prudent to do so.
|
||||
* Once successfully deinitialized, PHYSFS_init() can be called again to
|
||||
* restart the subsystem. All defaults API states are restored at this
|
||||
* point.
|
||||
*
|
||||
* @return nonzero on success, zero on error. Specifics of the error can be
|
||||
* gleaned from PHYSFS_getLastError(). If failure, state of PhysFS is
|
||||
* undefined, and probably badly screwed up.
|
||||
*/
|
||||
void PHYSFS_deinit(void);
|
||||
int PHYSFS_deinit(void);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -286,6 +292,30 @@ const char *PHYSFS_getLastError(void);
|
|||
const char *PHYSFS_getDirSeparator(void);
|
||||
|
||||
|
||||
/**
|
||||
* Enable symbolic links. Some physical filesystems and archives contain
|
||||
* files that are just pointers to other files. On the physical filesystem,
|
||||
* opening such a link will (transparently) open the file that is pointed to.
|
||||
*
|
||||
* By default, PhysicsFS will check if a file is really a symlink during open
|
||||
* calls and fail if it is. Otherwise, the link could take you outside the
|
||||
* write and search paths, and compromise security.
|
||||
*
|
||||
* If you want to take that risk, call this function with a non-zero parameter.
|
||||
* Note that this is more for sandboxing a program's scripting language, in
|
||||
* case untrusted scripts try to compromise the system. Generally speaking,
|
||||
* a user could very well have a legitimate reason to set up a symlink, so
|
||||
* unless you feel there's a specific danger in allowing them, you should
|
||||
* permit them.
|
||||
*
|
||||
* Symbolic link permission can be enabled or disabled at any time, and is
|
||||
* disabled by default.
|
||||
*
|
||||
* @param allow nonzero to permit symlinks, zero to deny linking.
|
||||
*/
|
||||
void PHYSFS_permitSymbolicLinks(int allow);
|
||||
|
||||
|
||||
/**
|
||||
* Get an array of dirs to available CD-ROM drives.
|
||||
*
|
||||
|
@ -528,30 +558,6 @@ int PHYSFS_mkdir(const char *dirName);
|
|||
int PHYSFS_delete(const char *filename);
|
||||
|
||||
|
||||
/**
|
||||
* Enable symbolic links. Some physical filesystems and archives contain
|
||||
* files that are just pointers to other files. On the physical filesystem,
|
||||
* opening such a link will (transparently) open the file that is pointed to.
|
||||
*
|
||||
* By default, PhysicsFS will check if a file is really a symlink during open
|
||||
* calls and fail if it is. Otherwise, the link could take you outside the
|
||||
* write and search paths, and compromise security.
|
||||
*
|
||||
* If you want to take that risk, call this function with a non-zero parameter.
|
||||
* Note that this is more for sandboxing a program's scripting language, in
|
||||
* case untrusted scripts try to compromise the system. Generally speaking,
|
||||
* a user could very well have a legitimate reason to set up a symlink, so
|
||||
* unless you feel there's a specific danger in allowing them, you should
|
||||
* permit them.
|
||||
*
|
||||
* Symbolic link permission can be enabled or disabled at any time, and is
|
||||
* disabled by default.
|
||||
*
|
||||
* @param allow nonzero to permit symlinks, zero to deny linking.
|
||||
*/
|
||||
void PHYSFS_permitSymbolicLinks(int allow);
|
||||
|
||||
|
||||
/**
|
||||
* Figure out where in the search path a file resides. The file is specified
|
||||
* in platform-independent notation. The returned filename will be the
|
||||
|
@ -563,8 +569,9 @@ void PHYSFS_permitSymbolicLinks(int allow);
|
|||
* So, if you look for "maps/level1.map", and C:\mygame is in your search
|
||||
* path and C:\mygame\maps\level1.map exists, then "C:\mygame" is returned.
|
||||
*
|
||||
* If a match is a symbolic link, and you've not explicitly permitted symlinks,
|
||||
* then it will be ignored, and the search for a match will continue.
|
||||
* If a any part of a match is a symbolic link, and you've not explicitly
|
||||
* permitted symlinks, then it will be ignored, and the search for a match
|
||||
* will continue.
|
||||
*
|
||||
* @param filename file to look for.
|
||||
* @return READ ONLY string of element of search path containing the
|
||||
|
@ -612,12 +619,58 @@ const char *PHYSFS_getRealDir(const char *filename);
|
|||
char **PHYSFS_enumerateFiles(const char *dir);
|
||||
|
||||
|
||||
/**
|
||||
* Determine if there is an entry anywhere in the search path by the
|
||||
* name of (fname).
|
||||
*
|
||||
* Note that entries that are symlinks are ignored if
|
||||
* PHYSFS_permitSymbolicLinks(1) hasn't been called, so you
|
||||
* might end up further down in the search path than expected.
|
||||
*
|
||||
* @param fname filename in platform-independent notation.
|
||||
* @return non-zero if filename exists. zero otherwise.
|
||||
*/
|
||||
int PHYSFS_exists(const char *fname);
|
||||
|
||||
|
||||
/**
|
||||
* Determine if the first occurence of (fname) in the search path is
|
||||
* really a directory entry.
|
||||
*
|
||||
* Note that entries that are symlinks are ignored if
|
||||
* PHYSFS_permitSymbolicLinks(1) hasn't been called, so you
|
||||
* might end up further down in the search path than expected.
|
||||
*
|
||||
* @param fname filename in platform-independent notation.
|
||||
* @return non-zero if filename exists and is a directory. zero otherwise.
|
||||
*/
|
||||
int PHYSFS_isDirectory(const char *fname);
|
||||
|
||||
|
||||
/**
|
||||
* Determine if the first occurence of (fname) in the search path is
|
||||
* really a symbolic link.
|
||||
*
|
||||
* Note that entries that are symlinks are ignored if
|
||||
* PHYSFS_permitSymbolicLinks(1) hasn't been called, and as such,
|
||||
* this function will always return 0 in that case.
|
||||
*
|
||||
* @param fname filename in platform-independent notation.
|
||||
* @return non-zero if filename exists and is a symlink. zero otherwise.
|
||||
*/
|
||||
int PHYSFS_isSymbolicLink(const char *fname);
|
||||
|
||||
|
||||
/**
|
||||
* Open a file for writing, in platform-independent notation and in relation
|
||||
* to the write dir as the root of the writable filesystem. The specified
|
||||
* file is created if it doesn't exist. If it does exist, it is truncated to
|
||||
* zero bytes, and the writing offset is set to the start.
|
||||
*
|
||||
* Note that entries that are symlinks are ignored if
|
||||
* PHYSFS_permitSymbolicLinks(1) hasn't been called, and opening a
|
||||
* symlink with this function will fail in such a case.
|
||||
*
|
||||
* @param filename File to open.
|
||||
* @return A valid PhysicsFS filehandle on success, NULL on error. Specifics
|
||||
* of the error can be gleaned from PHYSFS_getLastError().
|
||||
|
@ -632,6 +685,10 @@ PHYSFS_file *PHYSFS_openWrite(const char *filename);
|
|||
* is set to the end of the file, so the first write will be the byte after
|
||||
* the end.
|
||||
*
|
||||
* Note that entries that are symlinks are ignored if
|
||||
* PHYSFS_permitSymbolicLinks(1) hasn't been called, and opening a
|
||||
* symlink with this function will fail in such a case.
|
||||
*
|
||||
* @param filename File to open.
|
||||
* @return A valid PhysicsFS filehandle on success, NULL on error. Specifics
|
||||
* of the error can be gleaned from PHYSFS_getLastError().
|
||||
|
@ -645,6 +702,10 @@ PHYSFS_file *PHYSFS_openAppend(const char *filename);
|
|||
* abstract filehandle is associated with it, and reading may be done.
|
||||
* The reading offset is set to the first byte of the file.
|
||||
*
|
||||
* Note that entries that are symlinks are ignored if
|
||||
* PHYSFS_permitSymbolicLinks(1) hasn't been called, and opening a
|
||||
* symlink with this function will fail in such a case.
|
||||
*
|
||||
* @param filename File to open.
|
||||
* @return A valid PhysicsFS filehandle on success, NULL on error. Specifics
|
||||
* of the error can be gleaned from PHYSFS_getLastError().
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#error Do not include this header from your applications.
|
||||
#endif
|
||||
|
||||
struct __PHYSFS_DIRREADER__;
|
||||
struct __PHYSFS_DIRHANDLE__;
|
||||
struct __PHYSFS_FILEFUNCTIONS__;
|
||||
|
||||
typedef struct __PHYSFS_FILEHANDLE__
|
||||
|
@ -27,7 +27,7 @@ typedef struct __PHYSFS_FILEHANDLE__
|
|||
/*
|
||||
* This should be the DirHandle that created this FileHandle.
|
||||
*/
|
||||
const struct __PHYSFS_DIRREADER__ *dirReader;
|
||||
const struct __PHYSFS_DIRHANDLE__ *dirHandle;
|
||||
|
||||
/*
|
||||
* Pointer to the file i/o functions for this filehandle.
|
||||
|
@ -40,6 +40,9 @@ typedef struct __PHYSFS_FILEFUNCTIONS__
|
|||
{
|
||||
/*
|
||||
* Read more from the file.
|
||||
* Returns number of objects of (objSize) bytes read from file, -1
|
||||
* if complete failure.
|
||||
* On failure, call __PHYSFS_setError().
|
||||
*/
|
||||
int (*read)(FileHandle *handle, void *buffer,
|
||||
unsigned int objSize, unsigned int objCount);
|
||||
|
@ -47,6 +50,9 @@ typedef struct __PHYSFS_FILEFUNCTIONS__
|
|||
/*
|
||||
* Write more to the file. Archives don't have to implement this.
|
||||
* (Set it to NULL if not implemented).
|
||||
* Returns number of objects of (objSize) bytes written to file, -1
|
||||
* if complete failure.
|
||||
* On failure, call __PHYSFS_setError().
|
||||
*/
|
||||
int (*write)(FileHandle *handle, void *buffer,
|
||||
unsigned int objSize, unsigned int objCount);
|
||||
|
@ -64,17 +70,20 @@ typedef struct __PHYSFS_FILEFUNCTIONS__
|
|||
/*
|
||||
* Move read/write pointer to byte offset from start of file.
|
||||
* Returns non-zero on success, zero on error.
|
||||
* On failure, call __PHYSFS_setError().
|
||||
*/
|
||||
int (*seek)(FileHandle *handle, int offset);
|
||||
|
||||
/*
|
||||
* Close the file, and free the FileHandle structure (including "opaque").
|
||||
* returns non-zero on success, zero if can't close file.
|
||||
* On failure, call __PHYSFS_setError().
|
||||
*/
|
||||
int (*close)(FileHandle *handle);
|
||||
} FileFunctions;
|
||||
|
||||
|
||||
typedef struct __PHYSFS_DIRREADER__
|
||||
typedef struct __PHYSFS_DIRHANDLE__
|
||||
{
|
||||
/*
|
||||
* This is reserved for the driver to store information.
|
||||
|
@ -82,7 +91,7 @@ typedef struct __PHYSFS_DIRREADER__
|
|||
void *opaque;
|
||||
|
||||
/*
|
||||
* Pointer to the directory i/o functions for this reader.
|
||||
* Pointer to the directory i/o functions for this handle.
|
||||
*/
|
||||
const struct __PHYSFS_DIRFUNCTIONS__ *funcs;
|
||||
} DirHandle;
|
||||
|
@ -104,16 +113,21 @@ typedef struct __PHYSFS_DIRFUNCTIONS__
|
|||
/*
|
||||
* Returns non-zero if (filename) is a valid archive that this
|
||||
* driver can handle. This filename is in platform-dependent
|
||||
* notation.
|
||||
* notation. forWriting is non-zero if this is to be used for
|
||||
* the write directory, and zero if this is to be used for an
|
||||
* element of the search path.
|
||||
*/
|
||||
int (*isArchive)(const char *filename);
|
||||
int (*isArchive)(const char *filename, int forWriting);
|
||||
|
||||
/*
|
||||
* Return a DirHandle for dir/archive (name).
|
||||
* This filename is in platform-dependent notation.
|
||||
* return (NULL) on error.
|
||||
* forWriting is non-zero if this is to be used for
|
||||
* the write directory, and zero if this is to be used for an
|
||||
* element of the search path.
|
||||
* Returns NULL on failure, and calls __PHYSFS_setError().
|
||||
*/
|
||||
DirHandle *(*openArchive)(const char *name);
|
||||
DirHandle *(*openArchive)(const char *name, int forWriting);
|
||||
|
||||
/*
|
||||
* Returns a list of all files in dirname. Each element of this list
|
||||
|
@ -123,7 +137,13 @@ typedef struct __PHYSFS_DIRFUNCTIONS__
|
|||
* If you have a memory failure, return as much as you can.
|
||||
* This dirname is in platform-independent notation.
|
||||
*/
|
||||
LinkedStringList **(*enumerateFiles)(DirHandle *r, const char *dirname);
|
||||
LinkedStringList *(*enumerateFiles)(DirHandle *r, const char *dirname);
|
||||
|
||||
/*
|
||||
* Returns non-zero if filename can be opened for reading.
|
||||
* This filename is in platform-independent notation.
|
||||
*/
|
||||
int (*exists)(DirHandle *r, const char *name);
|
||||
|
||||
/*
|
||||
* Returns non-zero if filename is really a directory.
|
||||
|
@ -137,15 +157,12 @@ typedef struct __PHYSFS_DIRFUNCTIONS__
|
|||
*/
|
||||
int (*isSymLink)(DirHandle *r, const char *name);
|
||||
|
||||
/*
|
||||
* Returns non-zero if filename can be opened for reading.
|
||||
* This filename is in platform-independent notation.
|
||||
*/
|
||||
int (*isOpenable)(DirHandle *r, const char *name);
|
||||
|
||||
/*
|
||||
* Open file for reading, and return a FileHandle.
|
||||
* This filename is in platform-independent notation.
|
||||
* If you can't handle multiple opens of the same file,
|
||||
* you can opt to fail for the second call.
|
||||
* Returns NULL on failure, and calls __PHYSFS_setError().
|
||||
*/
|
||||
FileHandle *(*openRead)(DirHandle *r, const char *filename);
|
||||
|
||||
|
@ -153,6 +170,9 @@ typedef struct __PHYSFS_DIRFUNCTIONS__
|
|||
* Open file for writing, and return a FileHandle.
|
||||
* This filename is in platform-independent notation.
|
||||
* This method may be NULL.
|
||||
* If you can't handle multiple opens of the same file,
|
||||
* you can opt to fail for the second call.
|
||||
* Returns NULL on failure, and calls __PHYSFS_setError().
|
||||
*/
|
||||
FileHandle *(*openWrite)(DirHandle *r, const char *filename);
|
||||
|
||||
|
@ -160,9 +180,33 @@ typedef struct __PHYSFS_DIRFUNCTIONS__
|
|||
* Open file for appending, and return a FileHandle.
|
||||
* This filename is in platform-independent notation.
|
||||
* This method may be NULL.
|
||||
* If you can't handle multiple opens of the same file,
|
||||
* you can opt to fail for the second call.
|
||||
* Returns NULL on failure, and calls __PHYSFS_setError().
|
||||
*/
|
||||
FileHandle *(*openAppend)(DirHandle *r, const char *filename);
|
||||
|
||||
/*
|
||||
* Delete a file in the archive/directory.
|
||||
* Return non-zero on success, zero on failure.
|
||||
* This filename is in platform-independent notation.
|
||||
* This method may be NULL.
|
||||
* On failure, call __PHYSFS_setError().
|
||||
*/
|
||||
int (*remove)(DirHandle *r, const char *filename);
|
||||
|
||||
/*
|
||||
* Create a directory in the archive/directory.
|
||||
* If the application is trying to make multiple dirs, PhysicsFS
|
||||
* will split them up into multiple calls before passing them to
|
||||
* your driver.
|
||||
* Return non-zero on success, zero on failure.
|
||||
* This filename is in platform-independent notation.
|
||||
* This method may be NULL.
|
||||
* On failure, call __PHYSFS_setError().
|
||||
*/
|
||||
int (*mkdir)(DirHandle *r, const char *filename);
|
||||
|
||||
/*
|
||||
* Close directories/archives, and free the handle, including
|
||||
* the "opaque" entry. This should assume that it won't be called if
|
||||
|
@ -176,25 +220,59 @@ typedef struct __PHYSFS_DIRFUNCTIONS__
|
|||
#define ERR_IS_INITIALIZED "Already initialized"
|
||||
#define ERR_NOT_INITIALIZED "Not initialized"
|
||||
#define ERR_INVALID_ARGUMENT "Invalid argument"
|
||||
#define ERR_FILES_OPEN_READ "Files still open for reading"
|
||||
#define ERR_FILES_OPEN_WRITE "Files still open for writing"
|
||||
#define ERR_FILES_STILL_OPEN "Files still open"
|
||||
#define ERR_NO_DIR_CREATE "Failed to create directories"
|
||||
#define ERR_OUT_OF_MEMORY "Out of memory"
|
||||
#define ERR_NOT_IN_SEARCH_PATH "No such entry in search path"
|
||||
#define ERR_NOT_SUPPORTED "Operation not supported"
|
||||
#define ERR_UNSUPPORTED_ARCHIVE "Archive type unsupported"
|
||||
#define ERR_NOT_A_HANDLE "Not a file handle"
|
||||
#define ERR_INSECURE_FNAME "Insecure filename"
|
||||
#define ERR_SYMLINK_DISALLOWED "Symbolic links are disabled"
|
||||
#define ERR_NO_WRITE_DIR "Write directory is not set"
|
||||
|
||||
|
||||
/*
|
||||
* Call this to set the message returned by PHYSFS_getLastError().
|
||||
* Please only use the ERR_* constants above, or add new constants to the
|
||||
* above group, but I want these all in one place.
|
||||
*
|
||||
* Calling this with a NULL argument is a safe no-op.
|
||||
*/
|
||||
void __PHYSFS_setError(const char *err);
|
||||
|
||||
|
||||
/*
|
||||
* Convert (dirName) to platform-dependent notation, then prepend (prepend)
|
||||
* and append (append) to the converted string.
|
||||
*
|
||||
* So, on Win32, calling:
|
||||
* __PHYSFS_convertToDependentNotation("C:\", "my/files", NULL);
|
||||
* ...will return the string "C:\my\files".
|
||||
*
|
||||
* This is a convenience function; you might want to hack something out that
|
||||
* is less generic (and therefore more efficient).
|
||||
*
|
||||
* Be sure to free() the return value when done with it.
|
||||
*/
|
||||
char *__PHYSFS_convertToDependentNotation(const char *prepend,
|
||||
const char *dirName,
|
||||
const char *append);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Returns non-zero if string is safe, zero if there's a security issue.
|
||||
* PHYSFS_getLastError() will specify what was wrong.
|
||||
*/
|
||||
int __PHYSFS_verifySecurity(DirHandle *h, const char *fname);
|
||||
|
||||
|
||||
/* This gets used all over for lessening code clutter. */
|
||||
#define BAIL_IF_MACRO(c, e, r) if (c) { __PHYSFS_setError(e); return(r); }
|
||||
#define BAIL_IF_MACRO(c, e, r) if (c) { __PHYSFS_setError(e); return r; }
|
||||
|
||||
|
||||
|
||||
|
@ -214,7 +292,7 @@ void __PHYSFS_setError(const char *err);
|
|||
* The dir separator; "/" on unix, "\\" on win32, ":" on MacOS, etc...
|
||||
* Obviously, this isn't a function, but it IS a null-terminated string.
|
||||
*/
|
||||
extern const char *__PHYSFS_PlatformDirSeparator;
|
||||
extern const char *__PHYSFS_platformDirSeparator;
|
||||
|
||||
/*
|
||||
* Platform implementation of PHYSFS_getCdRomDirs()...
|
||||
|
@ -262,6 +340,11 @@ int __PHYSFS_platformStricmp(const char *str1, const char *str2);
|
|||
*/
|
||||
int __PHYSFS_platformIsSymlink(const char *fname);
|
||||
|
||||
/*
|
||||
* Return non-zero if filename (in platform-dependent notation) is a symlink.
|
||||
*/
|
||||
int __PHYSFS_platformIsDirectory(const char *fname);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
21
unix.c
21
unix.c
|
@ -14,7 +14,7 @@
|
|||
#include "physfs_internal.h"
|
||||
|
||||
|
||||
const char *__PHYSFS_PlatformDirSeparator = "/";
|
||||
const char *__PHYSFS_platformDirSeparator = "/";
|
||||
|
||||
char **__PHYSFS_platformDetectAvailableCDs(void)
|
||||
{
|
||||
|
@ -27,6 +27,16 @@ char *__PHYSFS_platformCalcBaseDir(char *argv0)
|
|||
} /* __PHYSFS_platformCalcBaseDir */
|
||||
|
||||
|
||||
char *__PHYSFS_platformGetUserName(void)
|
||||
{
|
||||
} /* __PHYSFS_platformGetUserName */
|
||||
|
||||
|
||||
char *__PHYSFS_platformGetUserDir(void)
|
||||
{
|
||||
} /* __PHYSFS_platformGetUserDir */
|
||||
|
||||
|
||||
int __PHYSFS_platformGetThreadID(void)
|
||||
{
|
||||
return((int) pthread_self());
|
||||
|
@ -44,14 +54,9 @@ int __PHYSFS_platformIsSymlink(const char *fname)
|
|||
} /* __PHYSFS_platformIsSymlink */
|
||||
|
||||
|
||||
char *__PHYSFS_platformGetUserName(void)
|
||||
int __PHYSFS_platformIsDirectory(const char *fname)
|
||||
{
|
||||
} /* __PHYSFS_platformGetUserName */
|
||||
|
||||
|
||||
char *__PHYSFS_platformGetUserDir(void);
|
||||
{
|
||||
} /* __PHYSFS_platformGetUserDir */
|
||||
} /* __PHYSFS_platformIsDirectory */
|
||||
|
||||
|
||||
/* end of unix.c ... */
|
||||
|
|
Loading…
Reference in New Issue