Mercurial > hg > dmlib
annotate src/dmpack.c @ 1046:7e54b2d08ce7
Add special debug error message function/macro that can be
disabled and compiled out.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Sun, 01 Mar 2015 18:03:08 +0200 |
parents | d674ddc0fc82 |
children | e06abfde6c39 |
rev | line source |
---|---|
0 | 1 /* |
2 * DMLib | |
3 * -- PACK-file handling | |
4 * Programmed and designed by Matti 'ccr' Hamalainen | |
1013 | 5 * (C) Copyright 2011-2015 Tecnic Software productions (TNSP) |
0 | 6 */ |
7 #include "dmpack.h" | |
8 #include "dmfile.h" | |
9 | |
10 | |
721
bb14d7907eb2
Rename many pack & resource handling functions.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
11 DMPackEntry *dmPackEntryNew() |
0 | 12 { |
13 return (DMPackEntry *) dmMalloc0(sizeof(DMPackEntry)); | |
14 } | |
15 | |
16 | |
721
bb14d7907eb2
Rename many pack & resource handling functions.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
17 void dmPackEntryFree(DMPackEntry * node) |
0 | 18 { |
19 dmFree(node); | |
20 } | |
21 | |
22 | |
721
bb14d7907eb2
Rename many pack & resource handling functions.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
23 void dmPackEntryInsert(DMPackEntry ** packDir, DMPackEntry * node) |
0 | 24 { |
25 if (*packDir != NULL) | |
26 { | |
27 node->prev = (*packDir)->prev; | |
28 (*packDir)->prev->next = node; | |
29 (*packDir)->prev = node; | |
30 } | |
31 else | |
32 { | |
33 *packDir = node->prev = node; | |
34 } | |
35 | |
36 node->next = NULL; | |
37 } | |
38 | |
39 | |
721
bb14d7907eb2
Rename many pack & resource handling functions.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
40 void dmPackEntryDelete(DMPackEntry ** packDir, DMPackEntry * node) |
0 | 41 { |
42 if (node->prev) | |
43 node->prev->next = node->next; | |
44 | |
45 if (node->next) | |
46 node->next->prev = node->prev; | |
47 else | |
48 (*packDir)->prev = node->prev; | |
49 | |
50 node->prev = node->next = NULL; | |
51 } | |
52 | |
53 | |
721
bb14d7907eb2
Rename many pack & resource handling functions.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
54 DMPackEntry *dmPackFind(DMPackEntry *list, const char *filename) |
0 | 55 { |
56 DMPackEntry *node; | |
57 | |
58 for (node = list; node != NULL; node = node->next) | |
59 { | |
60 if (strcmp(node->filename, filename) == 0) | |
61 return node; | |
62 } | |
63 | |
64 return NULL; | |
65 } | |
66 | |
67 | |
68 /* | |
69 * OPEN a packfile | |
70 */ | |
721
bb14d7907eb2
Rename many pack & resource handling functions.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
71 int dmPackOpen(const char *filename, DMPackFile ** ppPack, BOOL readOnly) |
0 | 72 { |
73 unsigned int i; | |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
74 DMPackFile *pack = NULL; |
0 | 75 DMPackFileHeader hdr; |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
76 int ret = DMERR_OK; |
0 | 77 |
78 // Allocate packfile-structure | |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
79 if ((pack = dmMalloc0(sizeof(DMPackFile))) == NULL) |
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
80 { |
1046
7e54b2d08ce7
Add special debug error message function/macro that can be
Matti Hamalainen <ccr@tnsp.org>
parents:
1037
diff
changeset
|
81 ret = dmErrorDBG(DMERR_MALLOC, |
7e54b2d08ce7
Add special debug error message function/macro that can be
Matti Hamalainen <ccr@tnsp.org>
parents:
1037
diff
changeset
|
82 "Failed to allocate memory for PACK file structure '%s'.\n", |
7e54b2d08ce7
Add special debug error message function/macro that can be
Matti Hamalainen <ccr@tnsp.org>
parents:
1037
diff
changeset
|
83 filename); |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
84 goto out; |
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
85 } |
0 | 86 |
87 // Open the file | |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
88 if ((pack->file = fopen(filename, readOnly ? "rb" : "r+b")) == NULL) |
0 | 89 { |
1046
7e54b2d08ce7
Add special debug error message function/macro that can be
Matti Hamalainen <ccr@tnsp.org>
parents:
1037
diff
changeset
|
90 ret = dmErrorDBG(dmGetErrno(), |
7e54b2d08ce7
Add special debug error message function/macro that can be
Matti Hamalainen <ccr@tnsp.org>
parents:
1037
diff
changeset
|
91 "Failed to open PACK file '%s'.\n", |
7e54b2d08ce7
Add special debug error message function/macro that can be
Matti Hamalainen <ccr@tnsp.org>
parents:
1037
diff
changeset
|
92 filename); |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
93 goto out; |
0 | 94 } |
95 | |
96 pack->filename = dm_strdup(filename); | |
97 | |
98 // Read PACK header | |
1046
7e54b2d08ce7
Add special debug error message function/macro that can be
Matti Hamalainen <ccr@tnsp.org>
parents:
1037
diff
changeset
|
99 DM_FSEEK64(pack->file, 0L, SEEK_SET); |
0 | 100 if (!dm_fread_str(pack->file, (Uint8 *) &hdr.ident, sizeof(hdr.ident)) || |
101 !dm_fread_le16(pack->file, &hdr.version) || | |
102 !dm_fread_le32(pack->file, &hdr.dirEntries) || | |
1037
d674ddc0fc82
Change PACK file format to use 64 bit fileoffsets. Also switch some
Matti Hamalainen <ccr@tnsp.org>
parents:
1033
diff
changeset
|
103 !dm_fread_le64(pack->file, &hdr.dirOffset)) |
0 | 104 { |
1046
7e54b2d08ce7
Add special debug error message function/macro that can be
Matti Hamalainen <ccr@tnsp.org>
parents:
1037
diff
changeset
|
105 ret = dmErrorDBG(DMERR_FREAD, |
7e54b2d08ce7
Add special debug error message function/macro that can be
Matti Hamalainen <ccr@tnsp.org>
parents:
1037
diff
changeset
|
106 "Error reading PACK file header data.\n"); |
1030 | 107 goto out; |
0 | 108 } |
109 | |
110 // Check information | |
111 if (memcmp(&hdr.ident, DPACK_IDENT, sizeof(hdr.ident)) != 0) | |
112 { | |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
113 ret = DMERR_NOTPACK; |
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
114 goto out; |
0 | 115 } |
116 | |
117 if (hdr.version != DPACK_VERSION) | |
118 { | |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
119 ret = DMERR_VERSION; |
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
120 goto out; |
0 | 121 } |
122 | |
123 // Read directory | |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
124 if (hdr.dirOffset < sizeof(hdr) || |
1046
7e54b2d08ce7
Add special debug error message function/macro that can be
Matti Hamalainen <ccr@tnsp.org>
parents:
1037
diff
changeset
|
125 DM_FSEEK64(pack->file, hdr.dirOffset, SEEK_SET) != 0) |
0 | 126 { |
1046
7e54b2d08ce7
Add special debug error message function/macro that can be
Matti Hamalainen <ccr@tnsp.org>
parents:
1037
diff
changeset
|
127 ret = dmErrorDBG(DMERR_INVALID, |
7e54b2d08ce7
Add special debug error message function/macro that can be
Matti Hamalainen <ccr@tnsp.org>
parents:
1037
diff
changeset
|
128 "Error seeking to PACK file '%s' directory offset.\n", |
7e54b2d08ce7
Add special debug error message function/macro that can be
Matti Hamalainen <ccr@tnsp.org>
parents:
1037
diff
changeset
|
129 filename); |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
130 goto out; |
0 | 131 } |
132 | |
133 for (i = 0; i < hdr.dirEntries; i++) | |
134 { | |
135 // Allocate and read directory entry | |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
136 DMPackEntry *entry; |
0 | 137 |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
138 if ((entry = dmPackEntryNew()) == NULL) |
0 | 139 { |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
140 ret = DMERR_MALLOC; |
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
141 goto out; |
0 | 142 } |
143 | |
1033
c353e6bcb733
Change handling of filename field in PACKs.
Matti Hamalainen <ccr@tnsp.org>
parents:
1030
diff
changeset
|
144 if (!dm_fread_str(pack->file, (Uint8 *) &entry->filename, DMRES_NAME_LEN) || |
1037
d674ddc0fc82
Change PACK file format to use 64 bit fileoffsets. Also switch some
Matti Hamalainen <ccr@tnsp.org>
parents:
1033
diff
changeset
|
145 !dm_fread_le64(pack->file, &entry->offset) || |
d674ddc0fc82
Change PACK file format to use 64 bit fileoffsets. Also switch some
Matti Hamalainen <ccr@tnsp.org>
parents:
1033
diff
changeset
|
146 !dm_fread_le32(pack->file, &entry->length) || |
0 | 147 !dm_fread_le32(pack->file, &entry->size) || |
721
bb14d7907eb2
Rename many pack & resource handling functions.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
148 !dm_fread_le32(pack->file, &entry->flags)) |
0 | 149 { |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
150 ret = DMERR_FREAD; |
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
151 goto out; |
0 | 152 } |
153 | |
1033
c353e6bcb733
Change handling of filename field in PACKs.
Matti Hamalainen <ccr@tnsp.org>
parents:
1030
diff
changeset
|
154 // Ensure that the filename ends in NUL |
c353e6bcb733
Change handling of filename field in PACKs.
Matti Hamalainen <ccr@tnsp.org>
parents:
1030
diff
changeset
|
155 entry->filename[DMRES_NAME_LEN] = 0; |
c353e6bcb733
Change handling of filename field in PACKs.
Matti Hamalainen <ccr@tnsp.org>
parents:
1030
diff
changeset
|
156 |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
157 // Validate |
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
158 if (entry->size == 0 || entry->length == 0 || |
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
159 entry->length > hdr.dirOffset || |
1033
c353e6bcb733
Change handling of filename field in PACKs.
Matti Hamalainen <ccr@tnsp.org>
parents:
1030
diff
changeset
|
160 entry->offset > hdr.dirOffset || |
c353e6bcb733
Change handling of filename field in PACKs.
Matti Hamalainen <ccr@tnsp.org>
parents:
1030
diff
changeset
|
161 strlen(entry->filename) == 0) |
1030 | 162 { |
163 ret = DMERR_INVALID; | |
164 goto out; | |
165 } | |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
166 |
0 | 167 // Insert into list |
721
bb14d7907eb2
Rename many pack & resource handling functions.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
168 dmPackEntryInsert(&pack->entries, entry); |
0 | 169 } |
170 | |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
171 out: |
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
172 if (ret != DMERR_OK) |
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
173 { |
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
174 dmPackClose(pack); |
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
175 pack = NULL; |
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
176 } |
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
177 |
0 | 178 *ppPack = pack; |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
179 |
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
180 return ret; |
0 | 181 } |
182 | |
183 | |
184 /* | |
185 * CLOSE the packfile | |
186 */ | |
721
bb14d7907eb2
Rename many pack & resource handling functions.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
187 int dmPackClose(DMPackFile * pack) |
0 | 188 { |
721
bb14d7907eb2
Rename many pack & resource handling functions.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
189 DMPackEntry *node; |
0 | 190 |
191 if (pack == NULL) | |
192 return DMERR_OK; | |
193 | |
194 // Write the directory | |
195 node = pack->entries; | |
196 while (node != NULL) | |
197 { | |
721
bb14d7907eb2
Rename many pack & resource handling functions.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
198 DMPackEntry *next = node->next; |
bb14d7907eb2
Rename many pack & resource handling functions.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
199 dmPackEntryFree(node); |
0 | 200 node = next; |
201 } | |
202 | |
203 // Close the file | |
204 if (pack->file != NULL) | |
205 fclose(pack->file); | |
206 | |
207 // Free structures | |
208 dmFree(pack->filename); | |
209 | |
210 // Free packfile | |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
211 memset(pack, 0, sizeof(DMPackFile)); |
0 | 212 dmFree(pack); |
213 | |
214 return DMERR_OK; | |
215 } |