From c2765f85719f8a523f73631f08a79d1b0e3fe1ad Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 29 Sep 2004 06:09:29 +0000 Subject: [PATCH] Added callback APIs and ripped up the internals everywhere to use them. --- CHANGELOG | 7 ++ TODO | 2 - archivers/dir.c | 23 +++-- archivers/grp.c | 32 ++++--- archivers/hog.c | 32 ++++--- archivers/mix.c | 37 ++++---- archivers/mvl.c | 32 ++++--- archivers/qpak.c | 45 ++++++---- archivers/wad.c | 36 ++++---- archivers/zip.c | 45 ++++++---- physfs.c | 203 ++++++++++++++++++++++++++++++++---------- physfs.h | 16 ++++ physfs_internal.h | 36 ++++---- platform/beos.cpp | 34 ++----- platform/macclassic.c | 53 ++++++----- platform/os2.c | 47 +++------- platform/pocketpc.c | 115 +++++++++++------------- platform/posix.c | 17 ++-- platform/skeleton.c | 10 +-- platform/unix.c | 86 +++--------------- platform/win32.c | 50 ++++------- 21 files changed, 491 insertions(+), 467 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 8c4412f6..b2effee8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -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 diff --git a/TODO b/TODO index 8cf011db..e7d301d7 100644 --- a/TODO +++ b/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. diff --git a/archivers/dir.c b/archivers/dir.c index 1a431e5a..b43a029d 100644 --- a/archivers/dir.c +++ b/archivers/dir.c @@ -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); - free(d); - return(retval); + if (d != NULL) + { + __PHYSFS_platformEnumerateFiles(d, omitSymLinks, cb, callbackdata); + free(d); + } /* if */ } /* DIR_enumerateFiles */ diff --git a/archivers/grp.c b/archivers/grp.c index fc4a1e19..6dee7054 100644 --- a/archivers/grp.c +++ b/archivers/grp.c @@ -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 @@ static void *GRP_openArchive(const char *name, int forWriting) } /* 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) { - 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); + if (*dname != '\0') + { + GRPinfo *info = (GRPinfo *) opaque; + GRPentry *entry = info->entries; + PHYSFS_uint32 max = info->entryCount; + PHYSFS_uint32 i; - return(retval); + for (i = 0; i < max; i++, entry++) + cb(callbackdata, entry->name); + } /* if */ } /* GRP_enumerateFiles */ diff --git a/archivers/hog.c b/archivers/hog.c index ee4ecfb4..e84e81cb 100644 --- a/archivers/hog.c +++ b/archivers/hog.c @@ -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 @@ static void *HOG_openArchive(const char *name, int forWriting) } /* 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); - 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); + if (*dname != '\0') + { + HOGinfo *info = (HOGinfo *) opaque; + HOGentry *entry = info->entries; + PHYSFS_uint32 max = info->entryCount; + PHYSFS_uint32 i; - return(retval); + for (i = 0; i < max; i++, entry++) + cb(callbackdata, entry->name); + } /* if */ } /* HOG_enumerateFiles */ diff --git a/archivers/mix.c b/archivers/mix.c index f00e7634..e2063c0c 100644 --- a/archivers/mix.c +++ b/archivers/mix.c @@ -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,23 +354,24 @@ static void *MIX_openArchive(const char *name, int forWriting) } /* 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) { - LinkedStringList *retval = NULL, *p = NULL; - MIXinfo *info = (MIXinfo*) opaque; - MIXentry *entry = info->entry; - int i; - char buffer[32]; - - for (i = 0; i < info->header.num_files; i++, entry++) + /* no directories in MIX files. */ + if (*dirname != '\0') { - sprintf(buffer, "%X", entry->hash); - retval = __PHYSFS_addToLinkedStringList(retval, &p, buffer, -1); - } /* for */ - - return(retval); + MIXinfo *info = (MIXinfo*) opaque; + MIXentry *entry = info->entry; + int i; + char buffer[32]; + + for (i = 0; i < info->header.num_files; i++, entry++) + { + sprintf(buffer, "%X", entry->hash); + cb(callbackdata, buffer); + } /* for */ + } /* if */ } /* MIX_enumerateFiles */ diff --git a/archivers/mvl.c b/archivers/mvl.c index 165bda6e..edc9faaa 100644 --- a/archivers/mvl.c +++ b/archivers/mvl.c @@ -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 @@ static void *MVL_openArchive(const char *name, int forWriting) } /* 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) { - 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); + if (*dname != '\0') + { + MVLinfo *info = ((MVLinfo *) opaque); + MVLentry *entry = info->entries; + PHYSFS_uint32 max = info->entryCount; + PHYSFS_uint32 i; - return(retval); + for (i = 0; i < max; i++, entry++) + cb(callbackdata, entry->name); + } /* if */ } /* MVL_enumerateFiles */ diff --git a/archivers/qpak.c b/archivers/qpak.c index 0f8f0c30..8c563dd2 100644 --- a/archivers/qpak.c +++ b/archivers/qpak.c @@ -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 */ diff --git a/archivers/wad.c b/archivers/wad.c index 1e604966..1603ed19 100644 --- a/archivers/wad.c +++ b/archivers/wad.c @@ -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 @@ static void *WAD_openArchive(const char *name, int forWriting) } /* 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 */ diff --git a/archivers/zip.c b/archivers/zip.c index b9296bff..29af1079 100644 --- a/archivers/zip.c +++ b/archivers/zip.c @@ -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 */ diff --git a/physfs.c b/physfs.c index 87be21ae..16a46283 100644 --- a/physfs.c +++ b/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) +{ + 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; - char **retval = NULL; - LinkedStringList *rc; - LinkedStringList *finalList = NULL; - int omitSymLinks = !allowSymLinks; + 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 ... */ diff --git a/physfs.h b/physfs.h index 725960ad..fa14487e 100644 --- a/physfs.h +++ b/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. */ diff --git a/physfs_internal.h b/physfs_internal.h index ccc7d295..ad00f6ad 100644 --- a/physfs_internal.h +++ b/physfs_internal.h @@ -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, - const char *dirname, - int omitSymLinks); - + void (*enumerateFiles)(dvoid *opaque, + const char *dirname, + 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); /* diff --git a/platform/beos.cpp b/platform/beos.cpp index 664ee5ba..00a053ee 100644 --- a/platform/beos.cpp +++ b/platform/beos.cpp @@ -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 */ diff --git a/platform/macclassic.c b/platform/macclassic.c index c5ad92ce..eb678792 100644 --- a/platform/macclassic.c +++ b/platform/macclassic.c @@ -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 */ diff --git a/platform/os2.c b/platform/os2.c index c3a23bae..82d16e63 100644 --- a/platform/os2.c +++ b/platform/os2.c @@ -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 */ diff --git a/platform/pocketpc.c b/platform/pocketpc.c index 47b60501..b7f815a1 100644 --- a/platform/pocketpc.c +++ b/platform/pocketpc.c @@ -67,52 +67,53 @@ static const char *win32strerror(void) static char *UnicodeToAsc(const wchar_t *w_str) { - char *str=NULL; + char *str = NULL; - if(w_str!=NULL) + if (w_str != NULL) { - int len=wcslen(w_str)+1; - str=(char *)malloc(len); + int len = wcslen(w_str) + 1; + str = (char *) malloc(len); - if(WideCharToMultiByte(CP_ACP,0,w_str,-1,str,len,NULL,NULL)==0) - { //Conversion failed - free(str); - return NULL; - } - else - { //Conversion successful - return(str); - } + if (WideCharToMultiByte(CP_ACP,0,w_str,-1,str,len,NULL,NULL) == 0) + { /*Conversion failed */ + free(str); + return(NULL); + } /* if */ + else + { /* Conversion successful */ + return(str); + } /* else */ + } /* if */ - } else - { //Given NULL string - return NULL; + { /* Given NULL string */ + return NULL; } -} +} /* UnicodeToAsc */ + static wchar_t *AscToUnicode(const char *str) { - wchar_t *w_str=NULL; - if(str!=NULL) - { - int len=strlen(str)+1; - w_str=(wchar_t *)malloc(sizeof(wchar_t)*len); - if(MultiByteToWideChar(CP_ACP,0,str,-1,w_str,len)==0) - { - free(w_str); - return NULL; - } - else + wchar_t *w_str = NULL; + if (str != NULL) { - return(w_str); - } - } + int len = strlen(str) + 1; + w_str = (wchar_t *) malloc(sizeof (wchar_t) * len); + if (MultiByteToWideChar(CP_ACP,0,str,-1,w_str,len) == 0) + { + free(w_str); + 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; @@ -328,43 +328,29 @@ LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname, free(w_SearchPath); free(SearchPath); - if(dir == INVALID_HANDLE_VALUE) - { - return NULL; - } + if (dir == INVALID_HANDLE_VALUE) + 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 */ diff --git a/platform/posix.c b/platform/posix.c index c0b66ed1..1ab6e36f 100644 --- a/platform/posix.c +++ b/platform/posix.c @@ -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 */ diff --git a/platform/skeleton.c b/platform/skeleton.c index 7594327e..9ec90927 100644 --- a/platform/skeleton.c +++ b/platform/skeleton.c @@ -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 */ diff --git a/platform/unix.c b/platform/unix.c index ac2bded8..89e74c7f 100644 --- a/platform/unix.c +++ b/platform/unix.c @@ -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 diff --git a/platform/win32.c b/platform/win32.c index e87b5c67..dab08f97 100644 --- a/platform/win32.c +++ b/platform/win32.c @@ -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 */