Mercurial > hg > dmlib
diff tools/packed.c @ 952:ffdae9cd81de
Remove the dmpackutil module, move the code to packed utility
as it is the only place it is used anyway.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 26 Feb 2015 18:51:18 +0200 |
parents | fc272f5f2d15 |
children | 985225a93aeb |
line wrap: on
line diff
--- a/tools/packed.c Thu Feb 26 18:38:14 2015 +0200 +++ b/tools/packed.c Thu Feb 26 18:51:18 2015 +0200 @@ -6,14 +6,16 @@ #include "dmlib.h" #include "dmargs.h" #include "dmpack.h" -#include "dmpackutil.h" +#include "dmfile.h" #include "dmres.h" #include "dmmutex.h" -#include <errno.h> +#include <zlib.h> + #define SET_MAX_FILES (4096) #define SET_DEFAULT_PACK "data.pak" + enum { CMD_NONE = 0, @@ -155,6 +157,301 @@ } +DMPackEntry *dmPackEntryCopy(const DMPackEntry *src) +{ + DMPackEntry *node = dmPackEntryNew(); + if (node == NULL) + return NULL; + + strncpy(node->filename, src->filename, sizeof(node->filename)); + node->filename[sizeof(node->filename) - 1] = 0; + + node->size = src->size; + node->offset = src->offset; + node->length = src->length; + node->flags = src->flags; + + return node; +} + + +int dmPackWrite(DMPackFile * pack) +{ + DMPackEntry *node; + DMPackFileHeader hdr; + + if (pack == NULL) + return DMERR_OK; + + if (pack->file == NULL) + return DMERR_FOPEN; + + // Compute directory offset and number of entries + memcpy(&hdr.ident, DPACK_IDENT, sizeof(hdr.ident)); + hdr.version = DPACK_VERSION; + hdr.dirEntries = 0; + hdr.dirOffset = + sizeof(hdr.ident) + sizeof(hdr.version) + + sizeof(hdr.dirEntries) + sizeof(hdr.dirOffset); + + node = pack->entries; + while (node != NULL) + { + hdr.dirEntries++; + hdr.dirOffset += node->length; + node = node->next; + } + + // Write PACK header + if (fseek(pack->file, 0L, SEEK_SET) != 0) + return DMERR_FSEEK; + + if (!dm_fwrite_str(pack->file, (Uint8 *) & hdr.ident, sizeof(hdr.ident)) || + !dm_fwrite_le16(pack->file, hdr.version) || + !dm_fwrite_le32(pack->file, hdr.dirEntries) || + !dm_fwrite_le32(pack->file, hdr.dirOffset)) + return DMERR_FWRITE; + + // Write the directory + if (fseek(pack->file, hdr.dirOffset, SEEK_SET) != 0) + return DMERR_FSEEK; + + node = pack->entries; + while (node != NULL) + { + // Write one entry + if (!dm_fwrite_str(pack->file, node->filename, sizeof(node->filename)) || + !dm_fwrite_le32(pack->file, node->size) || + !dm_fwrite_le32(pack->file, node->offset) || + !dm_fwrite_le32(pack->file, node->length) || + !dm_fwrite_le32(pack->file, node->flags)) + return DMERR_FWRITE; + + node = node->next; + } + + return DMERR_OK; +} + + +int dmPackCreate(const char *filename, DMPackFile ** pack) +{ + // Allocate packfile-structure + *pack = (DMPackFile *) dmCalloc(1, sizeof(DMPackFile)); + if (*pack == NULL) + return DMERR_MALLOC; + + // Open the file + (*pack)->file = fopen(filename, "wb"); + if ((*pack)->file == NULL) + { + dmFree(*pack); + return DMERR_FOPEN; + } + + (*pack)->filename = dm_strdup(filename); + + // Set the result + return DMERR_OK; +} + + +int dmPackAddFile(DMPackFile * pack, const char *filename, + BOOL doCompress, const Uint32 flags, DMPackEntry ** ppEntry) +{ + z_stream zstr; + off_t startOffs; + unsigned int zstrSize; + FILE *inFile; + Uint8 *inBuffer, *outBuffer; + DMPackEntry entry, *node; + int result; + + *ppEntry = NULL; + + if (pack == NULL) + return DMERR_OK; + + if (pack->file == NULL) + return DMERR_FOPEN; + + // Compute starting offset + startOffs = sizeof(DMPackFileHeader); + node = pack->entries; + while (node != NULL) + { + startOffs += node->length; + node = node->next; + } + + // Seek to the position + if (fseek(pack->file, startOffs, SEEK_SET) != 0) + return DMERR_INVALID; + + // Read file data + if ((inFile = fopen(filename, "rb")) == NULL) + return -1; + + // Allocate temporary buffer + inBuffer = (Uint8 *) dmMalloc(DPACK_TMPSIZE); + if (!inBuffer) + { + fclose(inFile); + return DMERR_MALLOC; + } + + outBuffer = (Uint8 *) dmMalloc(DPACK_TMPSIZE); + if (!outBuffer) + { + dmFree(inBuffer); + fclose(inFile); + return DMERR_MALLOC; + } + + // Read (and possibly compress) the data + zstrSize = 0; + zstr.zalloc = (alloc_func) Z_NULL; + zstr.zfree = (free_func) Z_NULL; + zstr.opaque = (voidpf) Z_NULL; + result = deflateInit(&zstr, (doCompress) ? Z_DEFAULT_COMPRESSION : 0); + if (result != Z_OK) + { + dmFree(inBuffer); + dmFree(outBuffer); + fclose(inFile); + return DMERR_COMPRESSION; + } + + // Initialize compression streams + result = Z_OK; + while (!feof(inFile) && result == Z_OK) + { + zstr.avail_in = fread(inBuffer, sizeof(Uint8), DPACK_TMPSIZE, inFile); + zstr.next_in = inBuffer; + zstr.next_out = outBuffer; + zstr.avail_out = DPACK_TMPSIZE; + zstr.total_out = 0; + result = deflate(&zstr, Z_FULL_FLUSH); + + if (result == Z_OK && zstr.total_out > 0) + { + zstrSize += zstr.total_out; + fwrite(outBuffer, sizeof(Uint8), zstr.total_out, pack->file); + } + } + + // Create directory entry + strncpy(entry.filename, filename, sizeof(entry.filename)); + entry.filename[sizeof(entry.filename) - 1] = 0; + entry.size = zstr.total_in; + entry.offset = startOffs; + entry.length = zstrSize; + entry.flags = flags; + + // Cleanup + deflateEnd(&zstr); + dmFree(inBuffer); + dmFree(outBuffer); + fclose(inFile); + + // Add directory entry + if ((*ppEntry = dmPackEntryCopy(&entry)) == NULL) + return DMERR_MALLOC; + + dmPackEntryInsert(&pack->entries, *ppEntry); + + return DMERR_OK; +} + + +/* + * EXTRACT a file from the PACK + */ +int dmPackExtractFile(DMPackFile *pack, DMPackEntry * entry) +{ + z_stream zstr; + FILE *outFile; + Uint8 *inBuffer, *outBuffer; + size_t inDataLeft; + int ret; + + if (pack == NULL) + return DMERR_OK; + + if (pack->file == NULL) + return DMERR_FOPEN; + + // Seek to the position + if (fseek(pack->file, entry->offset, SEEK_SET) != 0) + return DMERR_INVALID; + + // Open destination file + if ((outFile = fopen(entry->filename, "wb")) == NULL) + return -1; + + // Allocate temporary buffer + if ((inBuffer = (Uint8 *) dmMalloc(DPACK_TMPSIZE)) == NULL) + { + fclose(outFile); + return DMERR_MALLOC; + } + + if ((outBuffer = (Uint8 *) dmMalloc(DPACK_TMPSIZE)) == NULL) + { + dmFree(inBuffer); + fclose(outFile); + return DMERR_MALLOC; + } + + // Read and uncompress the data + zstr.zalloc = (alloc_func) Z_NULL; + zstr.zfree = (free_func) Z_NULL; + zstr.opaque = (voidpf) Z_NULL; + ret = inflateInit(&zstr); + if (ret != Z_OK) + { + dmFree(inBuffer); + dmFree(outBuffer); + fclose(outFile); + return DMERR_COMPRESSION; + } + + // Initialize compression streams + inDataLeft = entry->length; + ret = Z_OK; + while (inDataLeft > 0 && ret == Z_OK) + { + if (inDataLeft >= DPACK_TMPSIZE) + zstr.avail_in = fread(inBuffer, sizeof(Uint8), DPACK_TMPSIZE, pack->file); + else + zstr.avail_in = fread(inBuffer, sizeof(Uint8), inDataLeft, pack->file); + + inDataLeft -= zstr.avail_in; + zstr.next_in = inBuffer; + + while (zstr.avail_in > 0 && ret == Z_OK) + { + zstr.next_out = outBuffer; + zstr.avail_out = DPACK_TMPSIZE; + zstr.total_out = 0; + ret = inflate(&zstr, Z_FULL_FLUSH); + if (zstr.total_out > 0) + { + fwrite(outBuffer, sizeof(Uint8), zstr.total_out, outFile); + } + } + } + + // Cleanup + inflateEnd(&zstr); + dmFree(inBuffer); + dmFree(outBuffer); + fclose(outFile); + + return DMERR_OK; +} + + /* Compare a string to a pattern. Case-SENSITIVE version. * The matching pattern can consist of any normal characters plus * wildcards ? and *. "?" matches any character and "*" matches @@ -415,8 +712,9 @@ FILE *resFile = fopen(DMRES_RES_FILE, "w"); if (resFile == NULL) { + int err = dmGetErrno(); dmError("Could not create resource output file '%s' #%d: %s\n", - DMRES_RES_FILE, errno, strerror(errno)); + DMRES_RES_FILE, err, dmErrorStr(err)); } for (node = pack->entries; node != NULL; node = node->next)