Mercurial > hg > dmlib
annotate src/dmpack.c @ 2479:c1cae47cd410
Rename DMPackEntry::length to csize (compressed size).
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Mon, 27 Apr 2020 21:33:29 +0300 |
parents | 69a5af2eb1ea |
children | 9807ae37ad69 |
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 } | |
1102
e06abfde6c39
Cosmetics pass: Remove excess whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
1046
diff
changeset
|
35 |
0 | 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 { |
1119
007a9446256c
Enable some error messages also in not-debug-build.
Matti Hamalainen <ccr@tnsp.org>
parents:
1108
diff
changeset
|
90 ret = dmError(dmGetErrno(), |
1046
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 | |
1108 | 99 if (fseeko(pack->file, 0L, SEEK_SET) != 0) |
1103 | 100 { |
101 ret = dmErrorDBG(dmGetErrno(), | |
102 "Failed to seek to file start '%s'.\n", | |
103 filename); | |
104 goto out; | |
105 } | |
106 | |
0 | 107 if (!dm_fread_str(pack->file, (Uint8 *) &hdr.ident, sizeof(hdr.ident)) || |
108 !dm_fread_le16(pack->file, &hdr.version) || | |
109 !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
|
110 !dm_fread_le64(pack->file, &hdr.dirOffset)) |
0 | 111 { |
1046
7e54b2d08ce7
Add special debug error message function/macro that can be
Matti Hamalainen <ccr@tnsp.org>
parents:
1037
diff
changeset
|
112 ret = dmErrorDBG(DMERR_FREAD, |
7e54b2d08ce7
Add special debug error message function/macro that can be
Matti Hamalainen <ccr@tnsp.org>
parents:
1037
diff
changeset
|
113 "Error reading PACK file header data.\n"); |
1030 | 114 goto out; |
0 | 115 } |
116 | |
117 // Check information | |
118 if (memcmp(&hdr.ident, DPACK_IDENT, sizeof(hdr.ident)) != 0) | |
119 { | |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
120 ret = DMERR_NOTPACK; |
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
121 goto out; |
0 | 122 } |
123 | |
124 if (hdr.version != DPACK_VERSION) | |
125 { | |
1273
132706e3b94b
Improve error handling and reporting slightly.
Matti Hamalainen <ccr@tnsp.org>
parents:
1167
diff
changeset
|
126 ret = DMERR_PACK_VERSION; |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
127 goto out; |
0 | 128 } |
129 | |
130 // Read directory | |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
131 if (hdr.dirOffset < sizeof(hdr) || |
1108 | 132 fseeko(pack->file, hdr.dirOffset, SEEK_SET) != 0) |
0 | 133 { |
1046
7e54b2d08ce7
Add special debug error message function/macro that can be
Matti Hamalainen <ccr@tnsp.org>
parents:
1037
diff
changeset
|
134 ret = dmErrorDBG(DMERR_INVALID, |
7e54b2d08ce7
Add special debug error message function/macro that can be
Matti Hamalainen <ccr@tnsp.org>
parents:
1037
diff
changeset
|
135 "Error seeking to PACK file '%s' directory offset.\n", |
1102
e06abfde6c39
Cosmetics pass: Remove excess whitespace.
Matti Hamalainen <ccr@tnsp.org>
parents:
1046
diff
changeset
|
136 filename); |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
137 goto out; |
0 | 138 } |
139 | |
140 for (i = 0; i < hdr.dirEntries; i++) | |
141 { | |
142 // Allocate and read directory entry | |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
143 DMPackEntry *entry; |
0 | 144 |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
145 if ((entry = dmPackEntryNew()) == NULL) |
0 | 146 { |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
147 ret = DMERR_MALLOC; |
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
148 goto out; |
0 | 149 } |
150 | |
1033
c353e6bcb733
Change handling of filename field in PACKs.
Matti Hamalainen <ccr@tnsp.org>
parents:
1030
diff
changeset
|
151 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
|
152 !dm_fread_le64(pack->file, &entry->offset) || |
2479
c1cae47cd410
Rename DMPackEntry::length to csize (compressed size).
Matti Hamalainen <ccr@tnsp.org>
parents:
2414
diff
changeset
|
153 !dm_fread_le32(pack->file, &entry->csize) || |
0 | 154 !dm_fread_le32(pack->file, &entry->size) || |
721
bb14d7907eb2
Rename many pack & resource handling functions.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
155 !dm_fread_le32(pack->file, &entry->flags)) |
0 | 156 { |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
157 ret = DMERR_FREAD; |
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
158 goto out; |
0 | 159 } |
160 | |
1033
c353e6bcb733
Change handling of filename field in PACKs.
Matti Hamalainen <ccr@tnsp.org>
parents:
1030
diff
changeset
|
161 // Ensure that the filename ends in NUL |
c353e6bcb733
Change handling of filename field in PACKs.
Matti Hamalainen <ccr@tnsp.org>
parents:
1030
diff
changeset
|
162 entry->filename[DMRES_NAME_LEN] = 0; |
c353e6bcb733
Change handling of filename field in PACKs.
Matti Hamalainen <ccr@tnsp.org>
parents:
1030
diff
changeset
|
163 |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
164 // Validate |
2479
c1cae47cd410
Rename DMPackEntry::length to csize (compressed size).
Matti Hamalainen <ccr@tnsp.org>
parents:
2414
diff
changeset
|
165 if (entry->size == 0 || entry->csize == 0 || |
c1cae47cd410
Rename DMPackEntry::length to csize (compressed size).
Matti Hamalainen <ccr@tnsp.org>
parents:
2414
diff
changeset
|
166 entry->csize > hdr.dirOffset || |
1033
c353e6bcb733
Change handling of filename field in PACKs.
Matti Hamalainen <ccr@tnsp.org>
parents:
1030
diff
changeset
|
167 entry->offset > hdr.dirOffset || |
c353e6bcb733
Change handling of filename field in PACKs.
Matti Hamalainen <ccr@tnsp.org>
parents:
1030
diff
changeset
|
168 strlen(entry->filename) == 0) |
1030 | 169 { |
2304
9aa51ac4e502
Improve error messaging for invalid PACK file entries.
Matti Hamalainen <ccr@tnsp.org>
parents:
1273
diff
changeset
|
170 ret = dmErrorDBG(DMERR_INVALID, |
9aa51ac4e502
Improve error messaging for invalid PACK file entries.
Matti Hamalainen <ccr@tnsp.org>
parents:
1273
diff
changeset
|
171 "Invalid PACK entry #%d '%s'\n", i, |
9aa51ac4e502
Improve error messaging for invalid PACK file entries.
Matti Hamalainen <ccr@tnsp.org>
parents:
1273
diff
changeset
|
172 entry->filename); |
1030 | 173 goto out; |
174 } | |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
175 |
0 | 176 // Insert into list |
721
bb14d7907eb2
Rename many pack & resource handling functions.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
177 dmPackEntryInsert(&pack->entries, entry); |
0 | 178 } |
179 | |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
180 out: |
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
181 if (ret != DMERR_OK) |
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
182 { |
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
183 dmPackClose(pack); |
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
184 pack = NULL; |
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
185 } |
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
186 |
0 | 187 *ppPack = pack; |
1012
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
188 |
7666ba24e0c6
Cleanups and improve error handling.
Matti Hamalainen <ccr@tnsp.org>
parents:
812
diff
changeset
|
189 return ret; |
0 | 190 } |
191 | |
192 | |
193 /* | |
194 * CLOSE the packfile | |
195 */ | |
721
bb14d7907eb2
Rename many pack & resource handling functions.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
196 int dmPackClose(DMPackFile * pack) |
0 | 197 { |
721
bb14d7907eb2
Rename many pack & resource handling functions.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
198 DMPackEntry *node; |
0 | 199 |
200 if (pack == NULL) | |
201 return DMERR_OK; | |
202 | |
203 // Write the directory | |
204 node = pack->entries; | |
205 while (node != NULL) | |
206 { | |
721
bb14d7907eb2
Rename many pack & resource handling functions.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
207 DMPackEntry *next = node->next; |
bb14d7907eb2
Rename many pack & resource handling functions.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
208 dmPackEntryFree(node); |
0 | 209 node = next; |
210 } | |
211 | |
212 // Close the file | |
213 if (pack->file != NULL) | |
214 fclose(pack->file); | |
215 | |
216 // Free structures | |
217 dmFree(pack->filename); | |
218 | |
219 // Free packfile | |
2414
69a5af2eb1ea
Remove useless dmMemset().
Matti Hamalainen <ccr@tnsp.org>
parents:
2304
diff
changeset
|
220 memset(pack, 0, sizeof(DMPackFile)); |
0 | 221 dmFree(pack); |
222 | |
223 return DMERR_OK; | |
224 } |