0
|
1 /*
|
|
2 * DMLib
|
|
3 * -- PACK-file handling
|
|
4 * Programmed and designed by Matti 'ccr' Hamalainen
|
|
5 * (C) Copyright 2011 Tecnic Software productions (TNSP)
|
|
6 */
|
|
7 #include "dmpack.h"
|
|
8 #include "dmfile.h"
|
|
9 #include <zlib.h>
|
|
10
|
|
11
|
|
12 DMPackEntry *dm_pack_entry_new()
|
|
13 {
|
|
14 return (DMPackEntry *) dmMalloc0(sizeof(DMPackEntry));
|
|
15 }
|
|
16
|
|
17
|
|
18 void dm_pack_entry_free(DMPackEntry * node)
|
|
19 {
|
|
20 dmFree(node);
|
|
21 }
|
|
22
|
|
23
|
|
24 void dm_pack_entry_insert(DMPackEntry ** packDir, DMPackEntry * node)
|
|
25 {
|
|
26 if (*packDir != NULL)
|
|
27 {
|
|
28 node->prev = (*packDir)->prev;
|
|
29 (*packDir)->prev->next = node;
|
|
30 (*packDir)->prev = node;
|
|
31 }
|
|
32 else
|
|
33 {
|
|
34 *packDir = node->prev = node;
|
|
35 }
|
|
36
|
|
37 node->next = NULL;
|
|
38 }
|
|
39
|
|
40
|
|
41 void dm_pack_entry_delete(DMPackEntry ** packDir, DMPackEntry * node)
|
|
42 {
|
|
43 if (node->prev)
|
|
44 node->prev->next = node->next;
|
|
45
|
|
46 if (node->next)
|
|
47 node->next->prev = node->prev;
|
|
48 else
|
|
49 (*packDir)->prev = node->prev;
|
|
50
|
|
51 node->prev = node->next = NULL;
|
|
52 }
|
|
53
|
|
54
|
|
55 DMPackEntry *dm_pack_find(DMPackEntry *list, const char *filename)
|
|
56 {
|
|
57 DMPackEntry *node;
|
|
58
|
|
59 for (node = list; node != NULL; node = node->next)
|
|
60 {
|
|
61 if (strcmp(node->filename, filename) == 0)
|
|
62 return node;
|
|
63 }
|
|
64
|
|
65 return NULL;
|
|
66 }
|
|
67
|
|
68
|
|
69 /*
|
|
70 * OPEN a packfile
|
|
71 */
|
|
72 int dm_pack_open(const char *filename, DMPackFile ** ppPack, BOOL readOnly)
|
|
73 {
|
|
74 unsigned int i;
|
|
75 DMPackFile *pack;
|
|
76 DMPackFileHeader hdr;
|
|
77
|
|
78 *ppPack = NULL;
|
|
79
|
|
80 // Allocate packfile-structure
|
|
81 pack = (DMPackFile *) dmMalloc0(sizeof(DMPackFile));
|
|
82 if (pack == NULL)
|
|
83 return DMERR_MALLOC;
|
|
84
|
|
85 // Open the file
|
|
86 pack->file = fopen(filename, (readOnly) ? "rb" : "r+b");
|
|
87 if (pack->file == NULL)
|
|
88 {
|
|
89 dmFree(pack);
|
|
90 return DMERR_FOPEN;
|
|
91 }
|
|
92
|
|
93 pack->filename = dm_strdup(filename);
|
|
94
|
|
95 // Read PACK header
|
|
96 fseek(pack->file, 0L, SEEK_SET);
|
|
97 if (!dm_fread_str(pack->file, (Uint8 *) &hdr.ident, sizeof(hdr.ident)) ||
|
|
98 !dm_fread_le16(pack->file, &hdr.version) ||
|
|
99 !dm_fread_le32(pack->file, &hdr.dirEntries) ||
|
|
100 !dm_fread_le32(pack->file, &hdr.dirOffset))
|
|
101 {
|
|
102 dm_pack_close(pack);
|
|
103 return DMERR_FREAD;
|
|
104 }
|
|
105
|
|
106 // Check information
|
|
107 if (memcmp(&hdr.ident, DPACK_IDENT, sizeof(hdr.ident)) != 0)
|
|
108 {
|
|
109 dm_pack_close(pack);
|
|
110 return DMERR_NOTPACK;
|
|
111 }
|
|
112
|
|
113 if (hdr.version != DPACK_VERSION)
|
|
114 {
|
|
115 dm_pack_close(pack);
|
|
116 return DMERR_VERSION;
|
|
117 }
|
|
118
|
|
119 // Read directory
|
|
120 if (fseek(pack->file, hdr.dirOffset, SEEK_SET) != 0)
|
|
121 {
|
|
122 dm_pack_close(pack);
|
|
123 return DMERR_INVALID;
|
|
124 }
|
|
125
|
|
126 for (i = 0; i < hdr.dirEntries; i++)
|
|
127 {
|
|
128 // Allocate and read directory entry
|
|
129 DMPackEntry *entry = dm_pack_entry_new();
|
|
130
|
|
131 if (entry == NULL)
|
|
132 {
|
|
133 dm_pack_close(pack);
|
|
134 return DMERR_MALLOC;
|
|
135 }
|
|
136
|
|
137 if (!dm_fread_str(pack->file, (Uint8 *) &entry->filename, sizeof(entry->filename)) ||
|
|
138 !dm_fread_le32(pack->file, &entry->size) ||
|
|
139 !dm_fread_le32(pack->file, &entry->offset) ||
|
|
140 !dm_fread_le32(pack->file, &entry->length) ||
|
|
141 !dm_fread_le32(pack->file, &entry->resFlags))
|
|
142 {
|
|
143 *ppPack = pack;
|
|
144 return DMERR_FREAD;
|
|
145 }
|
|
146
|
|
147 // Insert into list
|
|
148 dm_pack_entry_insert(&pack->entries, entry);
|
|
149 }
|
|
150
|
|
151 // Set the result
|
|
152 *ppPack = pack;
|
|
153 return DMERR_OK;
|
|
154 }
|
|
155
|
|
156
|
|
157 /*
|
|
158 * CLOSE the packfile
|
|
159 */
|
|
160 int dm_pack_close(DMPackFile * pack)
|
|
161 {
|
|
162 DMPackEntry *node, *next;
|
|
163
|
|
164 if (pack == NULL)
|
|
165 return DMERR_OK;
|
|
166
|
|
167 // Write the directory
|
|
168 node = pack->entries;
|
|
169 while (node != NULL)
|
|
170 {
|
|
171 next = node->next;
|
|
172 dm_pack_entry_free(node);
|
|
173 node = next;
|
|
174 }
|
|
175
|
|
176 // Close the file
|
|
177 if (pack->file != NULL)
|
|
178 {
|
|
179 fclose(pack->file);
|
|
180 pack->file = NULL;
|
|
181 }
|
|
182
|
|
183 // Free structures
|
|
184 dmFree(pack->filename);
|
|
185 pack->filename = NULL;
|
|
186
|
|
187 // Free packfile
|
|
188 pack->entries = NULL;
|
|
189 dmFree(pack);
|
|
190
|
|
191 return DMERR_OK;
|
|
192 }
|