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)