Mercurial > hg > dmlib
comparison src/dmpack.c @ 1012:7666ba24e0c6
Cleanups and improve error handling.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Sun, 01 Mar 2015 04:42:04 +0200 |
parents | 1e5cf1144f36 |
children | 1684bf6aa1f8 |
comparison
equal
deleted
inserted
replaced
1011:aa745d31612e | 1012:7666ba24e0c6 |
---|---|
69 * OPEN a packfile | 69 * OPEN a packfile |
70 */ | 70 */ |
71 int dmPackOpen(const char *filename, DMPackFile ** ppPack, BOOL readOnly) | 71 int dmPackOpen(const char *filename, DMPackFile ** ppPack, BOOL readOnly) |
72 { | 72 { |
73 unsigned int i; | 73 unsigned int i; |
74 DMPackFile *pack; | 74 DMPackFile *pack = NULL; |
75 DMPackFileHeader hdr; | 75 DMPackFileHeader hdr; |
76 | 76 int ret = DMERR_OK; |
77 *ppPack = NULL; | |
78 | 77 |
79 // Allocate packfile-structure | 78 // Allocate packfile-structure |
80 pack = (DMPackFile *) dmMalloc0(sizeof(DMPackFile)); | 79 if ((pack = dmMalloc0(sizeof(DMPackFile))) == NULL) |
81 if (pack == NULL) | 80 { |
82 return DMERR_MALLOC; | 81 ret = DMERR_MALLOC; |
82 goto out; | |
83 } | |
83 | 84 |
84 // Open the file | 85 // Open the file |
85 pack->file = fopen(filename, readOnly ? "rb" : "r+b"); | 86 if ((pack->file = fopen(filename, readOnly ? "rb" : "r+b")) == NULL) |
86 if (pack->file == NULL) | 87 { |
87 { | 88 ret = DMERR_FOPEN; |
88 dmFree(pack); | 89 goto out; |
89 return DMERR_FOPEN; | |
90 } | 90 } |
91 | 91 |
92 pack->filename = dm_strdup(filename); | 92 pack->filename = dm_strdup(filename); |
93 | 93 |
94 // Read PACK header | 94 // Read PACK header |
103 } | 103 } |
104 | 104 |
105 // Check information | 105 // Check information |
106 if (memcmp(&hdr.ident, DPACK_IDENT, sizeof(hdr.ident)) != 0) | 106 if (memcmp(&hdr.ident, DPACK_IDENT, sizeof(hdr.ident)) != 0) |
107 { | 107 { |
108 dmPackClose(pack); | 108 ret = DMERR_NOTPACK; |
109 return DMERR_NOTPACK; | 109 goto out; |
110 } | 110 } |
111 | 111 |
112 if (hdr.version != DPACK_VERSION) | 112 if (hdr.version != DPACK_VERSION) |
113 { | 113 { |
114 dmPackClose(pack); | 114 ret = DMERR_VERSION; |
115 return DMERR_VERSION; | 115 goto out; |
116 } | 116 } |
117 | 117 |
118 // Read directory | 118 // Read directory |
119 if (fseek(pack->file, hdr.dirOffset, SEEK_SET) != 0) | 119 if (hdr.dirOffset < sizeof(hdr) || |
120 { | 120 fseek(pack->file, hdr.dirOffset, SEEK_SET) != 0) |
121 dmPackClose(pack); | 121 { |
122 return DMERR_INVALID; | 122 ret = DMERR_INVALID; |
123 goto out; | |
123 } | 124 } |
124 | 125 |
125 for (i = 0; i < hdr.dirEntries; i++) | 126 for (i = 0; i < hdr.dirEntries; i++) |
126 { | 127 { |
127 // Allocate and read directory entry | 128 // Allocate and read directory entry |
128 DMPackEntry *entry = dmPackEntryNew(); | 129 DMPackEntry *entry; |
129 | 130 |
130 if (entry == NULL) | 131 if ((entry = dmPackEntryNew()) == NULL) |
131 { | 132 { |
132 dmPackClose(pack); | 133 ret = DMERR_MALLOC; |
133 return DMERR_MALLOC; | 134 goto out; |
134 } | 135 } |
135 | 136 |
136 if (!dm_fread_str(pack->file, (Uint8 *) &entry->filename, sizeof(entry->filename)) || | 137 if (!dm_fread_str(pack->file, (Uint8 *) &entry->filename, sizeof(entry->filename)) || |
137 !dm_fread_le32(pack->file, &entry->size) || | 138 !dm_fread_le32(pack->file, &entry->size) || |
138 !dm_fread_le32(pack->file, &entry->offset) || | 139 !dm_fread_le32(pack->file, &entry->offset) || |
139 !dm_fread_le32(pack->file, &entry->length) || | 140 !dm_fread_le32(pack->file, &entry->length) || |
140 !dm_fread_le32(pack->file, &entry->flags)) | 141 !dm_fread_le32(pack->file, &entry->flags)) |
141 { | 142 { |
142 *ppPack = pack; | 143 ret = DMERR_FREAD; |
143 return DMERR_FREAD; | 144 goto out; |
144 } | 145 } |
146 | |
147 // Validate | |
148 if (entry->size == 0 || entry->length == 0 || | |
149 entry->length > hdr.dirOffset || | |
150 entry->offset > hdr.dirOffset) | |
145 | 151 |
146 // Insert into list | 152 // Insert into list |
147 dmPackEntryInsert(&pack->entries, entry); | 153 dmPackEntryInsert(&pack->entries, entry); |
148 } | 154 } |
149 | 155 |
150 // Set the result | 156 out: |
157 if (ret != DMERR_OK) | |
158 { | |
159 dmPackClose(pack); | |
160 pack = NULL; | |
161 } | |
162 | |
151 *ppPack = pack; | 163 *ppPack = pack; |
152 return DMERR_OK; | 164 |
165 return ret; | |
153 } | 166 } |
154 | 167 |
155 | 168 |
156 /* | 169 /* |
157 * CLOSE the packfile | 170 * CLOSE the packfile |
172 node = next; | 185 node = next; |
173 } | 186 } |
174 | 187 |
175 // Close the file | 188 // Close the file |
176 if (pack->file != NULL) | 189 if (pack->file != NULL) |
177 { | |
178 fclose(pack->file); | 190 fclose(pack->file); |
179 pack->file = NULL; | |
180 } | |
181 | 191 |
182 // Free structures | 192 // Free structures |
183 dmFree(pack->filename); | 193 dmFree(pack->filename); |
184 pack->filename = NULL; | |
185 | 194 |
186 // Free packfile | 195 // Free packfile |
187 pack->entries = NULL; | 196 memset(pack, 0, sizeof(DMPackFile)); |
188 dmFree(pack); | 197 dmFree(pack); |
189 | 198 |
190 return DMERR_OK; | 199 return DMERR_OK; |
191 } | 200 } |