Added callback APIs and ripped up the internals everywhere to use them.
This commit is contained in:
parent
80535e9b83
commit
c2765f8571
|
@ -2,6 +2,13 @@
|
|||
* CHANGELOG.
|
||||
*/
|
||||
|
||||
09292004 - Every API that can return a list of strings can now use a
|
||||
callback mechanism if the application wants to do it's own
|
||||
allocation or handling on a per-item basis. The guts of those
|
||||
APIs that create string lists now use the callbacks themselves to
|
||||
build the lists, too. The callback functionality goes all the way
|
||||
down to the archivers and platform drivers where appropriate, which
|
||||
cleans things up and simplifies some internal tasks very nicely.
|
||||
09262004 - Did the same thing to FileHandles than I did to DirHandles, but
|
||||
this triggered massive tweaking in physfs.c. A lot of code got
|
||||
little cleanups, which was nice. Less malloc pressure, too, since
|
||||
|
|
2
TODO
2
TODO
|
@ -22,7 +22,6 @@ Some might be dupes, some might be done already.
|
|||
- Cygwin should use unix/posix and not win32 platform code.
|
||||
- Add "mount points"
|
||||
- Expose the archiver registration mechanism to the outside world.
|
||||
- Set up a mechanism for file enumeration that employs a callback.
|
||||
- Allow the application to provide allocation services.
|
||||
- Find some way to relax or remove the security model for external tools.
|
||||
- Non-blocking I/O
|
||||
|
@ -41,7 +40,6 @@ Some might be dupes, some might be done already.
|
|||
- Deprecate PHYSFS_setSaneConfig and move it to extras?
|
||||
- (Re)move the profiling code in physfs.c.
|
||||
- Why is physfsrwops.c cut-and-pasted into the ruby bindings?
|
||||
- Get rid of addToLinkedStringList
|
||||
- Replace code from SDL...
|
||||
- MIX grabs all archives that no other archivers claim.
|
||||
- MIX enumerates files as hash values.
|
||||
|
|
|
@ -29,9 +29,9 @@ static PHYSFS_sint64 DIR_fileLength(fvoid *opaque);
|
|||
static int DIR_fileClose(fvoid *opaque);
|
||||
static int DIR_isArchive(const char *filename, int forWriting);
|
||||
static void *DIR_openArchive(const char *name, int forWriting);
|
||||
static LinkedStringList *DIR_enumerateFiles(dvoid *opaque,
|
||||
const char *dname,
|
||||
int omitSymLinks);
|
||||
static void DIR_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_StringCallback cb,
|
||||
void *callbackdata);
|
||||
static int DIR_exists(dvoid *opaque, const char *name);
|
||||
static int DIR_isDirectory(dvoid *opaque, const char *name, int *fileExists);
|
||||
static int DIR_isSymLink(dvoid *opaque, const char *name, int *fileExists);
|
||||
|
@ -165,17 +165,16 @@ static void *DIR_openArchive(const char *name, int forWriting)
|
|||
} /* DIR_openArchive */
|
||||
|
||||
|
||||
static LinkedStringList *DIR_enumerateFiles(dvoid *opaque,
|
||||
const char *dname,
|
||||
int omitSymLinks)
|
||||
static void DIR_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_StringCallback cb,
|
||||
void *callbackdata)
|
||||
{
|
||||
char *d = __PHYSFS_platformCvtToDependent((char *)opaque, dname, NULL);
|
||||
LinkedStringList *retval;
|
||||
|
||||
BAIL_IF_MACRO(d == NULL, NULL, NULL);
|
||||
retval = __PHYSFS_platformEnumerateFiles(d, omitSymLinks);
|
||||
if (d != NULL)
|
||||
{
|
||||
__PHYSFS_platformEnumerateFiles(d, omitSymLinks, cb, callbackdata);
|
||||
free(d);
|
||||
return(retval);
|
||||
} /* if */
|
||||
} /* DIR_enumerateFiles */
|
||||
|
||||
|
||||
|
|
|
@ -72,9 +72,9 @@ static PHYSFS_sint64 GRP_fileLength(fvoid *opaque);
|
|||
static int GRP_fileClose(fvoid *opaque);
|
||||
static int GRP_isArchive(const char *filename, int forWriting);
|
||||
static void *GRP_openArchive(const char *name, int forWriting);
|
||||
static LinkedStringList *GRP_enumerateFiles(dvoid *opaque,
|
||||
const char *dirname,
|
||||
int omitSymLinks);
|
||||
static void GRP_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_StringCallback cb,
|
||||
void *callbackdata);
|
||||
static int GRP_exists(dvoid *opaque, const char *name);
|
||||
static int GRP_isDirectory(dvoid *opaque, const char *name, int *fileExists);
|
||||
static int GRP_isSymLink(dvoid *opaque, const char *name, int *fileExists);
|
||||
|
@ -359,23 +359,21 @@ GRP_openArchive_failed:
|
|||
} /* GRP_openArchive */
|
||||
|
||||
|
||||
static LinkedStringList *GRP_enumerateFiles(dvoid *opaque,
|
||||
const char *dirname,
|
||||
int omitSymLinks)
|
||||
static void GRP_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_StringCallback cb,
|
||||
void *callbackdata)
|
||||
{
|
||||
/* no directories in GRP files. */
|
||||
if (*dname != '\0')
|
||||
{
|
||||
GRPinfo *info = (GRPinfo *) opaque;
|
||||
GRPentry *entry = info->entries;
|
||||
LinkedStringList *retval = NULL, *p = NULL;
|
||||
PHYSFS_uint32 max = info->entryCount;
|
||||
PHYSFS_uint32 i;
|
||||
|
||||
/* no directories in GRP files. */
|
||||
BAIL_IF_MACRO(*dirname != '\0', ERR_NOT_A_DIR, NULL);
|
||||
|
||||
for (i = 0; i < max; i++, entry++)
|
||||
retval = __PHYSFS_addToLinkedStringList(retval, &p, entry->name, -1);
|
||||
|
||||
return(retval);
|
||||
cb(callbackdata, entry->name);
|
||||
} /* if */
|
||||
} /* GRP_enumerateFiles */
|
||||
|
||||
|
||||
|
|
|
@ -86,9 +86,9 @@ static PHYSFS_sint64 HOG_fileLength(fvoid *opaque);
|
|||
static int HOG_fileClose(fvoid *opaque);
|
||||
static int HOG_isArchive(const char *filename, int forWriting);
|
||||
static void *HOG_openArchive(const char *name, int forWriting);
|
||||
static LinkedStringList *HOG_enumerateFiles(dvoid *opaque,
|
||||
const char *dirname,
|
||||
int omitSymLinks);
|
||||
static void HOG_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_StringCallback cb,
|
||||
void *callbackdata);
|
||||
static int HOG_exists(dvoid *opaque, const char *name);
|
||||
static int HOG_isDirectory(dvoid *opaque, const char *name, int *fileExists);
|
||||
static int HOG_isSymLink(dvoid *opaque, const char *name, int *fileExists);
|
||||
|
@ -398,23 +398,21 @@ HOG_openArchive_failed:
|
|||
} /* HOG_openArchive */
|
||||
|
||||
|
||||
static LinkedStringList *HOG_enumerateFiles(dvoid *opaque,
|
||||
const char *dirname,
|
||||
int omitSymLinks)
|
||||
static void HOG_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_StringCallback cb,
|
||||
void *callbackdata)
|
||||
{
|
||||
HOGinfo *info = ((HOGinfo *) opaque);
|
||||
/* no directories in HOG files. */
|
||||
if (*dname != '\0')
|
||||
{
|
||||
HOGinfo *info = (HOGinfo *) opaque;
|
||||
HOGentry *entry = info->entries;
|
||||
LinkedStringList *retval = NULL, *p = NULL;
|
||||
PHYSFS_uint32 max = info->entryCount;
|
||||
PHYSFS_uint32 i;
|
||||
|
||||
/* no directories in HOG files. */
|
||||
BAIL_IF_MACRO(*dirname != '\0', ERR_NOT_A_DIR, NULL);
|
||||
|
||||
for (i = 0; i < max; i++, entry++)
|
||||
retval = __PHYSFS_addToLinkedStringList(retval, &p, entry->name, -1);
|
||||
|
||||
return(retval);
|
||||
cb(callbackdata, entry->name);
|
||||
} /* if */
|
||||
} /* HOG_enumerateFiles */
|
||||
|
||||
|
||||
|
|
|
@ -91,9 +91,9 @@ static PHYSFS_sint64 MIX_fileLength(fvoid *opaque);
|
|||
static int MIX_fileClose(fvoid *opaque);
|
||||
static int MIX_isArchive(const char *filename, int forWriting);
|
||||
static void *MIX_openArchive(const char *name, int forWriting);
|
||||
static LinkedStringList *MIX_enumerateFiles(dvoid *opaque,
|
||||
const char *dirname,
|
||||
int omitSymLinks);
|
||||
static void MIX_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_StringCallback cb,
|
||||
void *callbackdata)
|
||||
static int MIX_exists(dvoid *opaque, const char *name);
|
||||
static int MIX_isDirectory(dvoid *opaque, const char *name, int *fileExists);
|
||||
static int MIX_isSymLink(dvoid *opaque, const char *name, int *fileExists);
|
||||
|
@ -354,11 +354,13 @@ MIX_openArchive_failed:
|
|||
} /* MIX_openArchive */
|
||||
|
||||
|
||||
static LinkedStringList *MIX_enumerateFiles(dvoid *opaque,
|
||||
const char *dirname,
|
||||
int omitSymLinks)
|
||||
static void MIX_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_StringCallback cb,
|
||||
void *callbackdata)
|
||||
{
|
||||
/* no directories in MIX files. */
|
||||
if (*dirname != '\0')
|
||||
{
|
||||
LinkedStringList *retval = NULL, *p = NULL;
|
||||
MIXinfo *info = (MIXinfo*) opaque;
|
||||
MIXentry *entry = info->entry;
|
||||
int i;
|
||||
|
@ -367,10 +369,9 @@ static LinkedStringList *MIX_enumerateFiles(dvoid *opaque,
|
|||
for (i = 0; i < info->header.num_files; i++, entry++)
|
||||
{
|
||||
sprintf(buffer, "%X", entry->hash);
|
||||
retval = __PHYSFS_addToLinkedStringList(retval, &p, buffer, -1);
|
||||
cb(callbackdata, buffer);
|
||||
} /* for */
|
||||
|
||||
return(retval);
|
||||
} /* if */
|
||||
} /* MIX_enumerateFiles */
|
||||
|
||||
|
||||
|
|
|
@ -75,9 +75,9 @@ static PHYSFS_sint64 MVL_fileLength(fvoid *opaque);
|
|||
static int MVL_fileClose(fvoid *opaque);
|
||||
static int MVL_isArchive(const char *filename, int forWriting);
|
||||
static void *MVL_openArchive(const char *name, int forWriting);
|
||||
static LinkedStringList *MVL_enumerateFiles(dvoid *opaque,
|
||||
const char *dirname,
|
||||
int omitSymLinks);
|
||||
static void MVL_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_StringCallback cb,
|
||||
void *callbackdata);
|
||||
static int MVL_exists(dvoid *opaque, const char *name);
|
||||
static int MVL_isDirectory(dvoid *opaque, const char *name, int *fileExists);
|
||||
static int MVL_isSymLink(dvoid *opaque, const char *name, int *fileExists);
|
||||
|
@ -356,23 +356,21 @@ MVL_openArchive_failed:
|
|||
} /* MVL_openArchive */
|
||||
|
||||
|
||||
static LinkedStringList *MVL_enumerateFiles(dvoid *opaque,
|
||||
const char *dirname,
|
||||
int omitSymLinks)
|
||||
static void MVL_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_StringCallback cb,
|
||||
void *callbackdata)
|
||||
{
|
||||
/* no directories in MVL files. */
|
||||
if (*dname != '\0')
|
||||
{
|
||||
MVLinfo *info = ((MVLinfo *) opaque);
|
||||
MVLentry *entry = info->entries;
|
||||
LinkedStringList *retval = NULL, *p = NULL;
|
||||
PHYSFS_uint32 max = info->entryCount;
|
||||
PHYSFS_uint32 i;
|
||||
|
||||
/* no directories in MVL files. */
|
||||
BAIL_IF_MACRO(*dirname != '\0', ERR_NOT_A_DIR, NULL);
|
||||
|
||||
for (i = 0; i < max; i++, entry++)
|
||||
retval = __PHYSFS_addToLinkedStringList(retval, &p, entry->name, -1);
|
||||
|
||||
return(retval);
|
||||
cb(callbackdata, entry->name);
|
||||
} /* if */
|
||||
} /* MVL_enumerateFiles */
|
||||
|
||||
|
||||
|
|
|
@ -89,9 +89,9 @@ static PHYSFS_sint64 QPAK_fileLength(fvoid *opaque);
|
|||
static int QPAK_fileClose(fvoid *opaque);
|
||||
static int QPAK_isArchive(const char *filename, int forWriting);
|
||||
static void *QPAK_openArchive(const char *name, int forWriting);
|
||||
static LinkedStringList *QPAK_enumerateFiles(dvoid *opaque,
|
||||
const char *dirname,
|
||||
int omitSymLinks);
|
||||
static void QPAK_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_StringCallback cb,
|
||||
void *callbackdata);
|
||||
static int QPAK_exists(dvoid *opaque, const char *name);
|
||||
static int QPAK_isDirectory(dvoid *opaque, const char *name, int *fileExists);
|
||||
static int QPAK_isSymLink(dvoid *opaque, const char *name, int *fileExists);
|
||||
|
@ -443,19 +443,36 @@ static PHYSFS_sint32 qpak_find_start_of_dir(QPAKinfo *info, const char *path,
|
|||
} /* qpak_find_start_of_dir */
|
||||
|
||||
|
||||
static LinkedStringList *QPAK_enumerateFiles(dvoid *opaque,
|
||||
const char *dirname,
|
||||
int omitSymLinks)
|
||||
/*
|
||||
* Moved to seperate function so we can use alloca then immediately throw
|
||||
* away the allocated stack space...
|
||||
*/
|
||||
static void doEnumCallback(PHYSFS_StringCallback cb, void *callbackdata,
|
||||
const char *str, PHYSFS_sint32 ln)
|
||||
{
|
||||
char *newstr = alloca(ln + 1);
|
||||
if (newstr == NULL)
|
||||
return;
|
||||
|
||||
memcpy(newstr, str, ln);
|
||||
newstr[ln] = '\0';
|
||||
cb(callbackdata, newstr);
|
||||
} /* doEnumCallback */
|
||||
|
||||
|
||||
static void QPAK_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_StringCallback cb,
|
||||
void *callbackdata)
|
||||
{
|
||||
QPAKinfo *info = ((QPAKinfo *) opaque);
|
||||
LinkedStringList *retval = NULL, *p = NULL;
|
||||
PHYSFS_sint32 dlen, dlen_inc, max, i;
|
||||
|
||||
i = qpak_find_start_of_dir(info, dirname, 0);
|
||||
BAIL_IF_MACRO(i == -1, ERR_NO_SUCH_FILE, NULL);
|
||||
i = qpak_find_start_of_dir(info, dname, 0);
|
||||
if (i == -1) /* no such directory. */
|
||||
return;
|
||||
|
||||
dlen = strlen(dirname);
|
||||
if ((dlen > 0) && (dirname[dlen - 1] == '/')) /* ignore trailing slash. */
|
||||
dlen = strlen(dname);
|
||||
if ((dlen > 0) && (dname[dlen - 1] == '/')) /* ignore trailing slash. */
|
||||
dlen--;
|
||||
|
||||
dlen_inc = ((dlen > 0) ? 1 : 0) + dlen;
|
||||
|
@ -466,13 +483,13 @@ static LinkedStringList *QPAK_enumerateFiles(dvoid *opaque,
|
|||
char *ptr;
|
||||
PHYSFS_sint32 ln;
|
||||
char *e = info->entries[i].name;
|
||||
if ((dlen) && ((QPAK_strncmp(e, dirname, dlen)) || (e[dlen] != '/')))
|
||||
if ((dlen) && ((QPAK_strncmp(e, dname, dlen)) || (e[dlen] != '/')))
|
||||
break; /* past end of this dir; we're done. */
|
||||
|
||||
add = e + dlen_inc;
|
||||
ptr = strchr(add, '/');
|
||||
ln = (PHYSFS_sint32) ((ptr) ? ptr-add : strlen(add));
|
||||
retval = __PHYSFS_addToLinkedStringList(retval, &p, add, ln);
|
||||
doEnumCallback(cb, callbackdata, add, ln);
|
||||
ln += dlen_inc; /* point past entry to children... */
|
||||
|
||||
/* increment counter and skip children of subdirs... */
|
||||
|
@ -483,8 +500,6 @@ static LinkedStringList *QPAK_enumerateFiles(dvoid *opaque,
|
|||
break;
|
||||
} /* while */
|
||||
} /* while */
|
||||
|
||||
return(retval);
|
||||
} /* QPAK_enumerateFiles */
|
||||
|
||||
|
||||
|
|
|
@ -91,9 +91,9 @@ static PHYSFS_sint64 WAD_fileLength(fvoid *opaque);
|
|||
static int WAD_fileClose(fvoid *opaque);
|
||||
static int WAD_isArchive(const char *filename, int forWriting);
|
||||
static void *WAD_openArchive(const char *name, int forWriting);
|
||||
static LinkedStringList *WAD_enumerateFiles(dvoid *opaque,
|
||||
const char *dirname,
|
||||
int omitSymLinks);
|
||||
static void WAD_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_StringCallback cb,
|
||||
void *callbackdata);
|
||||
static int WAD_exists(dvoid *opaque, const char *name);
|
||||
static int WAD_isDirectory(dvoid *opaque, const char *name, int *fileExists);
|
||||
static int WAD_isSymLink(dvoid *opaque, const char *name, int *fileExists);
|
||||
|
@ -386,45 +386,39 @@ WAD_openArchive_failed:
|
|||
} /* WAD_openArchive */
|
||||
|
||||
|
||||
static LinkedStringList *WAD_enumerateFiles(dvoid *opaque,
|
||||
const char *dirname,
|
||||
int omitSymLinks)
|
||||
static void WAD_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_StringCallback cb,
|
||||
void *callbackdata)
|
||||
{
|
||||
WADinfo *info = ((WADinfo *) opaque);
|
||||
WADentry *entry = info->entries;
|
||||
LinkedStringList *retval = NULL, *p = NULL;
|
||||
PHYSFS_uint32 max = info->entryCount;
|
||||
PHYSFS_uint32 i;
|
||||
const char *name;
|
||||
char *sep;
|
||||
|
||||
if (dirname[0] == 0)
|
||||
if (*dname == '\0') /* root directory enumeration? */
|
||||
{
|
||||
for (i = 0; i < max; i++, entry++)
|
||||
{
|
||||
if (strchr(entry->name, '/') == NULL)
|
||||
{
|
||||
retval = __PHYSFS_addToLinkedStringList(retval, &p,
|
||||
entry->name, -1);
|
||||
} /* if */
|
||||
name = entry->name;
|
||||
if (strchr(name, '/') == NULL)
|
||||
cb(callbackdata, name);
|
||||
} /* for */
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
for (i = 0; i < max; i++, entry++)
|
||||
{
|
||||
sep = strchr(entry->name, '/');
|
||||
name = entry->name;
|
||||
sep = strchr(name, '/');
|
||||
if (sep != NULL)
|
||||
{
|
||||
if (strncmp(dirname, entry->name, (sep-entry->name)) == 0)
|
||||
{
|
||||
retval = __PHYSFS_addToLinkedStringList(retval, &p,
|
||||
sep + 1, -1);
|
||||
} /* if */
|
||||
if (strncmp(dname, name, (sep - name)) == 0)
|
||||
cb(callbackdata, sep + 1);
|
||||
} /* if */
|
||||
} /* for */
|
||||
} /* else */
|
||||
|
||||
return(retval);
|
||||
} /* WAD_enumerateFiles */
|
||||
|
||||
|
||||
|
|
|
@ -127,9 +127,9 @@ static PHYSFS_sint64 ZIP_fileLength(fvoid *opaque);
|
|||
static int ZIP_fileClose(fvoid *opaque);
|
||||
static int ZIP_isArchive(const char *filename, int forWriting);
|
||||
static void *ZIP_openArchive(const char *name, int forWriting);
|
||||
static LinkedStringList *ZIP_enumerateFiles(dvoid *opaque,
|
||||
const char *dirname,
|
||||
int omitSymLinks);
|
||||
static void ZIP_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_StringCallback cb,
|
||||
void *callbackdata);
|
||||
static int ZIP_exists(dvoid *opaque, const char *name);
|
||||
static int ZIP_isDirectory(dvoid *opaque, const char *name, int *fileExists);
|
||||
static int ZIP_isSymLink(dvoid *opaque, const char *name, int *fileExists);
|
||||
|
@ -1235,19 +1235,36 @@ static PHYSFS_sint32 zip_find_start_of_dir(ZIPinfo *info, const char *path,
|
|||
} /* zip_find_start_of_dir */
|
||||
|
||||
|
||||
static LinkedStringList *ZIP_enumerateFiles(dvoid *opaque,
|
||||
const char *dirname,
|
||||
int omitSymLinks)
|
||||
/*
|
||||
* Moved to seperate function so we can use alloca then immediately throw
|
||||
* away the allocated stack space...
|
||||
*/
|
||||
static void doEnumCallback(PHYSFS_StringCallback cb, void *callbackdata,
|
||||
const char *str, PHYSFS_sint32 ln)
|
||||
{
|
||||
char *newstr = alloca(ln + 1);
|
||||
if (newstr == NULL)
|
||||
return;
|
||||
|
||||
memcpy(newstr, str, ln);
|
||||
newstr[ln] = '\0';
|
||||
cb(callbackdata, newstr);
|
||||
} /* doEnumCallback */
|
||||
|
||||
|
||||
static void ZIP_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_StringCallback cb,
|
||||
void *callbackdata)
|
||||
{
|
||||
ZIPinfo *info = ((ZIPinfo *) opaque);
|
||||
LinkedStringList *retval = NULL, *p = NULL;
|
||||
PHYSFS_sint32 dlen, dlen_inc, max, i;
|
||||
|
||||
i = zip_find_start_of_dir(info, dirname, 0);
|
||||
BAIL_IF_MACRO(i == -1, ERR_NO_SUCH_FILE, NULL);
|
||||
i = zip_find_start_of_dir(info, dname, 0);
|
||||
if (i == -1) /* no such directory. */
|
||||
return;
|
||||
|
||||
dlen = strlen(dirname);
|
||||
if ((dlen > 0) && (dirname[dlen - 1] == '/')) /* ignore trailing slash. */
|
||||
dlen = strlen(dname);
|
||||
if ((dlen > 0) && (dname[dlen - 1] == '/')) /* ignore trailing slash. */
|
||||
dlen--;
|
||||
|
||||
dlen_inc = ((dlen > 0) ? 1 : 0) + dlen;
|
||||
|
@ -1255,7 +1272,7 @@ static LinkedStringList *ZIP_enumerateFiles(dvoid *opaque,
|
|||
while (i < max)
|
||||
{
|
||||
char *e = info->entries[i].name;
|
||||
if ((dlen) && ((strncmp(e, dirname, dlen) != 0) || (e[dlen] != '/')))
|
||||
if ((dlen) && ((strncmp(e, dname, dlen) != 0) || (e[dlen] != '/')))
|
||||
break; /* past end of this dir; we're done. */
|
||||
|
||||
if ((omitSymLinks) && (zip_entry_is_symlink(&info->entries[i])))
|
||||
|
@ -1265,7 +1282,7 @@ static LinkedStringList *ZIP_enumerateFiles(dvoid *opaque,
|
|||
char *add = e + dlen_inc;
|
||||
char *ptr = strchr(add, '/');
|
||||
PHYSFS_sint32 ln = (PHYSFS_sint32) ((ptr) ? ptr-add : strlen(add));
|
||||
retval = __PHYSFS_addToLinkedStringList(retval, &p, add, ln);
|
||||
doEnumCallback(cb, callbackdata, add, ln);
|
||||
ln += dlen_inc; /* point past entry to children... */
|
||||
|
||||
/* increment counter and skip children of subdirs... */
|
||||
|
@ -1277,8 +1294,6 @@ static LinkedStringList *ZIP_enumerateFiles(dvoid *opaque,
|
|||
} /* while */
|
||||
} /* else */
|
||||
} /* while */
|
||||
|
||||
return(retval);
|
||||
} /* ZIP_enumerateFiles */
|
||||
|
||||
|
||||
|
|
205
physfs.c
205
physfs.c
|
@ -189,6 +189,54 @@ static PHYSFS_Allocator allocator;
|
|||
|
||||
/* functions ... */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char **list;
|
||||
PHYSFS_uint32 size;
|
||||
const char *errorstr;
|
||||
} EnumStringListCallbackData;
|
||||
|
||||
static void enumStringListCallback(void *data, const char *str)
|
||||
{
|
||||
void *ptr;
|
||||
char *newstr;
|
||||
EnumStringListCallbackData *pecd = (EnumStringListCallbackData *) data;
|
||||
|
||||
if (pecd->errorstr)
|
||||
return;
|
||||
|
||||
ptr = realloc(pecd->list, (pecd->size + 2) * sizeof (char *));
|
||||
newstr = malloc(strlen(str) + 1);
|
||||
if (ptr != NULL)
|
||||
pecd->list = (char **) ptr;
|
||||
|
||||
if ((ptr == NULL) || (newstr == NULL))
|
||||
{
|
||||
pecd->errorstr = ERR_OUT_OF_MEMORY;
|
||||
pecd->list[pecd->size] = NULL;
|
||||
PHYSFS_freeList(pecd->list);
|
||||
return;
|
||||
} /* if */
|
||||
|
||||
strcpy(newstr, str);
|
||||
pecd->list[pecd->size] = newstr;
|
||||
pecd->size++;
|
||||
} /* enumStringListCallback */
|
||||
|
||||
|
||||
static char **doEnumStringList(void (*func)(PHYSFS_StringCallback, void *))
|
||||
{
|
||||
EnumStringListCallbackData ecd;
|
||||
memset(&ecd, '\0', sizeof (ecd));
|
||||
ecd.list = (char **) malloc(sizeof (char *));
|
||||
BAIL_IF_MACRO(ecd.list == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
func(enumStringListCallback, &ecd);
|
||||
BAIL_IF_MACRO(ecd.errorstr != NULL, ecd.errorstr, NULL);
|
||||
ecd.list[ecd.size] = NULL;
|
||||
return(ecd.list);
|
||||
} /* doEnumStringList */
|
||||
|
||||
|
||||
static void __PHYSFS_bubble_sort(void *a, PHYSFS_uint32 lo, PHYSFS_uint32 hi,
|
||||
int (*cmpfn)(void *, PHYSFS_uint32, PHYSFS_uint32),
|
||||
void (*swapfn)(void *, PHYSFS_uint32, PHYSFS_uint32))
|
||||
|
@ -838,7 +886,6 @@ static int closeFileHandleList(FileHandle **list)
|
|||
{
|
||||
FileHandle *i;
|
||||
FileHandle *next = NULL;
|
||||
FileHandle *h;
|
||||
|
||||
for (i = *list; i != NULL; i = next)
|
||||
{
|
||||
|
@ -937,10 +984,16 @@ const char *PHYSFS_getDirSeparator(void)
|
|||
|
||||
char **PHYSFS_getCdRomDirs(void)
|
||||
{
|
||||
return(__PHYSFS_platformDetectAvailableCDs());
|
||||
return(doEnumStringList(__PHYSFS_platformDetectAvailableCDs));
|
||||
} /* PHYSFS_getCdRomDirs */
|
||||
|
||||
|
||||
void PHYSFS_getCdRomDirsCallback(PHYSFS_StringCallback callback, void *data)
|
||||
{
|
||||
__PHYSFS_platformDetectAvailableCDs(callback, data);
|
||||
} /* PHYSFS_getCdRomDirsCallback */
|
||||
|
||||
|
||||
const char *PHYSFS_getBaseDir(void)
|
||||
{
|
||||
return(baseDir); /* this is calculated in PHYSFS_init()... */
|
||||
|
@ -1060,42 +1113,21 @@ int PHYSFS_removeFromSearchPath(const char *oldDir)
|
|||
|
||||
char **PHYSFS_getSearchPath(void)
|
||||
{
|
||||
int count = 1;
|
||||
int x;
|
||||
return(doEnumStringList(PHYSFS_getSearchPathCallback));
|
||||
} /* PHYSFS_getSearchPath */
|
||||
|
||||
|
||||
void PHYSFS_getSearchPathCallback(PHYSFS_StringCallback callback, void *data)
|
||||
{
|
||||
DirHandle *i;
|
||||
char **retval;
|
||||
|
||||
__PHYSFS_platformGrabMutex(stateLock);
|
||||
|
||||
for (i = searchPath; i != NULL; i = i->next)
|
||||
count++;
|
||||
|
||||
retval = (char **) malloc(sizeof (char *) * count);
|
||||
BAIL_IF_MACRO_MUTEX(!retval, ERR_OUT_OF_MEMORY, stateLock, NULL);
|
||||
count--;
|
||||
retval[count] = NULL;
|
||||
|
||||
for (i = searchPath, x = 0; x < count; i = i->next, x++)
|
||||
{
|
||||
retval[x] = (char *) malloc(strlen(i->dirName) + 1);
|
||||
if (retval[x] == NULL) /* this is friggin' ugly. */
|
||||
{
|
||||
while (x > 0)
|
||||
{
|
||||
x--;
|
||||
free(retval[x]);
|
||||
} /* while */
|
||||
|
||||
free(retval);
|
||||
BAIL_MACRO_MUTEX(ERR_OUT_OF_MEMORY, stateLock, NULL);
|
||||
} /* if */
|
||||
|
||||
strcpy(retval[x], i->dirName);
|
||||
} /* for */
|
||||
callback(data, i->dirName);
|
||||
|
||||
__PHYSFS_platformReleaseMutex(stateLock);
|
||||
return(retval);
|
||||
} /* PHYSFS_getSearchPath */
|
||||
} /* PHYSFS_getSearchPathCallback */
|
||||
|
||||
|
||||
int PHYSFS_setSaneConfig(const char *organization, const char *appName,
|
||||
|
@ -1441,7 +1473,7 @@ const char *PHYSFS_getRealDir(const char *filename)
|
|||
return(retval);
|
||||
} /* PHYSFS_getRealDir */
|
||||
|
||||
|
||||
#if 0
|
||||
static int countList(LinkedStringList *list)
|
||||
{
|
||||
int retval = 0;
|
||||
|
@ -1529,34 +1561,114 @@ static void interpolateStringLists(LinkedStringList **final,
|
|||
newList = next;
|
||||
} /* while */
|
||||
} /* interpolateStringLists */
|
||||
#endif
|
||||
|
||||
|
||||
static int locateInStringList(const char *str,
|
||||
char **list,
|
||||
PHYSFS_uint32 *pos)
|
||||
{
|
||||
PHYSFS_uint32 hi = *pos - 1;
|
||||
PHYSFS_uint32 lo = 0;
|
||||
PHYSFS_uint32 i = hi / 2;
|
||||
int cmp;
|
||||
|
||||
while (hi != lo)
|
||||
{
|
||||
cmp = strcmp(list[i], str);
|
||||
if (cmp == 0) /* it's in the list already. */
|
||||
return(1);
|
||||
else if (cmp < 0)
|
||||
hi = i;
|
||||
else
|
||||
lo = i;
|
||||
i = lo + ((hi - lo) / 2);
|
||||
} /* while */
|
||||
|
||||
/* hi == lo, check it in case it's the match... */
|
||||
cmp = strcmp(list[lo], str);
|
||||
if (cmp == 0)
|
||||
return(1);
|
||||
|
||||
/* not in the list, set insertion point... */
|
||||
*pos = (cmp < 0) ? lo : lo + 1;
|
||||
return(0);
|
||||
} /* locateInStringList */
|
||||
|
||||
|
||||
static void enumFilesCallback(void *data, const char *str)
|
||||
{
|
||||
PHYSFS_uint32 pos;
|
||||
void *ptr;
|
||||
char *newstr;
|
||||
EnumStringListCallbackData *pecd = (EnumStringListCallbackData *) data;
|
||||
|
||||
/*
|
||||
* See if file is in the list already, and if not, insert it in there
|
||||
* alphabetically...
|
||||
*/
|
||||
pos = pecd->size;
|
||||
if (pos > 0)
|
||||
{
|
||||
if (locateInStringList(str, pecd->list, &pos))
|
||||
return; /* already in the list. */
|
||||
} /* if */
|
||||
|
||||
ptr = realloc(pecd->list, (pecd->size + 2) * sizeof (char *));
|
||||
newstr = malloc(strlen(str) + 1);
|
||||
if (ptr != NULL)
|
||||
pecd->list = (char **) ptr;
|
||||
|
||||
if ((ptr == NULL) || (newstr == NULL))
|
||||
return; /* better luck next time. */
|
||||
|
||||
strcpy(newstr, str);
|
||||
|
||||
if (pos != pecd->size)
|
||||
{
|
||||
memmove(&pecd->list[pos+1], &pecd->list[pos],
|
||||
sizeof (char *) * ((pecd->size) - pos));
|
||||
} /* if */
|
||||
|
||||
pecd->list[pos] = newstr;
|
||||
pecd->size++;
|
||||
} /* enumFilesCallback */
|
||||
|
||||
|
||||
char **PHYSFS_enumerateFiles(const char *path)
|
||||
{
|
||||
DirHandle *i;
|
||||
char **retval = NULL;
|
||||
LinkedStringList *rc;
|
||||
LinkedStringList *finalList = NULL;
|
||||
int omitSymLinks = !allowSymLinks;
|
||||
EnumStringListCallbackData ecd;
|
||||
memset(&ecd, '\0', sizeof (ecd));
|
||||
ecd.list = (char **) malloc(sizeof (char *));
|
||||
BAIL_IF_MACRO(ecd.list == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
PHYSFS_enumerateFilesCallback(path, enumFilesCallback, &ecd);
|
||||
ecd.list[ecd.size] = NULL;
|
||||
return(ecd.list);
|
||||
} /* PHYSFS_enumerateFiles */
|
||||
|
||||
|
||||
void PHYSFS_enumerateFilesCallback(const char *path,
|
||||
PHYSFS_StringCallback callback,
|
||||
void *data)
|
||||
{
|
||||
DirHandle *i;
|
||||
int noSyms;
|
||||
|
||||
if ((path == NULL) || (callback == NULL))
|
||||
return;
|
||||
|
||||
BAIL_IF_MACRO(path == NULL, ERR_INVALID_ARGUMENT, NULL);
|
||||
while (*path == '/')
|
||||
path++;
|
||||
|
||||
__PHYSFS_platformGrabMutex(stateLock);
|
||||
noSyms = !allowSymLinks;
|
||||
for (i = searchPath; i != NULL; i = i->next)
|
||||
{
|
||||
if (__PHYSFS_verifySecurity(i, path, 0))
|
||||
{
|
||||
rc = i->funcs->enumerateFiles(i->opaque, path, omitSymLinks);
|
||||
interpolateStringLists(&finalList, rc);
|
||||
} /* if */
|
||||
i->funcs->enumerateFiles(i->opaque, path, noSyms, callback, data);
|
||||
} /* for */
|
||||
__PHYSFS_platformReleaseMutex(stateLock);
|
||||
|
||||
retval = convertStringListToPhysFSList(finalList);
|
||||
return(retval);
|
||||
} /* PHYSFS_enumerateFiles */
|
||||
} /* PHYSFS_enumerateFilesCallback */
|
||||
|
||||
|
||||
int PHYSFS_exists(const char *fname)
|
||||
|
@ -2077,6 +2189,5 @@ PHYSFS_Allocator *__PHYSFS_getAllocator(void)
|
|||
return(&allocator);
|
||||
} /* __PHYFS_getAllocator */
|
||||
|
||||
|
||||
/* end of physfs.c ... */
|
||||
|
||||
|
|
16
physfs.h
16
physfs.h
|
@ -1874,6 +1874,22 @@ typedef struct
|
|||
__EXPORT__ int PHYSFS_setAllocator(PHYSFS_Allocator *allocator);
|
||||
|
||||
|
||||
/*
|
||||
* it is not safe to call physfs functions in these callbacks, as they may
|
||||
* be holding non recursive mutexes.
|
||||
*/
|
||||
/* !!! FIXME: comment! */
|
||||
typedef void (*PHYSFS_StringCallback)(void *data, const char *);
|
||||
|
||||
__EXPORT__ void PHYSFS_getCdRomDirsCallback(PHYSFS_StringCallback c, void *d);
|
||||
|
||||
__EXPORT__ void PHYSFS_getSearchPathCallback(PHYSFS_StringCallback c, void *d);
|
||||
|
||||
__EXPORT__ void PHYSFS_enumerateFilesCallback(const char *dir,
|
||||
PHYSFS_StringCallback c,
|
||||
void *d);
|
||||
|
||||
|
||||
/* Everything above this line is part of the PhysicsFS 2.0 API. */
|
||||
|
||||
|
||||
|
|
|
@ -979,17 +979,18 @@ typedef struct
|
|||
void *(*openArchive)(const char *name, int forWriting);
|
||||
|
||||
/*
|
||||
* Returns a list of all files in dirname. Each element of this list
|
||||
* (and its "str" field) will be deallocated with the system's free()
|
||||
* function by the caller, so be sure to explicitly malloc() each
|
||||
* chunk. Omit symlinks if (omitSymLinks) is non-zero.
|
||||
* If you have a memory failure, return as much as you can.
|
||||
* This dirname is in platform-independent notation.
|
||||
* List all files in (dirname). Each file is passed to (callback),
|
||||
* where a copy is made if appropriate, so you should dispose of
|
||||
* it properly upon return from the callback.
|
||||
* You should omit symlinks if (omitSymLinks) is non-zero.
|
||||
* If you have a failure, report as much as you can.
|
||||
* (dirname) is in platform-independent notation.
|
||||
*/
|
||||
LinkedStringList *(*enumerateFiles)(dvoid *opaque,
|
||||
void (*enumerateFiles)(dvoid *opaque,
|
||||
const char *dirname,
|
||||
int omitSymLinks);
|
||||
|
||||
int omitSymLinks,
|
||||
PHYSFS_StringCallback callback,
|
||||
void *callbackdata);
|
||||
|
||||
/*
|
||||
* Returns non-zero if filename can be opened for reading.
|
||||
|
@ -1445,10 +1446,13 @@ int __PHYSFS_platformFlush(void *opaque);
|
|||
int __PHYSFS_platformClose(void *opaque);
|
||||
|
||||
/*
|
||||
* Platform implementation of PHYSFS_getCdRomDirs()...
|
||||
* See physfs.h. The retval should be freeable via PHYSFS_freeList().
|
||||
* Platform implementation of PHYSFS_getCdRomDirsCallback()...
|
||||
* CD directories are discovered and reported to the callback one at a time.
|
||||
* Pointers passed to the callback are assumed to be invalid to the
|
||||
* application after the callback returns, so you can free them or whatever.
|
||||
* Callback does not assume results will be sorted in any meaningful way.
|
||||
*/
|
||||
char **__PHYSFS_platformDetectAvailableCDs(void);
|
||||
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data);
|
||||
|
||||
/*
|
||||
* Calculate the base dir, if your platform needs special consideration.
|
||||
|
@ -1559,8 +1563,10 @@ void __PHYSFS_platformTimeslice(void);
|
|||
* uses platform-independent notation. Note that ".", "..", and other
|
||||
* metaentries should always be ignored.
|
||||
*/
|
||||
LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname,
|
||||
int omitSymLinks);
|
||||
void __PHYSFS_platformEnumerateFiles(const char *dirname,
|
||||
int omitSymLinks,
|
||||
PHYSFS_StringCallback callback,
|
||||
void *callbackdata);
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
@ -47,20 +47,6 @@ int __PHYSFS_platformDeinit(void)
|
|||
} /* __PHYSFS_platformDeinit */
|
||||
|
||||
|
||||
|
||||
/* caller needs to malloc() mntpnt, and expect us to free() it. */
|
||||
static void addDisc(char *mntpnt, char ***discs, int *disccount)
|
||||
{
|
||||
char **tmp = (char **) realloc(*discs, sizeof (char *) * (*disccount + 1));
|
||||
if (tmp)
|
||||
{
|
||||
tmp[*disccount - 1] = mntpnt;
|
||||
*discs = tmp;
|
||||
(*disccount)++;
|
||||
} /* if */
|
||||
} /* addDisc */
|
||||
|
||||
|
||||
static char *getMountPoint(const char *devname)
|
||||
{
|
||||
BVolumeRoster mounts;
|
||||
|
@ -101,10 +87,10 @@ static char *getMountPoint(const char *devname)
|
|||
* This function is lifted from Simple Directmedia Layer (SDL):
|
||||
* http://www.libsdl.org/
|
||||
*/
|
||||
static void tryDir(const char *dirname, char ***discs, int *disccount)
|
||||
static void tryDir(const char *d, PHYSFS_StringCallback callback, void *data)
|
||||
{
|
||||
BDirectory dir;
|
||||
dir.SetTo(dirname);
|
||||
dir.SetTo(d);
|
||||
if (dir.InitCheck() != B_NO_ERROR)
|
||||
return;
|
||||
|
||||
|
@ -127,7 +113,7 @@ static void tryDir(const char *dirname, char ***discs, int *disccount)
|
|||
if (entry.IsDirectory())
|
||||
{
|
||||
if (strcmp(e.name, "floppy") != 0)
|
||||
tryDir(name, discs, disccount);
|
||||
tryDir(name, callback, data);
|
||||
} /* if */
|
||||
|
||||
else
|
||||
|
@ -147,7 +133,10 @@ static void tryDir(const char *dirname, char ***discs, int *disccount)
|
|||
{
|
||||
char *mntpnt = getMountPoint(name);
|
||||
if (mntpnt != NULL)
|
||||
addDisc(mntpnt, discs, disccount);
|
||||
{
|
||||
callback(data, mntpnt);
|
||||
free(mntpnt); /* !!! FIXME: lose this malloc! */
|
||||
} /* if */
|
||||
} /* if */
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
@ -159,14 +148,9 @@ static void tryDir(const char *dirname, char ***discs, int *disccount)
|
|||
} /* tryDir */
|
||||
|
||||
|
||||
char **__PHYSFS_platformDetectAvailableCDs(void)
|
||||
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
|
||||
{
|
||||
char **retval = (char **) malloc(sizeof (char *));
|
||||
int cd_count = 1; /* We count the NULL entry. */
|
||||
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
tryDir("/dev/disk", &retval, &cd_count);
|
||||
retval[cd_count - 1] = NULL;
|
||||
return(retval);
|
||||
tryDir("/dev/disk", cb, data);
|
||||
} /* __PHYSFS_platformDetectAvailableCDs */
|
||||
|
||||
|
||||
|
|
|
@ -177,17 +177,12 @@ int __PHYSFS_platformDeinit(void)
|
|||
* CD detection code is borrowed from Apple Technical Q&A DV18.
|
||||
* http://developer.apple.com/qa/dv/dv18.html
|
||||
*/
|
||||
char **__PHYSFS_platformDetectAvailableCDs(void)
|
||||
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
|
||||
{
|
||||
|
||||
DriverGestaltParam pb;
|
||||
DrvQEl *dqp;
|
||||
OSErr status;
|
||||
char **retval = (char **) malloc(sizeof (char *));
|
||||
int cd_count = 1;
|
||||
|
||||
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
*retval = NULL;
|
||||
|
||||
pb.csCode = kDriverGestaltCode;
|
||||
pb.driverGestaltSelector = kdgDeviceType;
|
||||
|
@ -201,6 +196,7 @@ char **__PHYSFS_platformDetectAvailableCDs(void)
|
|||
if ((status == noErr) && (pb.driverGestaltResponse == kdgCDType))
|
||||
{
|
||||
Str63 volName;
|
||||
size_t size;
|
||||
HParamBlockRec hpbr;
|
||||
memset(&hpbr, '\0', sizeof (HParamBlockRec));
|
||||
hpbr.volumeParam.ioNamePtr = volName;
|
||||
|
@ -208,27 +204,15 @@ char **__PHYSFS_platformDetectAvailableCDs(void)
|
|||
hpbr.volumeParam.ioVolIndex = 0;
|
||||
if (PBHGetVInfoSync(&hpbr) == noErr)
|
||||
{
|
||||
char **tmp = realloc(retval, sizeof (char *) * (cd_count + 1));
|
||||
if (tmp)
|
||||
{
|
||||
char *str = (char *) malloc(volName[0] + 1);
|
||||
retval = tmp;
|
||||
if (str != NULL)
|
||||
{
|
||||
memcpy(str, &volName[1], volName[0]);
|
||||
str[volName[0]] = '\0';
|
||||
retval[cd_count-1] = str;
|
||||
cd_count++;
|
||||
} /* if */
|
||||
} /* if */
|
||||
size = (size_t) volName[0]; /* convert to ASCIZ string... */
|
||||
memmove(&volName[0], &volName[1], size);
|
||||
volName[size] = '\0';
|
||||
cb(data, volName);
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
dqp = (DrvQEl *) dqp->qLink;
|
||||
} /* while */
|
||||
|
||||
retval[cd_count - 1] = NULL;
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformDetectAvailableCDs */
|
||||
|
||||
|
||||
|
@ -577,10 +561,12 @@ void __PHYSFS_platformTimeslice(void)
|
|||
} /* __PHYSFS_platformTimeslice */
|
||||
|
||||
|
||||
LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname,
|
||||
int omitSymLinks)
|
||||
/* returns int so we can use BAIL*MACRO... */
|
||||
static int macClassicEnumerateFiles(const char *dirname,
|
||||
int omitSymLinks,
|
||||
PHYSFS_StringCallback callback,
|
||||
void *callbackdata)
|
||||
{
|
||||
LinkedStringList *ret = NULL, *p = NULL;
|
||||
UInt16 i;
|
||||
UInt16 max;
|
||||
FSSpec spec;
|
||||
|
@ -606,6 +592,7 @@ LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname,
|
|||
|
||||
for (i = 1; i <= max; i++)
|
||||
{
|
||||
size_t size;
|
||||
FSSpec aliasspec;
|
||||
Boolean alias = 0;
|
||||
Boolean folder = 0;
|
||||
|
@ -629,10 +616,20 @@ LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname,
|
|||
continue;
|
||||
|
||||
/* still here? Add it to the list. */
|
||||
ret = __PHYSFS_addToLinkedStringList(ret, &p, (const char *) &str255[1], str255[0]);
|
||||
size = (size_t) str255[0]; /* (convert to ASCIZ string...) */
|
||||
memmove(&str255[0], &str255[1], size);
|
||||
str255[size] = '\0';
|
||||
callback(callbackdata, str255);
|
||||
} /* for */
|
||||
} /* macClassicEnumerateFiles */
|
||||
|
||||
return(ret);
|
||||
|
||||
void __PHYSFS_platformEnumerateFiles(const char *dirname,
|
||||
int omitSymLinks,
|
||||
PHYSFS_StringCallback callback,
|
||||
void *callbackdata)
|
||||
{
|
||||
macClassicEnumerateFiles(dirname, omitSymLinks, callback, callbackdata);
|
||||
} /* __PHYSFS_platformEnumerateFiles */
|
||||
|
||||
|
||||
|
|
|
@ -254,20 +254,12 @@ static int is_cdrom_drive(ULONG drive)
|
|||
} /* is_cdrom_drive */
|
||||
|
||||
|
||||
char **__PHYSFS_platformDetectAvailableCDs(void)
|
||||
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
|
||||
{
|
||||
ULONG dummy;
|
||||
ULONG drivemap;
|
||||
ULONG dummy = 0;
|
||||
ULONG drivemap = 0;
|
||||
ULONG i, bit;
|
||||
APIRET rc;
|
||||
char **retval;
|
||||
PHYSFS_uint32 cd_count = 1; /* we count the NULL entry. */
|
||||
|
||||
retval = (char **) malloc(sizeof (char *));
|
||||
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
*retval = NULL;
|
||||
|
||||
rc = DosQueryCurrentDisk(&dummy, &drivemap);
|
||||
APIRET rc = DosQueryCurrentDisk(&dummy, &drivemap);
|
||||
BAIL_IF_MACRO(os2err(rc) != NO_ERROR, NULL, retval);
|
||||
|
||||
for (i = 0, bit = 1; i < 26; i++, bit <<= 1)
|
||||
|
@ -276,27 +268,12 @@ char **__PHYSFS_platformDetectAvailableCDs(void)
|
|||
{
|
||||
if ((is_cdrom_drive(i)) && (disc_is_inserted(i)))
|
||||
{
|
||||
char **tmp = realloc(retval, sizeof (char *) * (cd_count + 1));
|
||||
if (tmp)
|
||||
{
|
||||
char *str = (char *) malloc(4);
|
||||
retval = tmp;
|
||||
retval[cd_count - 1] = str;
|
||||
if (str)
|
||||
{
|
||||
str[0] = ('A' + i);
|
||||
str[1] = ':';
|
||||
str[2] = '\\';
|
||||
str[3] = '\0';
|
||||
cd_count++;
|
||||
} /* if */
|
||||
} /* if */
|
||||
char drive[4] = "x:\\";
|
||||
drive[0] = ('A' + i);
|
||||
cb(data, drive);
|
||||
} /* if */
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
||||
retval[cd_count - 1] = NULL;
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformDetectAvailableCDs */
|
||||
|
||||
|
||||
|
@ -417,11 +394,12 @@ char *__PHYSFS_platformCvtToDependent(const char *prepend,
|
|||
} /* __PHYSFS_platformCvtToDependent */
|
||||
|
||||
|
||||
LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname,
|
||||
int omitSymLinks)
|
||||
void __PHYSFS_platformEnumerateFiles(const char *dirname,
|
||||
int omitSymLinks,
|
||||
PHYSFS_StringCallback callback,
|
||||
void *callbackdata)
|
||||
{
|
||||
char spec[CCHMAXPATH];
|
||||
LinkedStringList *ret = NULL, *p = NULL;
|
||||
FILEFINDBUF3 fb;
|
||||
HDIR hdir = HDIR_CREATE;
|
||||
ULONG count = 1;
|
||||
|
@ -439,13 +417,12 @@ LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname,
|
|||
while (count == 1)
|
||||
{
|
||||
if ((strcmp(fb.achName, ".") != 0) && (strcmp(fb.achName, "..") != 0))
|
||||
ret = __PHYSFS_addToLinkedStringList(ret, &p, fb.achName, -1);
|
||||
callback(callbackdata, fb.achName);
|
||||
|
||||
DosFindNext(hdir, &fb, sizeof (fb), &count);
|
||||
} /* while */
|
||||
|
||||
DosFindClose(hdir);
|
||||
return(ret);
|
||||
} /* __PHYSFS_platformEnumerateFiles */
|
||||
|
||||
|
||||
|
|
|
@ -75,21 +75,22 @@ static char *UnicodeToAsc(const wchar_t *w_str)
|
|||
str = (char *) malloc(len);
|
||||
|
||||
if (WideCharToMultiByte(CP_ACP,0,w_str,-1,str,len,NULL,NULL) == 0)
|
||||
{ //Conversion failed
|
||||
{ /*Conversion failed */
|
||||
free(str);
|
||||
return NULL;
|
||||
}
|
||||
return(NULL);
|
||||
} /* if */
|
||||
else
|
||||
{ //Conversion successful
|
||||
{ /* Conversion successful */
|
||||
return(str);
|
||||
}
|
||||
} /* else */
|
||||
} /* if */
|
||||
|
||||
}
|
||||
else
|
||||
{ //Given NULL string
|
||||
{ /* Given NULL string */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
} /* UnicodeToAsc */
|
||||
|
||||
|
||||
static wchar_t *AscToUnicode(const char *str)
|
||||
{
|
||||
|
@ -101,18 +102,18 @@ static wchar_t *AscToUnicode(const char *str)
|
|||
if (MultiByteToWideChar(CP_ACP,0,str,-1,w_str,len) == 0)
|
||||
{
|
||||
free(w_str);
|
||||
return NULL;
|
||||
}
|
||||
return(NULL);
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
return(w_str);
|
||||
}
|
||||
}
|
||||
} /* else */
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return(NULL);
|
||||
} /* else */
|
||||
} /* AscToUnicode */
|
||||
|
||||
|
||||
static char *getExePath()
|
||||
|
@ -177,9 +178,9 @@ int __PHYSFS_platformDeinit(void)
|
|||
} /* __PHYSFS_platformDeinit */
|
||||
|
||||
|
||||
char **__PHYSFS_platformDetectAvailableCDs(void)
|
||||
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_IMPLEMENTED, NULL);
|
||||
/* no-op on this platform. */
|
||||
} /* __PHYSFS_platformDetectAvailableCDs */
|
||||
|
||||
|
||||
|
@ -293,12 +294,11 @@ void __PHYSFS_platformTimeslice(void)
|
|||
} /* __PHYSFS_platformTimeslice */
|
||||
|
||||
|
||||
LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname,
|
||||
int omitSymLinks)
|
||||
void __PHYSFS_platformEnumerateFiles(const char *dirname,
|
||||
int omitSymLinks,
|
||||
PHYSFS_StringCallback callback,
|
||||
void *callbackdata)
|
||||
{
|
||||
LinkedStringList *retval = NULL;
|
||||
LinkedStringList *l = NULL;
|
||||
LinkedStringList *prev = NULL;
|
||||
HANDLE dir;
|
||||
WIN32_FIND_DATA ent;
|
||||
char *SearchPath;
|
||||
|
@ -329,42 +329,28 @@ LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname,
|
|||
free(SearchPath);
|
||||
|
||||
if (dir == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return;
|
||||
|
||||
do
|
||||
{
|
||||
const char *str;
|
||||
|
||||
if (wcscmp(ent.cFileName, L".") == 0)
|
||||
continue;
|
||||
|
||||
if (wcscmp(ent.cFileName, L"..") == 0)
|
||||
continue;
|
||||
|
||||
l = (LinkedStringList *) malloc(sizeof (LinkedStringList));
|
||||
if (l == NULL)
|
||||
/* !!! FIXME: avoid malloc in UnicodeToAsc? */
|
||||
str = UnicodeToAsc(ent.cFileName);
|
||||
if (str == NULL)
|
||||
break;
|
||||
|
||||
l->str=UnicodeToAsc(ent.cFileName);
|
||||
|
||||
if (l->str == NULL)
|
||||
{
|
||||
free(l);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (retval == NULL)
|
||||
retval = l;
|
||||
else
|
||||
prev->next = l;
|
||||
|
||||
prev = l;
|
||||
l->next = NULL;
|
||||
callback(callbackdata, str);
|
||||
free(str);
|
||||
} while (FindNextFile(dir, &ent) != 0);
|
||||
|
||||
FindClose(dir);
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformEnumerateFiles */
|
||||
|
||||
|
||||
|
@ -381,7 +367,6 @@ char *__PHYSFS_platformRealPath(const char *path)
|
|||
strcpy(retval,path);
|
||||
|
||||
return(retval);
|
||||
|
||||
} /* __PHYSFS_platformRealPath */
|
||||
|
||||
|
||||
|
|
|
@ -225,22 +225,24 @@ char *__PHYSFS_platformCvtToDependent(const char *prepend,
|
|||
|
||||
|
||||
|
||||
LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname,
|
||||
int omitSymLinks)
|
||||
void __PHYSFS_platformEnumerateFiles(const char *dirname,
|
||||
int omitSymLinks,
|
||||
PHYSFS_StringCallback callback,
|
||||
void *callbackdata)
|
||||
{
|
||||
LinkedStringList *retval = NULL, *p = NULL;
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
int bufsize = 0;
|
||||
char *buf = NULL;
|
||||
int dlen = 0;
|
||||
|
||||
if (omitSymLinks)
|
||||
if (omitSymLinks) /* !!! FIXME: this malloc sucks. */
|
||||
{
|
||||
dlen = strlen(dirname);
|
||||
bufsize = dlen + 256;
|
||||
buf = (char *) malloc(bufsize);
|
||||
BAIL_IF_MACRO(buf == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
if (buf == NULL)
|
||||
return;
|
||||
strcpy(buf, dirname);
|
||||
if (buf[dlen - 1] != '/')
|
||||
{
|
||||
|
@ -255,7 +257,7 @@ LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname,
|
|||
{
|
||||
if (buf != NULL)
|
||||
free(buf);
|
||||
BAIL_IF_MACRO(1, strerror(errno), NULL);
|
||||
return;
|
||||
} /* if */
|
||||
|
||||
while ((ent = readdir(dir)) != NULL)
|
||||
|
@ -284,14 +286,13 @@ LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname,
|
|||
continue;
|
||||
} /* if */
|
||||
|
||||
retval = __PHYSFS_addToLinkedStringList(retval, &p, ent->d_name, -1);
|
||||
callback(callbackdata, ent->d_name);
|
||||
} /* while */
|
||||
|
||||
if (buf != NULL)
|
||||
free(buf);
|
||||
|
||||
closedir(dir);
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformEnumerateFiles */
|
||||
|
||||
|
||||
|
|
|
@ -32,9 +32,8 @@ int __PHYSFS_platformDeinit(void)
|
|||
} /* __PHYSFS_platformDeinit */
|
||||
|
||||
|
||||
char **__PHYSFS_platformDetectAvailableCDs(void)
|
||||
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_IMPLEMENTED, NULL);
|
||||
} /* __PHYSFS_platformDetectAvailableCDs */
|
||||
|
||||
|
||||
|
@ -105,10 +104,11 @@ void __PHYSFS_platformTimeslice(void)
|
|||
} /* __PHYSFS_platformTimeslice */
|
||||
|
||||
|
||||
LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname,
|
||||
int omitSymLinks)
|
||||
void __PHYSFS_platformEnumerateFiles(const char *dirname,
|
||||
int omitSymLinks,
|
||||
PHYSFS_StringCallback callback,
|
||||
void *callbackdata)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_IMPLEMENTED, NULL);
|
||||
} /* __PHYSFS_platformEnumerateFiles */
|
||||
|
||||
|
||||
|
|
|
@ -76,12 +76,8 @@ int __PHYSFS_platformDeinit(void)
|
|||
#ifdef PHYSFS_NO_CDROM_SUPPORT
|
||||
|
||||
/* Stub version for platforms without CD-ROM support. */
|
||||
char **__PHYSFS_platformDetectAvailableCDs(void)
|
||||
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
|
||||
{
|
||||
char **retval = (char **) malloc(sizeof (char *));
|
||||
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
*retval = NULL;
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformDetectAvailableCDs */
|
||||
|
||||
|
||||
|
@ -166,13 +162,11 @@ static int darwinIsMountedDisc(char *bsdName, mach_port_t masterPort)
|
|||
} /* darwinIsMountedDisc */
|
||||
|
||||
|
||||
char **__PHYSFS_platformDetectAvailableCDs(void)
|
||||
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
|
||||
{
|
||||
const char *devPrefix = "/dev/";
|
||||
int prefixLen = strlen(devPrefix);
|
||||
mach_port_t masterPort = 0;
|
||||
char **retval = (char **) malloc(sizeof (char *));
|
||||
int cd_count = 1; /* We count the NULL entry. */
|
||||
struct statfs *mntbufp;
|
||||
int i, mounts;
|
||||
|
||||
|
@ -191,38 +185,17 @@ char **__PHYSFS_platformDetectAvailableCDs(void)
|
|||
|
||||
dev += prefixLen;
|
||||
if (darwinIsMountedDisc(dev, masterPort))
|
||||
{
|
||||
char **tmp = realloc(retval, sizeof (char *) * (cd_count + 1));
|
||||
if (tmp)
|
||||
{
|
||||
retval = tmp;
|
||||
retval[cd_count - 1] = (char *) malloc(strlen(mnt) + 1);
|
||||
if (retval[cd_count - 1])
|
||||
{
|
||||
strcpy(retval[cd_count - 1], mnt);
|
||||
cd_count++;
|
||||
} /* if */
|
||||
} /* if */
|
||||
} /* if */
|
||||
cb(data, mnt);
|
||||
} /* for */
|
||||
|
||||
retval[cd_count - 1] = NULL;
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformDetectAvailableCDs */
|
||||
|
||||
#elif (defined PHYSFS_HAVE_SYS_UCRED_H)
|
||||
|
||||
char **__PHYSFS_platformDetectAvailableCDs(void)
|
||||
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
|
||||
{
|
||||
char **retval = (char **) malloc(sizeof (char *));
|
||||
int cd_count = 1; /* We count the NULL entry. */
|
||||
struct statfs *mntbufp = NULL;
|
||||
int mounts;
|
||||
int i;
|
||||
|
||||
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
mounts = getmntinfo(&mntbufp, MNT_WAIT);
|
||||
struct statfs *mntbufp = NULL;
|
||||
int mounts = getmntinfo(&mntbufp, MNT_WAIT);
|
||||
|
||||
for (i = 0; i < mounts; i++)
|
||||
{
|
||||
|
@ -236,40 +209,23 @@ char **__PHYSFS_platformDetectAvailableCDs(void)
|
|||
/* add other mount types here */
|
||||
|
||||
if (add_it)
|
||||
{
|
||||
char **tmp = realloc(retval, sizeof (char *) * (cd_count + 1));
|
||||
if (tmp)
|
||||
{
|
||||
retval = tmp;
|
||||
retval[cd_count - 1] = (char *)
|
||||
malloc(strlen(mntbufp[i].f_mntonname) + 1);
|
||||
if (retval[cd_count - 1])
|
||||
{
|
||||
strcpy(retval[cd_count - 1], mntbufp[i].f_mntonname);
|
||||
cd_count++;
|
||||
} /* if */
|
||||
} /* if */
|
||||
} /* if */
|
||||
cb(data, mntbufp[i].f_mntonname);
|
||||
} /* for */
|
||||
|
||||
retval[cd_count - 1] = NULL;
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformDetectAvailableCDs */
|
||||
|
||||
#elif (defined PHYSFS_HAVE_MNTENT_H)
|
||||
|
||||
char **__PHYSFS_platformDetectAvailableCDs(void)
|
||||
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
|
||||
{
|
||||
char **retval = (char **) malloc(sizeof (char *));
|
||||
int cd_count = 1; /* We count the NULL entry. */
|
||||
FILE *mounts = NULL;
|
||||
struct mntent *ent = NULL;
|
||||
|
||||
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
*retval = NULL;
|
||||
mounts = setmntent("/etc/mtab", "r");
|
||||
BAIL_IF_MACRO(mounts == NULL, ERR_IO_ERROR, retval);
|
||||
if (mounts == NULL)
|
||||
{
|
||||
__PHYSFS_setError(ERR_IO_ERROR);
|
||||
return;
|
||||
} /* if */
|
||||
|
||||
while ( (ent = getmntent(mounts)) != NULL )
|
||||
{
|
||||
|
@ -280,25 +236,11 @@ char **__PHYSFS_platformDetectAvailableCDs(void)
|
|||
/* add other mount types here */
|
||||
|
||||
if (add_it)
|
||||
{
|
||||
char **tmp = realloc(retval, sizeof (char *) * (cd_count + 1));
|
||||
if (tmp)
|
||||
{
|
||||
retval = tmp;
|
||||
retval[cd_count-1] = (char *) malloc(strlen(ent->mnt_dir) + 1);
|
||||
if (retval[cd_count - 1])
|
||||
{
|
||||
strcpy(retval[cd_count - 1], ent->mnt_dir);
|
||||
cd_count++;
|
||||
} /* if */
|
||||
} /* if */
|
||||
} /* if */
|
||||
cb(data, ent->mnt_dir);
|
||||
} /* while */
|
||||
|
||||
endmntent(mounts);
|
||||
|
||||
retval[cd_count - 1] = NULL;
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformDetectAvailableCDs */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -268,33 +268,17 @@ static BOOL mediaInDrive(const char *drive)
|
|||
} /* mediaInDrive */
|
||||
|
||||
|
||||
char **__PHYSFS_platformDetectAvailableCDs(void)
|
||||
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
|
||||
{
|
||||
char **retval = (char **) malloc(sizeof (char *));
|
||||
int cd_count = 1; /* We count the NULL entry. */
|
||||
char drive_str[4] = "x:\\";
|
||||
|
||||
for (drive_str[0] = 'A'; drive_str[0] <= 'Z'; drive_str[0]++)
|
||||
char ch;
|
||||
for (ch = 'A'; ch <= 'Z'; ch++)
|
||||
{
|
||||
drive_str[0] = ch;
|
||||
if (GetDriveType(drive_str) == DRIVE_CDROM && mediaInDrive(drive_str))
|
||||
{
|
||||
char **tmp = realloc(retval, sizeof (char *) * (cd_count + 1));
|
||||
if (tmp)
|
||||
{
|
||||
retval = tmp;
|
||||
retval[cd_count - 1] = (char *) malloc(4);
|
||||
if (retval[cd_count - 1])
|
||||
{
|
||||
strcpy(retval[cd_count - 1], drive_str);
|
||||
cd_count++;
|
||||
} /* if */
|
||||
} /* if */
|
||||
} /* if */
|
||||
cb(data, drive_str);
|
||||
} /* for */
|
||||
|
||||
retval[cd_count - 1] = NULL;
|
||||
return(retval);
|
||||
} /* __PHYSFS_detectAvailableCDs */
|
||||
} /* __PHYSFS_platformDetectAvailableCDs */
|
||||
|
||||
|
||||
char *__PHYSFS_platformCalcBaseDir(const char *argv0)
|
||||
|
@ -454,18 +438,20 @@ void __PHYSFS_platformTimeslice(void)
|
|||
} /* __PHYSFS_platformTimeslice */
|
||||
|
||||
|
||||
LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname,
|
||||
int omitSymLinks)
|
||||
void __PHYSFS_platformEnumerateFiles(const char *dirname,
|
||||
int omitSymLinks,
|
||||
PHYSFS_StringCallback callback,
|
||||
void *callbackdata)
|
||||
{
|
||||
LinkedStringList *retval = NULL, *p = NULL;
|
||||
HANDLE dir;
|
||||
WIN32_FIND_DATA ent;
|
||||
char *SearchPath;
|
||||
size_t len = strlen(dirname);
|
||||
char *SearchPath;
|
||||
|
||||
/* Allocate a new string for path, maybe '\\', "*", and NULL terminator */
|
||||
SearchPath = (char *) alloca(len + 3);
|
||||
BAIL_IF_MACRO(SearchPath == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
if (SearchPath == NULL)
|
||||
return;
|
||||
|
||||
/* Copy current dirname */
|
||||
strcpy(SearchPath, dirname);
|
||||
|
@ -481,11 +467,8 @@ LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname,
|
|||
strcat(SearchPath, "*");
|
||||
|
||||
dir = FindFirstFile(SearchPath, &ent);
|
||||
BAIL_IF_MACRO
|
||||
(
|
||||
dir == INVALID_HANDLE_VALUE,
|
||||
win32strerror(), NULL
|
||||
);
|
||||
if (dir == INVALID_HANDLE_VALUE)
|
||||
return;
|
||||
|
||||
do
|
||||
{
|
||||
|
@ -495,11 +478,10 @@ LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname,
|
|||
if (strcmp(ent.cFileName, "..") == 0)
|
||||
continue;
|
||||
|
||||
retval = __PHYSFS_addToLinkedStringList(retval, &p, ent.cFileName, -1);
|
||||
callback(callbackdata, ent.cFileName);
|
||||
} while (FindNextFile(dir, &ent) != 0);
|
||||
|
||||
FindClose(dir);
|
||||
return(retval);
|
||||
} /* __PHYSFS_platformEnumerateFiles */
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue