Skip to content

Latest commit

 

History

History
272 lines (219 loc) · 7.53 KB

archive_pck.c

File metadata and controls

272 lines (219 loc) · 7.53 KB
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* MojoSetup; a portable, flexible installation application.
*
* Please see the file LICENSE.txt in the source's root directory.
*
* This file written by Steffen Pankratz.
*/
#include "fileio.h"
#include "platform.h"
#if !SUPPORT_PCK
MojoArchive *MojoArchive_createPCK(MojoInput *io) { return NULL; }
#else
#define PCK_MAGIC 0x534c4850
typedef struct
{
Mar 23, 2010
Mar 23, 2010
20
uint32 Magic; // 4 bytes, has to be PCK_MAGIC (0x534c4850)
21
uint32 StartOfBinaryData; // 4 bytes, offset to the data
Mar 23, 2010
Mar 23, 2010
22
} PCKheader;
23
24
25
typedef struct
{
Mar 29, 2010
Mar 29, 2010
26
int8 filename[60]; // 60 bytes, null terminated
27
uint32 filesize; // 4 bytes
Mar 23, 2010
Mar 23, 2010
28
} PCKentry;
Mar 29, 2010
Mar 29, 2010
30
typedef struct
31
32
33
34
35
{
uint64 fileCount;
uint64 dataStart;
uint64 nextFileStart;
int64 nextEnumPos;
Mar 23, 2010
Mar 23, 2010
36
MojoArchiveEntry *archiveEntries;
37
38
39
40
41
42
43
44
45
46
} PCKinfo;
static boolean MojoInput_pck_ready(MojoInput *io)
{
return true; // !!! FIXME?
} // MojoInput_pck_ready
static int64 MojoInput_pck_read(MojoInput *io, void *buf, uint32 bufsize)
{
MojoArchive *ar = (MojoArchive *) io->opaque;
Mar 23, 2010
Mar 23, 2010
47
const MojoArchiveEntry *entry = &ar->prevEnum;
48
int64 pos = io->tell(io);
Mar 23, 2010
Mar 23, 2010
49
50
if ((pos + bufsize) > entry->filesize)
bufsize = (uint32) (entry->filesize - pos);
51
52
53
54
55
56
return ar->io->read(ar->io, buf, bufsize);
} // MojoInput_pck_read
static boolean MojoInput_pck_seek(MojoInput *io, uint64 pos)
{
MojoArchive *ar = (MojoArchive *) io->opaque;
Mar 23, 2010
Mar 23, 2010
57
const PCKinfo *info = (PCKinfo *) ar->opaque;
Mar 23, 2010
Mar 23, 2010
58
const MojoArchiveEntry *entry = &ar->prevEnum;
59
boolean retval = false;
Mar 23, 2010
Mar 23, 2010
60
if (pos < ((uint64) entry->filesize))
Mar 23, 2010
Mar 23, 2010
61
{
Mar 23, 2010
Mar 23, 2010
62
const uint64 newpos = (info->nextFileStart - entry->filesize) + pos;
Mar 23, 2010
Mar 23, 2010
63
64
retval = ar->io->seek(ar->io, newpos);
} // if
65
66
67
68
69
70
return retval;
} // MojoInput_pck_seek
static int64 MojoInput_pck_tell(MojoInput *io)
{
MojoArchive *ar = (MojoArchive *) io->opaque;
Mar 23, 2010
Mar 23, 2010
71
const PCKinfo *info = (PCKinfo *) ar->opaque;
Mar 23, 2010
Mar 23, 2010
72
73
const MojoArchiveEntry *entry = &ar->prevEnum;
return ar->io->tell(ar->io) - (info->nextFileStart - entry->filesize);
74
75
76
77
78
} // MojoInput_pck_tell
static int64 MojoInput_pck_length(MojoInput *io)
{
MojoArchive *ar = (MojoArchive *) io->opaque;
Mar 23, 2010
Mar 23, 2010
79
80
const MojoArchiveEntry *entry = &ar->prevEnum;
return entry->filesize;
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
} // MojoInput_pck_length
static MojoInput *MojoInput_pck_duplicate(MojoInput *io)
{
MojoInput *retval = NULL;
fatal(_("BUG: Can't duplicate pck inputs")); // !!! FIXME: why not?
return retval;
} // MojoInput_pck_duplicate
static void MojoInput_pck_close(MojoInput *io)
{
free(io);
} // MojoInput_pck_close
// MojoArchive implementation...
static boolean MojoArchive_pck_enumerate(MojoArchive *ar)
{
Mar 23, 2010
Mar 23, 2010
99
MojoArchiveEntry *archiveEntries = NULL;
100
PCKinfo *info = (PCKinfo *) ar->opaque;
Mar 23, 2010
Mar 23, 2010
101
102
103
104
const int dataStart = info->dataStart;
const int fileCount = dataStart / sizeof (PCKentry);
const size_t len = fileCount * sizeof (MojoArchiveEntry);
PCKentry fileEntry;
105
106
uint64 i, realFileCount = 0;
char directory[256] = {'\0'};
Mar 29, 2010
Mar 29, 2010
107
MojoInput *io = ar->io;
Mar 23, 2010
Mar 23, 2010
109
110
111
112
113
MojoArchive_resetEntry(&ar->prevEnum);
archiveEntries = (MojoArchiveEntry *) xmalloc(len);
for (i = 0; i < fileCount; i++)
114
{
Mar 23, 2010
Mar 23, 2010
115
int dotdot;
Mar 29, 2010
Mar 29, 2010
116
117
118
119
120
int64 br;
br = io->read(io, fileEntry.filename, sizeof (fileEntry.filename));
if (br != sizeof (fileEntry.filename))
return false;
Apr 24, 2010
Apr 24, 2010
121
else if (!MojoInput_readui32(io, &fileEntry.filesize))
Mar 29, 2010
Mar 29, 2010
122
return false;
Mar 23, 2010
Mar 23, 2010
123
124
dotdot = (strcmp(fileEntry.filename, "..") == 0);
Mar 23, 2010
Mar 23, 2010
126
if ((!dotdot) && (fileEntry.filesize == 0x80000000))
127
{
Mar 23, 2010
Mar 23, 2010
128
129
MojoArchiveEntry *entry = &archiveEntries[realFileCount];
130
131
132
strcat(directory, fileEntry.filename);
strcat(directory, "/");
Mar 23, 2010
Mar 23, 2010
133
134
135
136
entry->filename = xstrdup(directory);
entry->type = MOJOARCHIVE_ENTRY_DIR;
entry->perms = MojoPlatform_defaultDirPerms();
entry->filesize = 0;
137
realFileCount++;
Mar 23, 2010
Mar 23, 2010
138
139
140
} // if
else if ((dotdot) && (fileEntry.filesize == 0x80000000))
141
{
Mar 23, 2010
Mar 23, 2010
142
143
144
// remove trailing path separator
char *pathSep;
const size_t strLength = strlen(directory);
145
146
directory[strLength - 1] = '\0';
Mar 23, 2010
Mar 23, 2010
147
pathSep = strrchr(directory, '/');
148
149
150
151
if(pathSep != NULL)
{
pathSep++;
*pathSep = '\0';
Mar 23, 2010
Mar 23, 2010
152
153
154
} // if
} // else if
155
156
else
{
Mar 23, 2010
Mar 23, 2010
157
158
159
MojoArchiveEntry *entry = &archiveEntries[realFileCount];
if (directory[0] == '\0')
entry->filename = xstrdup(fileEntry.filename);
160
161
else
{
Mar 23, 2010
Mar 23, 2010
162
163
164
165
166
167
168
169
170
171
172
const size_t len = sizeof (char) * strlen(directory) +
strlen(fileEntry.filename) + 1;
entry->filename = (char *) xmalloc(len);
strcat(entry->filename, directory);
strcat(entry->filename, fileEntry.filename);
} // else
entry->perms = MojoPlatform_defaultFilePerms();
entry->type = MOJOARCHIVE_ENTRY_FILE;
entry->filesize = fileEntry.filesize;
173
realFileCount++;
Mar 23, 2010
Mar 23, 2010
174
175
} // else
} // for
176
177
info->fileCount = realFileCount;
Mar 23, 2010
Mar 23, 2010
178
info->archiveEntries = archiveEntries;
Mar 23, 2010
Mar 23, 2010
179
info->nextEnumPos = 0;
180
181
182
183
184
185
186
187
188
info->nextFileStart = dataStart;
return true;
} // MojoArchive_pck_enumerate
static const MojoArchiveEntry *MojoArchive_pck_enumNext(MojoArchive *ar)
{
PCKinfo *info = (PCKinfo *) ar->opaque;
Mar 23, 2010
Mar 23, 2010
189
const MojoArchiveEntry *entry = &info->archiveEntries[info->nextEnumPos];
Mar 23, 2010
Mar 23, 2010
191
if (info->nextEnumPos >= info->fileCount)
192
193
return NULL;
Mar 23, 2010
Mar 23, 2010
194
if (!ar->io->seek(ar->io, info->nextFileStart))
Mar 23, 2010
Mar 23, 2010
195
return NULL;
196
197
info->nextEnumPos++;
Mar 23, 2010
Mar 23, 2010
198
info->nextFileStart += entry->filesize;
Mar 23, 2010
Mar 23, 2010
200
memcpy(&ar->prevEnum, entry, sizeof (ar->prevEnum));
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
return &ar->prevEnum;
} // MojoArchive_pck_enumNext
static MojoInput *MojoArchive_pck_openCurrentEntry(MojoArchive *ar)
{
MojoInput *io = NULL;
io = (MojoInput *) xmalloc(sizeof (MojoInput));
io->ready = MojoInput_pck_ready;
io->read = MojoInput_pck_read;
io->seek = MojoInput_pck_seek;
io->tell = MojoInput_pck_tell;
io->length = MojoInput_pck_length;
io->duplicate = MojoInput_pck_duplicate;
io->close = MojoInput_pck_close;
io->opaque = ar;
return io;
} // MojoArchive_pck_openCurrentEntry
static void MojoArchive_pck_close(MojoArchive *ar)
{
int i;
PCKinfo *info = (PCKinfo *) ar->opaque;
ar->io->close(ar->io);
Mar 23, 2010
Mar 23, 2010
228
for (i = 0; i < info->fileCount; i++)
229
{
Mar 23, 2010
Mar 23, 2010
230
231
MojoArchiveEntry *entry = &info->archiveEntries[i];
free(entry->filename);
Mar 23, 2010
Mar 23, 2010
232
} // for
Mar 23, 2010
Mar 23, 2010
234
free(info->archiveEntries);
235
236
237
238
free(info);
free(ar);
} // MojoArchive_pck_close
Mar 23, 2010
Mar 23, 2010
239
Mar 29, 2010
Mar 29, 2010
240
MojoArchive *MojoArchive_createPCK(MojoInput *io)
241
242
{
MojoArchive *ar = NULL;
Mar 23, 2010
Mar 23, 2010
243
244
PCKinfo *pckInfo = NULL;
PCKheader pckHeader;
Mar 29, 2010
Mar 29, 2010
245
Apr 24, 2010
Apr 24, 2010
246
if (!MojoInput_readui32(io, &pckHeader.Magic))
Mar 29, 2010
Mar 29, 2010
247
return NULL;
Apr 24, 2010
Apr 24, 2010
248
else if (!MojoInput_readui32(io, &pckHeader.StartOfBinaryData))
Mar 29, 2010
Mar 29, 2010
249
return NULL;
250
251
// Check if this is a *.pck file.
Mar 29, 2010
Mar 29, 2010
252
if (pckHeader.Magic != PCK_MAGIC)
253
254
return NULL;
Mar 23, 2010
Mar 23, 2010
255
256
pckInfo = (PCKinfo *) xmalloc(sizeof (PCKinfo));
pckInfo->dataStart = pckHeader.StartOfBinaryData + sizeof (PCKheader);
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
ar = (MojoArchive *) xmalloc(sizeof (MojoArchive));
ar->opaque = pckInfo;
ar->enumerate = MojoArchive_pck_enumerate;
ar->enumNext = MojoArchive_pck_enumNext;
ar->openCurrentEntry = MojoArchive_pck_openCurrentEntry;
ar->close = MojoArchive_pck_close;
ar->io = io;
return ar;
} // MojoArchive_createPCK
#endif // SUPPORT_PCK
// end of archive_pck.c ...