diff dmpack.c @ 0:32250b436bca

Initial re-import.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 28 Sep 2012 01:54:23 +0300
parents
children 324374ced543 bb14d7907eb2
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmpack.c	Fri Sep 28 01:54:23 2012 +0300
@@ -0,0 +1,192 @@
+/*
+ * DMLib
+ * -- PACK-file handling
+ * Programmed and designed by Matti 'ccr' Hamalainen
+ * (C) Copyright 2011 Tecnic Software productions (TNSP)
+ */
+#include "dmpack.h"
+#include "dmfile.h"
+#include <zlib.h>
+
+
+DMPackEntry *dm_pack_entry_new()
+{
+    return (DMPackEntry *) dmMalloc0(sizeof(DMPackEntry));
+}
+
+
+void dm_pack_entry_free(DMPackEntry * node)
+{
+    dmFree(node);
+}
+
+
+void dm_pack_entry_insert(DMPackEntry ** packDir, DMPackEntry * node)
+{
+    if (*packDir != NULL)
+    {
+        node->prev = (*packDir)->prev;
+        (*packDir)->prev->next = node;
+        (*packDir)->prev = node;
+    }
+    else
+    {
+        *packDir = node->prev = node;
+    }
+    
+    node->next = NULL;
+}
+
+
+void dm_pack_entry_delete(DMPackEntry ** packDir, DMPackEntry * node)
+{
+    if (node->prev)
+        node->prev->next = node->next;
+
+    if (node->next)
+        node->next->prev = node->prev;
+    else
+        (*packDir)->prev = node->prev;
+
+    node->prev = node->next = NULL;
+}
+
+
+DMPackEntry *dm_pack_find(DMPackEntry *list, const char *filename)
+{
+    DMPackEntry *node;
+
+    for (node = list; node != NULL; node = node->next)
+    {
+        if (strcmp(node->filename, filename) == 0)
+            return node;
+    }
+
+    return NULL;
+}
+
+
+/*
+ * OPEN a packfile
+ */
+int dm_pack_open(const char *filename, DMPackFile ** ppPack, BOOL readOnly)
+{
+    unsigned int i;
+    DMPackFile *pack;
+    DMPackFileHeader hdr;
+
+    *ppPack = NULL;
+
+    // Allocate packfile-structure
+    pack = (DMPackFile *) dmMalloc0(sizeof(DMPackFile));
+    if (pack == NULL)
+        return DMERR_MALLOC;
+
+    // Open the file
+    pack->file = fopen(filename, (readOnly) ? "rb" : "r+b");
+    if (pack->file == NULL)
+    {
+        dmFree(pack);
+        return DMERR_FOPEN;
+    }
+
+    pack->filename = dm_strdup(filename);
+
+    // Read PACK header
+    fseek(pack->file, 0L, SEEK_SET);
+    if (!dm_fread_str(pack->file, (Uint8 *) &hdr.ident, sizeof(hdr.ident)) ||
+        !dm_fread_le16(pack->file, &hdr.version) ||
+        !dm_fread_le32(pack->file, &hdr.dirEntries) ||
+        !dm_fread_le32(pack->file, &hdr.dirOffset))
+    {
+        dm_pack_close(pack);
+        return DMERR_FREAD;
+    }
+
+    // Check information
+    if (memcmp(&hdr.ident, DPACK_IDENT, sizeof(hdr.ident)) != 0)
+    {
+        dm_pack_close(pack);
+        return DMERR_NOTPACK;
+    }
+
+    if (hdr.version != DPACK_VERSION)
+    {
+        dm_pack_close(pack);
+        return DMERR_VERSION;
+    }
+
+    // Read directory
+    if (fseek(pack->file, hdr.dirOffset, SEEK_SET) != 0)
+    {
+        dm_pack_close(pack);
+        return DMERR_INVALID;
+    }
+
+    for (i = 0; i < hdr.dirEntries; i++)
+    {
+        // Allocate and read directory entry
+        DMPackEntry *entry = dm_pack_entry_new();
+
+        if (entry == NULL)
+        {
+            dm_pack_close(pack);
+            return DMERR_MALLOC;
+        }
+
+        if (!dm_fread_str(pack->file, (Uint8 *) &entry->filename, sizeof(entry->filename)) ||
+            !dm_fread_le32(pack->file, &entry->size) ||
+            !dm_fread_le32(pack->file, &entry->offset) ||
+            !dm_fread_le32(pack->file, &entry->length) ||
+            !dm_fread_le32(pack->file, &entry->resFlags))
+        {
+            *ppPack = pack;
+            return DMERR_FREAD;
+        }
+
+        // Insert into list
+        dm_pack_entry_insert(&pack->entries, entry);
+    }
+
+    // Set the result
+    *ppPack = pack;
+    return DMERR_OK;
+}
+
+
+/*
+ * CLOSE the packfile
+ */
+int dm_pack_close(DMPackFile * pack)
+{
+    DMPackEntry *node, *next;
+
+    if (pack == NULL)
+        return DMERR_OK;
+
+    // Write the directory
+    node = pack->entries;
+    while (node != NULL)
+    {
+        next = node->next;
+        dm_pack_entry_free(node);
+        node = next;
+    }
+
+    // Close the file
+    if (pack->file != NULL)
+    {
+        fclose(pack->file);
+        pack->file = NULL;
+    }
+
+    // Free structures
+    dmFree(pack->filename);
+    pack->filename = NULL;
+
+    // Free packfile
+    pack->entries = NULL;
+    dmFree(pack);
+
+    return DMERR_OK;
+}