Mercurial > hg > dmlib
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; +}