From 0ddd2b1f6d4b7b0243cba4c0aea5f23dee0e6deb Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sun, 15 Jul 2001 09:29:30 +0000 Subject: [PATCH] Initial work on ZIPfile support. Not complete. Not very pleased with this minizip library at this moment in time. --ryan. --- archivers/zip.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/archivers/zip.c b/archivers/zip.c index 26e1c0f1..9067fda5 100644 --- a/archivers/zip.c +++ b/archivers/zip.c @@ -8,7 +8,11 @@ #include #include +#include +#include #include "physfs.h" +#include "unzip.h" + #define __PHYSICSFS_INTERNAL__ #include "physfs_internal.h" @@ -17,6 +21,18 @@ #error PHYSFS_SUPPORTS_ZIP must be defined. #endif + +typedef struct +{ + unzFile handle; + uLong totalEntries; +} ZIPinfo; + +typedef struct +{ +} ZIPfileinfo; + + extern const DirFunctions __PHYSFS_DirFunctions_ZIP; static const FileFunctions __PHYSFS_FileFunctions_ZIP; @@ -54,16 +70,119 @@ static int ZIP_fileClose(FileHandle *handle) static int ZIP_isArchive(const char *filename, int forWriting) { + int retval = 0; + unzFile unz = unzOpen(name); + unz_global_info global; + + if (unz != NULL) + { + if (unzGetGlobalInfo(unz, &global) == UNZ_OK) + retval = 1; + unzClose(unz); + } /* if */ + + return(retval); } /* ZIP_isArchive */ static DirHandle *ZIP_openArchive(const char *name, int forWriting) { + unzFile unz = NULL; + DirHandle *retval = NULL; + unz_global_info global; + + BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, NULL); + + errno = 0; + BAIL_IF_MACRO(access(name, R_OK) != 0, strerror(errno), NULL); + + retval = malloc(sizeof (DirHandle)); + BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL); + + unz = unzOpen(name); + if ((unz == NULL) || (unzGetGlobalInfo(unz, &global) != UNZ_OK)) + { + if (unz) + unzClose(unz); + free(retval); + BAIL_IF_MACRO(1, ERR_UNSUPPORTED_ARCHIVE, NULL); + } /* if */ + + retval->opaque = malloc(sizeof (ZIPinfo)); + if (retval->opaque == NULL) + { + free(retval); + unzClose(unz); + BAIL_IF_MACRO(1, ERR_OUT_OF_MEMORY, NULL); + } /* if */ + + ((ZIPinfo *) (retval->opaque))->handle = unz; + ((ZIPinfo *) (retval->opaque))->totalEntries = global.number_entry; + + return(retval); } /* ZIP_openArchive */ static LinkedStringList *ZIP_enumerateFiles(DirHandle *h, const char *dirname) { + ZIPinfo *zi = (ZIPinfo *) (h->opaque); + unzFile fh = zi->handle; + int i; + LinkedStringList *retval = NULL; + LinkedStringList *l = NULL; + LinkedStringList *prev = NULL; + char buffer[256]; + char *d; + + /* jump to first file entry... */ + BAIL_IF_MACRO(unzGoToFirstFile(fh) != UNZ_OK, ERR_IO_ERROR, NULL); + + i = strlen(dirname); + d = malloc(i + 1); + strcpy(d, dirname); + if ((i > 0) && (d[i - 1] == '/')) /* no trailing slash. */ + d[i - 1] = '\0'; + + for (i = 0; i < zi->totalEntries; i++) + { + char *ptr; + unzGetCurrentFileInfo(fh, NULL, buf, sizeof (buf), NULL, 0, NULL, 0); + ptr = strrchr(p, '/'); /* !!! check this! */ + if (ptr == NULL) + { + if (*d != '\0') + continue; /* not for this dir; skip it. */ + ptr = buf; + else + { + *ptr = '\0'; + ptr++; + if (strcmp(buf, d) != 0) + continue; /* not for this dir; skip it. */ + } /* else */ + + l = (LinkedStringList *) malloc(sizeof (LinkedStringList)); + if (l != NULL) + break; + + l->str = (char *) malloc(strlen(ptr) + 1); + if (l->str == NULL) + { + free(l); + break; + } /* if */ + + if (retval == NULL) + retval = l; + else + prev->next = l; + + prev = l; + l->next = NULL; + } /* for */ + + free(d); + return(retval); } /* ZIP_enumerateFiles */