|
dvander@29
|
1 |
#include <stdio.h> |
|
dvander@29
|
2 |
#include <string.h> |
|
dvander@29
|
3 |
#include <malloc.h> |
|
dvander@29
|
4 |
#include "sp_file.h" |
|
dvander@31
|
5 |
#include "memfile.h" |
|
dvander@29
|
6 |
|
|
dvander@31
|
7 |
void *mf_open(const char *name); |
|
dvander@31
|
8 |
void mf_close(void *handle); |
|
dvander@31
|
9 |
size_t mf_write(const void *buf, size_t size, size_t count, void *handle); |
|
dvander@31
|
10 |
size_t mf_read(void *buf, size_t size, size_t count, void *handle); |
|
dvander@31
|
11 |
size_t mf_getpos(void *handle); |
|
dvander@31
|
12 |
int mf_setpos(void *handle, size_t pos); |
|
dvander@29
|
13 |
|
|
dvander@29
|
14 |
sp_writefuncs_t cstd_funcs = |
|
dvander@29
|
15 |
{ |
|
dvander@31
|
16 |
mf_open, |
|
dvander@31
|
17 |
mf_close, |
|
dvander@31
|
18 |
mf_write, |
|
dvander@31
|
19 |
mf_read, |
|
dvander@31
|
20 |
mf_getpos, |
|
dvander@31
|
21 |
mf_setpos |
|
dvander@29
|
22 |
}; |
|
dvander@29
|
23 |
|
|
dvander@29
|
24 |
sp_file_t *spfw_create(const char *name, sp_writefuncs_t *optfuncs) |
|
dvander@29
|
25 |
{ |
|
dvander@29
|
26 |
sp_file_t file; |
|
dvander@29
|
27 |
sp_file_t *pFile; |
|
dvander@29
|
28 |
|
|
dvander@29
|
29 |
if (!optfuncs) |
|
dvander@29
|
30 |
{ |
|
dvander@29
|
31 |
optfuncs = &cstd_funcs; |
|
dvander@29
|
32 |
} |
|
dvander@29
|
33 |
|
|
dvander@29
|
34 |
file.handle = optfuncs->fnOpen(name); |
|
dvander@29
|
35 |
if (!file.handle) |
|
dvander@29
|
36 |
{ |
|
dvander@29
|
37 |
return NULL; |
|
dvander@29
|
38 |
} |
|
dvander@29
|
39 |
|
|
dvander@29
|
40 |
pFile = (sp_file_t *)malloc(sizeof(sp_file_t)); |
|
dvander@29
|
41 |
|
|
dvander@29
|
42 |
pFile->handle = file.handle; |
|
dvander@29
|
43 |
memcpy(&pFile->funcs, optfuncs, sizeof(sp_writefuncs_t)); |
|
dvander@29
|
44 |
pFile->curoffs = 0; |
|
dvander@29
|
45 |
pFile->header.magic = SPFILE_MAGIC; |
|
dvander@29
|
46 |
pFile->header.sections = 0; |
|
dvander@29
|
47 |
pFile->header.stringtab = 0; |
|
dvander@29
|
48 |
pFile->header.version = SPFILE_VERSION; |
|
dvander@29
|
49 |
pFile->header.imagesize = 0; |
|
dvander@31
|
50 |
pFile->header.disksize = 0; |
|
dvander@31
|
51 |
pFile->header.compression = SPFILE_COMPRESSION_NONE; |
|
dvander@31
|
52 |
pFile->header.dataoffs = 0; |
|
dvander@29
|
53 |
pFile->lastsection = 0; |
|
dvander@29
|
54 |
pFile->offsets = NULL; |
|
dvander@29
|
55 |
pFile->sections = NULL; |
|
dvander@29
|
56 |
pFile->state = -1; |
|
dvander@29
|
57 |
pFile->nametab = NULL; |
|
dvander@29
|
58 |
pFile->nametab_idx = 0; |
|
dvander@29
|
59 |
|
|
dvander@29
|
60 |
return pFile; |
|
dvander@29
|
61 |
} |
|
dvander@29
|
62 |
|
|
dvander@29
|
63 |
void spfw_destroy(sp_file_t *spf) |
|
dvander@29
|
64 |
{ |
|
dvander@29
|
65 |
free(spf->sections); |
|
dvander@29
|
66 |
free(spf->nametab); |
|
dvander@29
|
67 |
free(spf->offsets); |
|
dvander@29
|
68 |
spf->funcs.fnClose(spf->handle); |
|
dvander@29
|
69 |
free(spf); |
|
dvander@29
|
70 |
} |
|
dvander@29
|
71 |
|
|
dvander@29
|
72 |
uint8_t spfw_add_section(sp_file_t *spf, const char *name) |
|
dvander@29
|
73 |
{ |
|
dvander@29
|
74 |
size_t namelen; |
|
dvander@29
|
75 |
uint8_t s; |
|
dvander@29
|
76 |
if (spf->state != -1) |
|
dvander@29
|
77 |
{ |
|
dvander@29
|
78 |
return 0; |
|
dvander@29
|
79 |
} |
|
dvander@29
|
80 |
|
|
dvander@29
|
81 |
namelen = strlen(name) + 1; |
|
dvander@29
|
82 |
|
|
dvander@29
|
83 |
if (spf->header.sections == 0) |
|
dvander@29
|
84 |
{ |
|
dvander@29
|
85 |
/** allocate for first section */ |
|
dvander@29
|
86 |
spf->sections = (sp_file_section_t *)malloc(sizeof(sp_file_section_t)); |
|
dvander@29
|
87 |
spf->offsets = (size_t *)malloc(sizeof(size_t)); |
|
dvander@29
|
88 |
spf->nametab = (char *)malloc(namelen); |
|
dvander@29
|
89 |
} else { |
|
dvander@29
|
90 |
uint16_t num = spf->header.sections + 1; |
|
dvander@29
|
91 |
spf->sections = (sp_file_section_t *)realloc(spf->sections, sizeof(sp_file_section_t) * num); |
|
dvander@29
|
92 |
spf->offsets = (size_t *)realloc(spf->offsets, sizeof(size_t) * num); |
|
dvander@29
|
93 |
spf->nametab = (char *)realloc(spf->nametab, spf->nametab_idx + namelen); |
|
dvander@29
|
94 |
} |
|
dvander@29
|
95 |
|
|
dvander@29
|
96 |
s = spf->header.sections; |
|
dvander@29
|
97 |
|
|
dvander@29
|
98 |
spf->sections[s].nameoffs = spf->nametab_idx; |
|
dvander@29
|
99 |
/** |
|
dvander@29
|
100 |
* "fix" offset will be the second uint2 slot, which is after the previous sections after the header. |
|
dvander@29
|
101 |
*/ |
|
dvander@29
|
102 |
spf->offsets[s] = sizeof(spf->header) + (sizeof(sp_file_section_t) * spf->header.sections) + sizeof(uint32_t); |
|
dvander@29
|
103 |
strcpy(&spf->nametab[spf->nametab_idx], name); |
|
dvander@29
|
104 |
spf->nametab_idx += namelen; |
|
dvander@29
|
105 |
|
|
dvander@29
|
106 |
return ++spf->header.sections; |
|
dvander@29
|
107 |
} |
|
dvander@29
|
108 |
|
|
dvander@29
|
109 |
int spfw_finalize_header(sp_file_t *spf) |
|
dvander@29
|
110 |
{ |
|
dvander@29
|
111 |
uint32_t size; |
|
dvander@29
|
112 |
if (spf->state != -1) |
|
dvander@29
|
113 |
{ |
|
dvander@29
|
114 |
return -1; |
|
dvander@29
|
115 |
} |
|
dvander@29
|
116 |
|
|
dvander@29
|
117 |
size = sizeof(sp_file_section_t) * spf->header.sections; |
|
dvander@29
|
118 |
|
|
dvander@29
|
119 |
spf->header.stringtab = sizeof(spf->header) + size; |
|
dvander@31
|
120 |
spf->header.dataoffs = spf->header.stringtab + spf->nametab_idx; |
|
dvander@29
|
121 |
if (spf->funcs.fnWrite(&spf->header, sizeof(spf->header), 1, spf->handle) != 1) |
|
dvander@29
|
122 |
{ |
|
dvander@29
|
123 |
return -1; |
|
dvander@29
|
124 |
} |
|
dvander@29
|
125 |
if (spf->funcs.fnWrite(spf->sections, sizeof(sp_file_section_t), spf->header.sections, spf->handle) != |
|
dvander@29
|
126 |
spf->header.sections) |
|
dvander@29
|
127 |
{ |
|
dvander@29
|
128 |
return -1; |
|
dvander@29
|
129 |
} |
|
dvander@29
|
130 |
if (spf->funcs.fnWrite(spf->nametab, sizeof(char), spf->nametab_idx, spf->handle) != spf->nametab_idx) |
|
dvander@29
|
131 |
{ |
|
dvander@29
|
132 |
return -1; |
|
dvander@29
|
133 |
} |
|
dvander@29
|
134 |
spf->curoffs = spf->funcs.fnGetPos(spf->handle); |
|
dvander@29
|
135 |
spf->lastsection = spf->curoffs; |
|
dvander@29
|
136 |
spf->state++; |
|
dvander@29
|
137 |
|
|
dvander@29
|
138 |
return 0; |
|
dvander@29
|
139 |
} |
|
dvander@29
|
140 |
|
|
dvander@29
|
141 |
int spfw_next_section(sp_file_t *spf) |
|
dvander@29
|
142 |
{ |
|
dvander@29
|
143 |
uint8_t s; |
|
dvander@29
|
144 |
uint32_t rest[2]; |
|
dvander@29
|
145 |
|
|
dvander@29
|
146 |
if (spf->state < 0 || spf->state > spf->header.sections) |
|
dvander@29
|
147 |
{ |
|
dvander@29
|
148 |
return -1; |
|
dvander@29
|
149 |
} |
|
dvander@29
|
150 |
|
|
dvander@29
|
151 |
if (spf->state == (int)spf->header.sections) |
|
dvander@29
|
152 |
{ |
|
dvander@29
|
153 |
return 0; |
|
dvander@29
|
154 |
} |
|
dvander@29
|
155 |
|
|
dvander@29
|
156 |
s = (uint8_t)spf->state; |
|
dvander@29
|
157 |
|
|
dvander@29
|
158 |
spf->curoffs = spf->funcs.fnGetPos(spf->handle); |
|
dvander@29
|
159 |
spf->funcs.fnSetPos(spf->handle, spf->offsets[s]); |
|
dvander@29
|
160 |
|
|
dvander@29
|
161 |
rest[0] = spf->lastsection; |
|
dvander@29
|
162 |
rest[1] = spf->curoffs - spf->lastsection; |
|
dvander@29
|
163 |
if (spf->funcs.fnWrite(rest, sizeof(uint32_t), 2, spf->handle) != 2) |
|
dvander@29
|
164 |
{ |
|
dvander@29
|
165 |
return -1; |
|
dvander@29
|
166 |
} |
|
dvander@29
|
167 |
|
|
dvander@29
|
168 |
spf->funcs.fnSetPos(spf->handle, spf->curoffs); |
|
dvander@29
|
169 |
spf->lastsection = spf->curoffs; |
|
dvander@29
|
170 |
|
|
dvander@29
|
171 |
spf->state++; |
|
dvander@29
|
172 |
|
|
dvander@29
|
173 |
return 1; |
|
dvander@29
|
174 |
} |
|
dvander@29
|
175 |
|
|
dvander@29
|
176 |
int spfw_finalize_all(sp_file_t *spf) |
|
dvander@29
|
177 |
{ |
|
dvander@29
|
178 |
uint8_t offs; |
|
dvander@29
|
179 |
|
|
dvander@29
|
180 |
if (spf->state < spf->header.sections) |
|
dvander@29
|
181 |
{ |
|
dvander@29
|
182 |
return -1; |
|
dvander@29
|
183 |
} |
|
dvander@29
|
184 |
|
|
dvander@29
|
185 |
offs = offsetof(sp_file_hdr_t, imagesize); |
|
dvander@31
|
186 |
spf->header.disksize = spf->funcs.fnGetPos(spf->handle); |
|
dvander@29
|
187 |
spf->header.imagesize = spf->funcs.fnGetPos(spf->handle); |
|
dvander@29
|
188 |
spf->funcs.fnSetPos(spf->handle, offs); |
|
dvander@29
|
189 |
spf->funcs.fnWrite(&spf->header.imagesize, sizeof(uint32_t), 1, spf->handle); |
|
dvander@29
|
190 |
spf->funcs.fnSetPos(spf->handle, spf->header.imagesize); |
|
dvander@29
|
191 |
|
|
dvander@29
|
192 |
return 1; |
|
dvander@29
|
193 |
} |
|
dvander@29
|
194 |
|
|
dvander@29
|
195 |
/** |
|
dvander@31
|
196 |
* More memory file operations |
|
dvander@31
|
197 |
*/ |
|
dvander@31
|
198 |
|
|
dvander@31
|
199 |
void *mf_open(const char *name) |
|
dvander@31
|
200 |
{ |
|
dvander@31
|
201 |
return memfile_creat(name, 1024); |
|
dvander@31
|
202 |
} |
|
dvander@31
|
203 |
|
|
dvander@31
|
204 |
void mf_close(void *handle) |
|
dvander@31
|
205 |
{ |
|
dvander@31
|
206 |
memfile_destroy((memfile_t *)handle); |
|
dvander@31
|
207 |
} |
|
dvander@31
|
208 |
|
|
dvander@31
|
209 |
size_t mf_write(const void *buf, size_t size, size_t count, void *handle) |
|
dvander@31
|
210 |
{ |
|
dvander@31
|
211 |
if (!count) |
|
dvander@31
|
212 |
{ |
|
dvander@31
|
213 |
return 0; |
|
dvander@31
|
214 |
} |
|
dvander@31
|
215 |
|
|
dvander@31
|
216 |
if (memfile_write((memfile_t *)handle, buf, size*count)) |
|
dvander@31
|
217 |
{ |
|
dvander@31
|
218 |
return count; |
|
dvander@31
|
219 |
} |
|
dvander@31
|
220 |
|
|
dvander@31
|
221 |
return 0; |
|
dvander@31
|
222 |
} |
|
dvander@31
|
223 |
|
|
dvander@31
|
224 |
size_t mf_read(void *buf, size_t size, size_t count, void *handle) |
|
dvander@31
|
225 |
{ |
|
dvander@31
|
226 |
return memfile_read((memfile_t *)handle, buf, size*count) / count; |
|
dvander@31
|
227 |
} |
|
dvander@31
|
228 |
|
|
dvander@31
|
229 |
size_t mf_getpos(void *handle) |
|
dvander@31
|
230 |
{ |
|
dvander@31
|
231 |
return (long)memfile_tell((memfile_t *)handle); |
|
dvander@31
|
232 |
} |
|
dvander@31
|
233 |
|
|
dvander@31
|
234 |
int mf_setpos(void *handle, size_t pos) |
|
dvander@31
|
235 |
{ |
|
dvander@31
|
236 |
memfile_seek((memfile_t *)handle, (long)pos); |
|
dvander@31
|
237 |
return 1; |
|
dvander@31
|
238 |
} |
|
dvander@31
|
239 |
|
|
dvander@31
|
240 |
|
|
dvander@31
|
241 |
#if UNUSED_FOR_NOW |
|
dvander@31
|
242 |
/** |
|
dvander@29
|
243 |
* Default file operations... |
|
dvander@29
|
244 |
* Based on C standard library calls. |
|
dvander@29
|
245 |
*/ |
|
dvander@29
|
246 |
|
|
dvander@29
|
247 |
void *fp_open(const char *name) |
|
dvander@29
|
248 |
{ |
|
dvander@29
|
249 |
return fopen(name, "wb"); |
|
dvander@29
|
250 |
} |
|
dvander@29
|
251 |
|
|
dvander@29
|
252 |
void fp_close(void *handle) |
|
dvander@29
|
253 |
{ |
|
dvander@29
|
254 |
fclose((FILE *)handle); |
|
dvander@29
|
255 |
} |
|
dvander@29
|
256 |
|
|
dvander@29
|
257 |
size_t fp_write(const void *buf, size_t size, size_t count, void *handle) |
|
dvander@29
|
258 |
{ |
|
dvander@29
|
259 |
return fwrite(buf, size, count, (FILE *)handle); |
|
dvander@29
|
260 |
} |
|
dvander@29
|
261 |
|
|
dvander@29
|
262 |
size_t fp_read(void *buf, size_t size, size_t count, void *handle) |
|
dvander@29
|
263 |
{ |
|
dvander@29
|
264 |
return fread(buf, size, count, (FILE *)handle); |
|
dvander@29
|
265 |
} |
|
dvander@29
|
266 |
|
|
dvander@29
|
267 |
size_t fp_getpos(void *handle) |
|
dvander@29
|
268 |
{ |
|
dvander@29
|
269 |
return (size_t)ftell((FILE *)handle); |
|
dvander@29
|
270 |
} |
|
dvander@29
|
271 |
|
|
dvander@29
|
272 |
int fp_setpos(void *handle, size_t pos) |
|
dvander@29
|
273 |
{ |
|
dvander@29
|
274 |
return fseek((FILE *)handle, (long)pos, SEEK_SET); |
|
dvander@29
|
275 |
} |
|
dvander@31
|
276 |
#endif |