1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #include "ztypes.h"
6 #include "pickle.h"
7
8 /* This file is the source code for the PICKLE Reader Library.
9 Version 1. */
10
11 /* This library is a very simple one, intended for use in interpreters
12 that want to support reading PICKLE files. This library does not
13 have functions to write or analyze PICKLE files, just to read them
14 in the rather limited way that interpreters should want to. */
15
16 #ifdef BIG_END_MODE
17 static char contentmessage[] = "\nPICKLE Reader Library 1.0.0 (big-endian)\n";
18 #endif
19
20 #ifdef LITTLE_END_MODE
21 static char contentmessage[] = "\nPICKLE Reader Library 1.0.0 (little-endian)\n";
22 #endif
23
24 #ifdef __STDC__
25 static char contentmessage2[] = "\nLibrary compiled with __STDC__\n";
26 #else
27 static char contentmessage2[] = "\nLibrary compiled without __STDC__\n";
28 #endif
29
30 #define pik_InitedMagic (0x18328EEB)
31
32 #if defined(BIG_END_MODE) || defined(LITTLE_END_MODE)
33
34 #ifdef BIG_END_MODE
35 #define pikNative(v) (v)
36 #endif
37
38 #ifdef LITTLE_END_MODE
39 #define pikNative(v) ( \
40 ((((long)(v)) >> 24) & 0x000000ff) \
41 | ((((long)(v)) >> 8) & 0x0000ff00) \
42 | ((((long)(v)) << 8) & 0x00ff0000) \
43 | ((((long)(v)) << 24) & 0xff000000) \
44 )
45 #endif
46
47 #else
48
49 #define pikNative(v) (0)
50
51 #endif
52
53 struct pikDescriptorData {
54 pikType use;
55 pikLong number;
56 pikType format;
57 pikLong formatversion;
58 pikLong startpos;
59 pikLong length;
60
61 void *data; /* (non-Mac systems) */
62 /*Handle data;*/ /* (Mac only) */
63 };
64 typedef struct pikDescriptorData pikDescriptor;
65
66 struct pikMapData {
67 pikLong inited; /* contains pik_InitedMagic while the map is in existence */
68 FILE *file; /* (non-Mac systems) */
69 /*short file;*/ /* (Mac only) */
70
71 pikLong numchunks;
72 pikLong filelength;
73
74 pikDescriptor *chunks; /* pointer to an array of descriptors */
75 };
76 typedef struct pikMapData pikMap;
77
78 #ifdef __STDC__
pikIsPickleHeader(char * header)79 short pikIsPickleHeader(char *header)
80 #else
81 short pikIsPickleHeader(header)
82 char *header;
83 #endif
84 {
85 if (header[0] == 0x70
86 && header[1] == 0x69
87 && header[2] == 0x6b
88 && header[3] == 0x6c) {
89 return TRUE;
90 }
91 else {
92 return FALSE;
93 }
94 }
95
96 #ifdef __STDC__
pikCreateMap(FILE * file,pikMapPtr * newmap)97 pikErr pikCreateMap(FILE *file, pikMapPtr *newmap)
98 #else
99 pikErr pikCreateMap(file, newmap)
100 FILE *file;
101 pikMapPtr *newmap;
102 #endif
103 {
104 pikMapPtr map;
105 pikLong buffer[6];
106 int err;
107 long count;
108 long lx;
109 pikLong numchunks;
110 pikLong filelength;
111 pikDescriptor *chunks;
112
113 if (sizeof(pikLong) != 4) {
114 return pikerr_WrongSizeInts;
115 }
116 {
117 pikLong testval;
118 unsigned char *cx;
119 cx = (unsigned char *)(&testval);
120 cx[0] = 0x12;
121 cx[1] = 0x34;
122 cx[2] = 0x56;
123 cx[3] = 0x78;
124 if (pikNative(testval) != 0x12345678) {
125 return pikerr_WrongEndian;
126 }
127 }
128
129 if (!file) {
130 return pikerr_BadOption;
131 }
132
133 err = fseek(file, 0, 0);
134 if (err) {
135 return pikerr_CantRead;
136 }
137
138 count = fread(buffer, 1, 16, file);
139 if (count != 16) {
140 return pikerr_CantRead;
141 }
142
143 if (pikNative(buffer[0]) != pikMakeType('p', 'i', 'k', 'l')
144 || pikNative(buffer[1]) != 1) {
145 return pikerr_NotAMap;
146 }
147
148 numchunks = pikNative(buffer[2]);
149 filelength = pikNative(buffer[3]);
150
151 err = fseek(file, 0, 2);
152 if (err) {
153 return pikerr_CantRead;
154 }
155 count = ftell(file);
156 if (count == (-1)) {
157 return pikerr_CantRead;
158 }
159 if (count != filelength) {
160 return pikerr_NotAMap;
161 }
162 err = fseek(file, 16, 0);
163 if (err) {
164 return pikerr_CantRead;
165 }
166
167 map = (pikMapPtr)malloc(sizeof(pikMap));
168 if (!map) {
169 return pikerr_Memory;
170 }
171 chunks = (pikDescriptor *)malloc(sizeof(pikDescriptor) * numchunks);
172 if (!chunks) {
173 free(map);
174 return pikerr_Memory;
175 }
176
177 for (lx=0; lx<numchunks; lx++) {
178
179 count = fread(buffer, 1, 24, file);
180 if (count != 24) {
181 free(chunks);
182 free(map);
183 return pikerr_CantRead;
184 }
185
186 chunks[lx].use = pikNative(buffer[0]);
187 chunks[lx].number = pikNative(buffer[1]);
188 chunks[lx].format = pikNative(buffer[2]);
189 chunks[lx].formatversion = pikNative(buffer[3]);
190 chunks[lx].startpos = pikNative(buffer[4]);
191 chunks[lx].length = pikNative(buffer[5]);
192 chunks[lx].data = NULL;
193 }
194
195 map->chunks = chunks;
196 map->numchunks = numchunks;
197 map->filelength = filelength;
198 map->file = file;
199 map->inited = pik_InitedMagic;
200
201 *newmap = map;
202 return pikerr_None;
203 }
204
205 #ifdef __STDC__
pikDestroyMap(pikMapPtr map)206 pikErr pikDestroyMap(pikMapPtr map)
207 #else
208 pikErr pikDestroyMap(map)
209 pikMapPtr map;
210 #endif
211 {
212 pikLong lx;
213 pikDescriptor *desc;
214
215 if (!map || !map->chunks || map->inited != pik_InitedMagic) {
216 return pikerr_NotAMap;
217 }
218
219 for (lx=0; lx<map->numchunks; lx++) {
220 desc = (&(map->chunks[lx]));
221 if (desc->data) {
222 free(desc->data);
223 desc->data = NULL;
224 }
225 }
226
227 map->inited = 0;
228 free(map->chunks);
229 free(map);
230
231 return pikerr_None;
232 }
233
234 #ifdef __STDC__
pikFindChunk(pikMapPtr map,pikType use,pikLong number,short numformats,pikFormat * formatlist,pikChunkID * idfound)235 pikErr pikFindChunk(pikMapPtr map, pikType use, pikLong number,
236 short numformats, pikFormat *formatlist, pikChunkID *idfound)
237 #else
238 pikErr pikFindChunk(map, use, number, numformats, formatlist, idfound)
239 pikMapPtr map;
240 pikType use;
241 pikLong number;
242 short numformats;
243 pikFormat *formatlist;
244 pikChunkID *idfound;
245 #endif
246 {
247 pikDescriptor *desc;
248 pikLong id, bestid;
249 short fx, sofar;
250
251 if (!map || !map->chunks || map->inited != pik_InitedMagic) {
252 return pikerr_NotAMap;
253 }
254
255 if (numformats < 0 || (numformats > 0 && !formatlist)) {
256 return pikerr_BadOption;
257 }
258
259 sofar = (-1);
260 for (id=0, desc=map->chunks; id<map->numchunks; id++, desc++) {
261 if (desc->use == use && desc->number == number) {
262 if (numformats == 0) {
263 if (idfound)
264 *idfound = id;
265 return pikerr_None;
266 }
267 for (fx=0; fx<numformats; fx++) {
268 if (desc->format == formatlist[fx].name &&
269 desc->formatversion == formatlist[fx].version) {
270 if (sofar < 0 || fx < sofar) {
271 sofar = fx;
272 bestid = id;
273 }
274 }
275 }
276 }
277 }
278
279 if (sofar >= 0) {
280 if (idfound)
281 *idfound = bestid;
282 return pikerr_None;
283 }
284
285 if (idfound)
286 *idfound = pik_NoChunk;
287 return pikerr_NotFound;
288 }
289
290 #ifdef __STDC__
pikLoadChunk(pikMapPtr map,pikChunkID id,short method,pikChunk * found)291 pikErr pikLoadChunk(pikMapPtr map, pikChunkID id, short method, pikChunk *found)
292 #else
293 pikErr pikLoadChunk(map, id, method, found)
294 pikMapPtr map;
295 pikChunkID id;
296 short method;
297 pikChunk *found;
298 #endif
299 {
300 pikDescriptor *desc;
301
302 if (!map || !map->chunks || map->inited != pik_InitedMagic) {
303 return pikerr_NotAMap;
304 }
305
306 if (id < 0 || id >= map->numchunks) {
307 return pikerr_BadOption;
308 }
309 if (!found) {
310 return pikerr_BadOption;
311 }
312
313 desc = (&(map->chunks[id]));
314 switch (method) {
315 case pikmethod_DontRead:
316 break;
317 case pikmethod_FilePos:
318 found->data.startpos = desc->startpos;
319 break;
320 case pikmethod_Memory:
321 if (!desc->data) {
322 long count;
323 int err;
324 desc->data = malloc(desc->length);
325 if (!desc->data) {
326 return pikerr_Memory;
327 }
328 err = fseek(map->file, desc->startpos, 0);
329 if (err) {
330 return pikerr_CantRead;
331 }
332 count = fread(desc->data, 1, desc->length, map->file);
333 if (count != desc->length) {
334 return pikerr_CantRead;
335 }
336 }
337 found->data.ptr = desc->data;
338 break;
339 default:
340 return pikerr_BadOption;
341 }
342
343 found->length = desc->length;
344 found->format.name = desc->format;
345 found->format.version = desc->formatversion;
346
347 return pikerr_None;
348 }
349
350 #ifdef __STDC__
pikUnloadChunk(pikMapPtr map,pikChunkID id)351 pikErr pikUnloadChunk(pikMapPtr map, pikChunkID id)
352 #else
353 pikErr pikUnloadChunk(map, id)
354 pikMapPtr map;
355 pikChunkID id;
356 #endif
357 {
358 pikDescriptor *desc;
359
360 if (!map || !map->chunks || map->inited != pik_InitedMagic) {
361 return pikerr_NotAMap;
362 }
363
364 if (id < 0 || id >= map->numchunks) {
365 return pikerr_BadOption;
366 }
367
368 desc = (&(map->chunks[id]));
369
370 if (desc->data) {
371 free(desc->data);
372 desc->data = NULL;
373 return pikerr_None;
374 }
375 else {
376 return pikerr_NotFound;
377 }
378 }
379
380