Skip to content

Latest commit

 

History

History
724 lines (595 loc) · 20.2 KB

fileio.c

File metadata and controls

724 lines (595 loc) · 20.2 KB
 
May 12, 2007
May 12, 2007
1
2
3
4
5
6
7
8
/**
* MojoSetup; a portable, flexible installation application.
*
* Please see the file LICENSE.txt in the source's root directory.
*
* This file written by Ryan C. Gordon.
*/
Mar 25, 2006
Mar 25, 2006
10
#include "platform.h"
Mar 26, 2006
Mar 26, 2006
12
13
14
typedef MojoArchive* (*MojoArchiveCreateEntryPoint)(MojoInput *io);
MojoArchive *MojoArchive_createZIP(MojoInput *io);
May 4, 2007
May 4, 2007
15
MojoArchive *MojoArchive_createTAR(MojoInput *io);
May 10, 2009
May 10, 2009
16
MojoArchive *MojoArchive_createUZ2(MojoInput *io);
Mar 26, 2006
Mar 26, 2006
17
18
19
20
21
typedef struct
{
const char *ext;
MojoArchiveCreateEntryPoint create;
May 9, 2009
May 9, 2009
22
boolean hasMagic; // can determine file type from contents?
Mar 26, 2006
Mar 26, 2006
23
24
25
26
} MojoArchiveType;
static const MojoArchiveType archives[] =
{
May 9, 2009
May 9, 2009
27
28
29
30
31
32
33
34
{ "zip", MojoArchive_createZIP, true },
{ "tar", MojoArchive_createTAR, true },
{ "tar.gz", MojoArchive_createTAR, true },
{ "tar.bz2", MojoArchive_createTAR, true },
{ "tgz", MojoArchive_createTAR, true },
{ "tbz2", MojoArchive_createTAR, true },
{ "tb2", MojoArchive_createTAR, true },
{ "tbz", MojoArchive_createTAR, true },
May 10, 2009
May 10, 2009
35
{ "uz2", MojoArchive_createUZ2, false },
Mar 26, 2006
Mar 26, 2006
36
37
};
May 5, 2007
May 5, 2007
38
MojoArchive *MojoArchive_newFromInput(MojoInput *io, const char *origfname)
Mar 26, 2006
Mar 26, 2006
39
40
41
{
int i;
MojoArchive *retval = NULL;
May 5, 2007
May 5, 2007
42
43
44
45
const char *ext = NULL;
if (origfname != NULL)
{
May 9, 2009
May 9, 2009
46
ext = strrchr(origfname, '/');
May 5, 2007
May 5, 2007
47
48
49
50
51
52
if (ext == NULL)
ext = strchr(origfname, '.');
else
ext = strchr(ext+1, '.');
} // if
May 9, 2009
May 9, 2009
53
while (ext != NULL)
Mar 26, 2006
Mar 26, 2006
54
{
May 9, 2009
May 9, 2009
55
// Try for an exact match by filename extension.
May 5, 2007
May 5, 2007
56
ext++; // skip that '.'
Mar 26, 2006
Mar 26, 2006
57
58
for (i = 0; i < STATICARRAYLEN(archives); i++)
{
May 9, 2009
May 9, 2009
59
60
61
const MojoArchiveType *arc = &archives[i];
if (strcasecmp(ext, arc->ext) == 0)
return arc->create(io);
Mar 26, 2006
Mar 26, 2006
62
} // for
May 9, 2009
May 9, 2009
63
64
ext = strchr(ext, '.');
} // while
Mar 26, 2006
Mar 26, 2006
65
May 9, 2009
May 9, 2009
66
// Try any that could be determined without the file extension...
Mar 26, 2006
Mar 26, 2006
67
68
for (i = 0; i < STATICARRAYLEN(archives); i++)
{
May 9, 2009
May 9, 2009
69
70
const MojoArchiveType *arc = &archives[i];
if ((arc->hasMagic) && ((retval = arc->create(io)) != NULL))
Mar 26, 2006
Mar 26, 2006
71
72
73
74
75
76
77
78
return retval;
} // for
io->close(io);
return NULL; // nothing can handle this data.
} // MojoArchive_newFromInput
May 4, 2007
May 4, 2007
79
void MojoArchive_resetEntry(MojoArchiveEntry *info)
Mar 26, 2006
Mar 26, 2006
80
81
{
free(info->filename);
May 1, 2007
May 1, 2007
82
free(info->linkdest);
Apr 29, 2007
Apr 29, 2007
83
84
memset(info, '\0', sizeof (MojoArchiveEntry));
} // MojoArchive_resetEntry
Mar 26, 2006
Mar 26, 2006
85
86
May 1, 2007
May 1, 2007
87
88
// !!! FIXME: I'd rather not use a callback here, but I can't see a cleaner
// !!! FIXME: way right now...
May 3, 2007
May 3, 2007
89
boolean MojoInput_toPhysicalFile(MojoInput *in, const char *fname, uint16 perms,
Jan 16, 2008
Jan 16, 2008
90
MojoChecksums *checksums, int64 maxbytes,
May 1, 2007
May 1, 2007
91
MojoInput_FileCopyCallback cb, void *data)
May 7, 2007
May 7, 2007
93
94
boolean retval = false;
uint32 start = MojoPlatform_ticks();
Sep 20, 2007
Sep 20, 2007
95
void *out = NULL;
96
boolean iofailure = false;
May 1, 2007
May 1, 2007
97
98
int64 flen = 0;
int64 bw = 0;
May 27, 2007
May 27, 2007
99
MojoChecksumContext sumctx;
100
101
102
103
if (in == NULL)
return false;
May 27, 2007
May 27, 2007
104
105
106
107
108
109
if (checksums != NULL)
{
memset(checksums, '\0', sizeof (MojoChecksums));
MojoChecksum_init(&sumctx);
} // if
May 12, 2007
May 12, 2007
110
111
112
113
114
115
// Wait for a ready(), so length() can be meaningful on network streams.
while ((!in->ready(in)) && (!iofailure))
{
MojoPlatform_sleep(100);
if (cb != NULL)
{
May 17, 2007
May 17, 2007
116
if (!cb(MojoPlatform_ticks() - start, 0, 0, -1, data))
May 12, 2007
May 12, 2007
117
118
119
120
iofailure = true;
} // if
} // while
May 1, 2007
May 1, 2007
121
flen = in->length(in);
Jan 16, 2008
Jan 16, 2008
122
123
if ((maxbytes >= 0) && (flen > maxbytes))
flen = maxbytes;
May 1, 2007
May 1, 2007
124
Dec 9, 2006
Dec 9, 2006
125
MojoPlatform_unlink(fname);
May 12, 2007
May 12, 2007
126
if (!iofailure)
Sep 20, 2007
Sep 20, 2007
127
128
129
130
131
{
const uint32 flags = MOJOFILE_WRITE|MOJOFILE_CREATE|MOJOFILE_TRUNCATE;
const uint16 mode = MojoPlatform_defaultFilePerms();
out = MojoPlatform_open(fname, flags, mode);
} // if
May 12, 2007
May 12, 2007
132
May 7, 2007
May 7, 2007
133
if (out != NULL)
May 7, 2007
May 7, 2007
135
while (!iofailure)
May 8, 2007
May 8, 2007
137
int64 br = 0;
Jan 16, 2008
Jan 16, 2008
138
139
140
141
142
143
144
145
146
147
148
149
150
int64 maxread = sizeof (scratchbuf_128k);
// see if we need to clamp to eof or maxbytes...
if (flen >= 0)
{
const int64 avail = flen - bw;
if (avail < maxread)
{
maxread = avail;
if (maxread == 0)
break; // nothing left to do, break out.
} // if
} // if
May 8, 2007
May 8, 2007
151
May 7, 2007
May 7, 2007
152
153
154
// If there's a callback, then poll. Otherwise, just block on
// the reads from the MojoInput.
if ((cb != NULL) && (!in->ready(in)))
May 7, 2007
May 7, 2007
155
156
MojoPlatform_sleep(100);
else
May 1, 2007
May 1, 2007
157
{
Feb 2, 2008
Feb 2, 2008
158
br = in->read(in, scratchbuf_128k, (uint32) maxread);
May 7, 2007
May 7, 2007
159
160
161
162
163
if (br == 0) // we're done!
break;
else if (br < 0)
iofailure = true;
else
May 1, 2007
May 1, 2007
164
{
Sep 25, 2007
Sep 25, 2007
165
if (MojoPlatform_write(out, scratchbuf_128k, (uint32) br) != br)
May 1, 2007
May 1, 2007
166
iofailure = true;
May 7, 2007
May 7, 2007
167
else
May 27, 2007
May 27, 2007
168
169
{
if (checksums != NULL)
Sep 25, 2007
Sep 25, 2007
170
MojoChecksum_append(&sumctx, scratchbuf_128k, (uint32) br);
May 7, 2007
May 7, 2007
171
bw += br;
May 27, 2007
May 27, 2007
172
} // else
May 7, 2007
May 7, 2007
173
} // else
May 1, 2007
May 1, 2007
174
} // else
May 7, 2007
May 7, 2007
176
177
if (cb != NULL)
{
May 8, 2007
May 8, 2007
178
if (!cb(MojoPlatform_ticks() - start, br, bw, flen, data))
May 7, 2007
May 7, 2007
179
180
181
182
iofailure = true;
} // if
} // while
Sep 20, 2007
Sep 20, 2007
183
if (MojoPlatform_close(out) != 0)
May 7, 2007
May 7, 2007
184
iofailure = true;
Jan 16, 2008
Jan 16, 2008
185
186
else if (bw != flen)
iofailure = true;
May 1, 2007
May 1, 2007
187
May 7, 2007
May 7, 2007
188
189
190
191
192
if (iofailure)
MojoPlatform_unlink(fname);
else
{
MojoPlatform_chmod(fname, perms);
May 27, 2007
May 27, 2007
193
194
if (checksums != NULL)
MojoChecksum_finish(&sumctx, checksums);
May 7, 2007
May 7, 2007
195
196
retval = true;
} // else
May 7, 2007
May 7, 2007
199
200
in->close(in);
return retval;
Dec 9, 2006
Dec 9, 2006
201
} // MojoInput_toPhysicalFile
Mar 25, 2006
Mar 25, 2006
203
Dec 3, 2006
Dec 3, 2006
204
205
206
MojoInput *MojoInput_newFromArchivePath(MojoArchive *ar, const char *fname)
{
MojoInput *retval = NULL;
May 4, 2007
May 4, 2007
207
if (ar->enumerate(ar))
Dec 3, 2006
Dec 3, 2006
208
{
Apr 29, 2007
Apr 29, 2007
209
const MojoArchiveEntry *entinfo;
Dec 3, 2006
Dec 3, 2006
210
211
while ((entinfo = ar->enumNext(ar)) != NULL)
{
May 4, 2007
May 4, 2007
212
if (strcmp(entinfo->filename, fname) == 0)
Dec 3, 2006
Dec 3, 2006
213
214
215
216
217
218
219
220
221
222
223
224
{
if (entinfo->type == MOJOARCHIVE_ENTRY_FILE)
retval = ar->openCurrentEntry(ar);
break;
} // if
} // while
} // if
return retval;
} // MojoInput_newFromArchivePath
Mar 26, 2006
Mar 26, 2006
225
Mar 25, 2006
Mar 25, 2006
226
227
// MojoInputs from files on the OS filesystem.
Mar 26, 2006
Mar 26, 2006
228
229
typedef struct
{
Sep 20, 2007
Sep 20, 2007
230
void *handle;
Mar 26, 2006
Mar 26, 2006
231
232
233
char *path;
} MojoInputFileInstance;
May 7, 2007
May 7, 2007
234
235
236
237
238
239
static boolean MojoInput_file_ready(MojoInput *io)
{
// !!! FIXME: select()? Does that help with network filesystems?
return true;
} // MojoInput_file_ready
Mar 26, 2006
Mar 26, 2006
240
static int64 MojoInput_file_read(MojoInput *io, void *buf, uint32 bufsize)
Mar 25, 2006
Mar 25, 2006
241
{
Mar 26, 2006
Mar 26, 2006
242
MojoInputFileInstance *inst = (MojoInputFileInstance *) io->opaque;
Sep 20, 2007
Sep 20, 2007
243
return MojoPlatform_read(inst->handle, buf, bufsize);
Mar 25, 2006
Mar 25, 2006
244
245
246
247
} // MojoInput_file_read
static boolean MojoInput_file_seek(MojoInput *io, uint64 pos)
{
Mar 26, 2006
Mar 26, 2006
248
MojoInputFileInstance *inst = (MojoInputFileInstance *) io->opaque;
Sep 20, 2007
Sep 20, 2007
249
return (MojoPlatform_seek(inst->handle, pos, MOJOSEEK_SET) == pos);
Mar 25, 2006
Mar 25, 2006
250
251
} // MojoInput_file_seek
Mar 26, 2006
Mar 26, 2006
252
static int64 MojoInput_file_tell(MojoInput *io)
Mar 25, 2006
Mar 25, 2006
253
{
Mar 26, 2006
Mar 26, 2006
254
MojoInputFileInstance *inst = (MojoInputFileInstance *) io->opaque;
Sep 20, 2007
Sep 20, 2007
255
return MojoPlatform_tell(inst->handle);
Mar 25, 2006
Mar 25, 2006
256
257
} // MojoInput_file_tell
Mar 26, 2006
Mar 26, 2006
258
259
260
static int64 MojoInput_file_length(MojoInput *io)
{
MojoInputFileInstance *inst = (MojoInputFileInstance *) io->opaque;
Sep 20, 2007
Sep 20, 2007
261
return MojoPlatform_flen(inst->handle);
Mar 26, 2006
Mar 26, 2006
262
263
264
265
266
267
268
269
} // MojoInput_file_length
static MojoInput *MojoInput_file_duplicate(MojoInput *io)
{
MojoInputFileInstance *inst = (MojoInputFileInstance *) io->opaque;
return MojoInput_newFromFile(inst->path);
} // MojoInput_file_duplicate
Mar 25, 2006
Mar 25, 2006
270
271
static void MojoInput_file_close(MojoInput *io)
{
Mar 26, 2006
Mar 26, 2006
272
MojoInputFileInstance *inst = (MojoInputFileInstance *) io->opaque;
Sep 20, 2007
Sep 20, 2007
273
MojoPlatform_close(inst->handle);
Mar 26, 2006
Mar 26, 2006
274
275
free(inst->path);
free(inst);
Mar 25, 2006
Mar 25, 2006
276
277
278
free(io);
} // MojoInput_file_close
May 3, 2007
May 3, 2007
279
MojoInput *MojoInput_newFromFile(const char *path)
Mar 25, 2006
Mar 25, 2006
280
{
Dec 13, 2006
Dec 13, 2006
281
MojoInput *io = NULL;
Sep 20, 2007
Sep 20, 2007
282
void *f = NULL;
Mar 26, 2006
Mar 26, 2006
283
Sep 20, 2007
Sep 20, 2007
284
f = MojoPlatform_open(path, MOJOFILE_READ, 0);
May 3, 2007
May 3, 2007
285
if (f != NULL)
Dec 14, 2006
Dec 14, 2006
286
{
May 3, 2007
May 3, 2007
287
288
289
290
291
292
MojoInputFileInstance *inst;
inst = (MojoInputFileInstance *) xmalloc(sizeof (MojoInputFileInstance));
inst->path = xstrdup(path);
inst->handle = f;
io = (MojoInput *) xmalloc(sizeof (MojoInput));
May 7, 2007
May 7, 2007
293
io->ready = MojoInput_file_ready;
May 3, 2007
May 3, 2007
294
295
296
297
298
299
300
io->read = MojoInput_file_read;
io->seek = MojoInput_file_seek;
io->tell = MojoInput_file_tell;
io->length = MojoInput_file_length;
io->duplicate = MojoInput_file_duplicate;
io->close = MojoInput_file_close;
io->opaque = inst;
Dec 14, 2006
Dec 14, 2006
301
} // if
Mar 25, 2006
Mar 25, 2006
302
303
304
305
306
return io;
} // MojoInput_newFromFile
Jan 13, 2008
Jan 13, 2008
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
// MojoInputs from blocks of memory.
typedef struct
{
void *ptr; // original pointer from xmalloc()
uint32 *refcount; // address in xmalloc()'d block for reference count.
const uint8 *data; // base of actual "file" data in xmalloc()'d block.
uint32 len; // size, in bytes, of "file" data.
uint32 pos; // current read position.
} MojoInputMemInstance;
static boolean MojoInput_memory_ready(MojoInput *io)
{
return true; // always ready!
} // MojoInput_memory_ready
static int64 MojoInput_memory_read(MojoInput *io, void *buf, uint32 bufsize)
{
MojoInputMemInstance *inst = (MojoInputMemInstance *) io->opaque;
const uint32 avail = inst->len - inst->pos;
if (bufsize > avail)
bufsize = avail;
memcpy(buf, inst->data + inst->pos, bufsize);
inst->pos += bufsize;
return bufsize;
} // MojoInput_memory_read
static boolean MojoInput_memory_seek(MojoInput *io, uint64 pos)
{
MojoInputMemInstance *inst = (MojoInputMemInstance *) io->opaque;
if (pos > (uint64) inst->len)
return false;
inst->pos = (uint32) pos;
return true;
} // MojoInput_memory_seek
static int64 MojoInput_memory_tell(MojoInput *io)
{
MojoInputMemInstance *inst = (MojoInputMemInstance *) io->opaque;
return (int64) inst->pos;
} // MojoInput_memory_tell
static int64 MojoInput_memory_length(MojoInput *io)
{
MojoInputMemInstance *inst = (MojoInputMemInstance *) io->opaque;
return (int64) inst->len;
} // MojoInput_memory_length
static MojoInput *MojoInput_memory_duplicate(MojoInput *io)
{
MojoInputMemInstance *srcinst = (MojoInputMemInstance *) io->opaque;
MojoInput *retval = NULL;
MojoInputMemInstance *inst = NULL;
if (srcinst->refcount != NULL)
{
// we don't copy the data for each duplicate; we just bump a reference
// counter. We free the data when all referencers are closed.
(*srcinst->refcount)++; // !!! FIXME: not thread safe!
} // if
inst = (MojoInputMemInstance*) xmalloc(sizeof (MojoInputMemInstance));
memcpy(inst, srcinst, sizeof (MojoInputMemInstance));
inst->pos = 0;
retval = (MojoInput *) xmalloc(sizeof (MojoInput));
memcpy(retval, io, sizeof (MojoInput));
retval->opaque = inst;
return retval;
} // MojoInput_memory_duplicate
static void MojoInput_memory_close(MojoInput *io)
{
MojoInputMemInstance *inst = (MojoInputMemInstance *) io->opaque;
if (inst->refcount != NULL) // memory we have to free?
{
assert(*inst->refcount > 0);
if (--(*inst->refcount) == 0) // !!! FIXME: not thread safe!
free(inst->ptr);
} // if
free(inst);
free(io);
} // MojoInput_memory_close
MojoInput *MojoInput_newFromMemory(const uint8 *ptr, uint32 len, int constant)
{
MojoInput *io = (MojoInput *) xmalloc(sizeof (MojoInput));
MojoInputMemInstance *inst = (MojoInputMemInstance*)
xmalloc(sizeof (MojoInputMemInstance));
if (constant)
inst->data = ptr;
else
{
inst->ptr = xmalloc(len + sizeof (uint32));
inst->refcount = (uint32 *) inst->ptr;
inst->data = ((const uint8 *) inst->ptr) + sizeof (uint32);
*inst->refcount = 1;
memcpy((void *) inst->data, ptr, len);
} // else
inst->len = len;
io->ready = MojoInput_memory_ready;
io->read = MojoInput_memory_read;
io->seek = MojoInput_memory_seek;
io->tell = MojoInput_memory_tell;
io->length = MojoInput_memory_length;
io->duplicate = MojoInput_memory_duplicate;
io->close = MojoInput_memory_close;
io->opaque = inst;
return io;
} // MojoInput_newFromMemory
Mar 25, 2006
Mar 25, 2006
429
430
// MojoArchives from directories on the OS filesystem.
Apr 29, 2007
Apr 29, 2007
431
typedef struct DirStack
Mar 25, 2006
Mar 25, 2006
432
{
Sep 20, 2007
Sep 20, 2007
433
void *dir;
Apr 29, 2007
Apr 29, 2007
434
435
436
437
char *basepath;
struct DirStack *next;
} DirStack;
Sep 20, 2007
Sep 20, 2007
438
static void pushDirStack(DirStack **_stack, const char *basepath, void *dir)
Apr 29, 2007
Apr 29, 2007
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
{
DirStack *stack = (DirStack *) xmalloc(sizeof (DirStack));
stack->dir = dir;
stack->basepath = xstrdup(basepath);
stack->next = *_stack;
*_stack = stack;
} // pushDirStack
static void popDirStack(DirStack **_stack)
{
DirStack *stack = *_stack;
if (stack != NULL)
{
DirStack *next = stack->next;
if (stack->dir)
Sep 20, 2007
Sep 20, 2007
454
MojoPlatform_closedir(stack->dir);
Apr 29, 2007
Apr 29, 2007
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
free(stack->basepath);
free(stack);
*_stack = next;
} // if
} // popDirStack
static void freeDirStack(DirStack **_stack)
{
while (*_stack)
popDirStack(_stack);
} // freeDirStack
typedef struct
{
DirStack *dirs;
Mar 25, 2006
Mar 25, 2006
471
char *base;
Mar 25, 2006
Mar 25, 2006
472
473
} MojoArchiveDirInstance;
May 4, 2007
May 4, 2007
474
static boolean MojoArchive_dir_enumerate(MojoArchive *ar)
Mar 25, 2006
Mar 25, 2006
475
476
{
MojoArchiveDirInstance *inst = (MojoArchiveDirInstance *) ar->opaque;
Sep 20, 2007
Sep 20, 2007
477
void *dir = NULL;
Mar 25, 2006
Mar 25, 2006
478
Apr 29, 2007
Apr 29, 2007
479
freeDirStack(&inst->dirs);
May 4, 2007
May 4, 2007
480
MojoArchive_resetEntry(&ar->prevEnum);
Apr 29, 2007
Apr 29, 2007
481
Sep 20, 2007
Sep 20, 2007
482
dir = MojoPlatform_opendir(inst->base);
Apr 29, 2007
Apr 29, 2007
483
if (dir != NULL)
May 4, 2007
May 4, 2007
484
pushDirStack(&inst->dirs, inst->base, dir);
Apr 29, 2007
Apr 29, 2007
485
486
return (dir != NULL);
Mar 25, 2006
Mar 25, 2006
487
488
489
} // MojoArchive_dir_enumerate
Apr 29, 2007
Apr 29, 2007
490
static const MojoArchiveEntry *MojoArchive_dir_enumNext(MojoArchive *ar)
Mar 25, 2006
Mar 25, 2006
491
{
Sep 20, 2007
Sep 20, 2007
492
uint16 perms = 0644; //(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Mar 25, 2006
Mar 25, 2006
493
char *fullpath = NULL;
Sep 20, 2007
Sep 20, 2007
494
char *dent = NULL; // "dent" == "directory entry"
Mar 25, 2006
Mar 25, 2006
495
MojoArchiveDirInstance *inst = (MojoArchiveDirInstance *) ar->opaque;
Sep 30, 2007
Sep 30, 2007
496
const char *basepath;
May 4, 2007
May 4, 2007
497
498
499
MojoArchive_resetEntry(&ar->prevEnum);
Apr 29, 2007
Apr 29, 2007
500
if (inst->dirs == NULL)
Mar 25, 2006
Mar 25, 2006
501
502
return NULL;
Sep 30, 2007
Sep 30, 2007
503
504
basepath = inst->dirs->basepath;
Sep 20, 2007
Sep 20, 2007
505
506
// if readdir fails, it's end of dir (!!! FIXME: what about i/o failures?)
dent = MojoPlatform_readdir(inst->dirs->dir);
Mar 25, 2006
Mar 25, 2006
507
508
if (dent == NULL) // end of dir?
{
Apr 29, 2007
Apr 29, 2007
509
510
popDirStack(&inst->dirs);
return MojoArchive_dir_enumNext(ar); // try higher level in tree.
Mar 25, 2006
Mar 25, 2006
511
512
} // if
Sep 20, 2007
Sep 20, 2007
513
514
// MojoPlatform layer shouldn't return "." or ".." paths.
assert((strcmp(dent, ".") != 0) && (strcmp(dent, "..") != 0));
Mar 25, 2006
Mar 25, 2006
515
Sep 20, 2007
Sep 20, 2007
516
517
518
fullpath = (char *) xmalloc(strlen(basepath) + strlen(dent) + 2);
sprintf(fullpath, "%s/%s", basepath, dent);
free(dent);
Apr 29, 2007
Apr 29, 2007
519
Sep 20, 2007
Sep 20, 2007
520
521
522
523
524
525
526
527
528
529
530
531
532
ar->prevEnum.filename = xstrdup(fullpath + strlen(inst->base) + 1);
ar->prevEnum.filesize = 0;
ar->prevEnum.type = MOJOARCHIVE_ENTRY_UNKNOWN;
// We currently force the perms from physical files, since CDs on
// Linux tend to mark every files as executable and read-only. If you
// want to install something with specific permissions, wrap it in a
// tarball, or use Setup.File.permissions, or return a permissions
// string from Setup.File.filter.
//MojoPlatform_perms(fullpath, &perms);
ar->prevEnum.perms = perms;
if (MojoPlatform_isfile(fullpath))
Mar 25, 2006
Mar 25, 2006
533
{
Sep 20, 2007
Sep 20, 2007
534
535
536
ar->prevEnum.type = MOJOARCHIVE_ENTRY_FILE;
ar->prevEnum.filesize = MojoPlatform_filesize(fullpath);
} // if
May 1, 2007
May 1, 2007
537
Sep 20, 2007
Sep 20, 2007
538
539
540
541
542
else if (MojoPlatform_issymlink(fullpath))
{
ar->prevEnum.type = MOJOARCHIVE_ENTRY_SYMLINK;
ar->prevEnum.linkdest = MojoPlatform_readlink(fullpath);
if (ar->prevEnum.linkdest == NULL)
May 1, 2007
May 1, 2007
543
{
Sep 20, 2007
Sep 20, 2007
544
545
546
547
free(fullpath);
return MojoArchive_dir_enumNext(ar);
} // if
} // else if
May 1, 2007
May 1, 2007
548
Sep 20, 2007
Sep 20, 2007
549
550
551
552
553
else if (MojoPlatform_isdir(fullpath))
{
void *dir = MojoPlatform_opendir(fullpath);
ar->prevEnum.type = MOJOARCHIVE_ENTRY_DIR;
if (dir == NULL)
Apr 29, 2007
Apr 29, 2007
554
{
Sep 20, 2007
Sep 20, 2007
555
556
557
558
559
560
561
562
563
564
565
free(fullpath);
return MojoArchive_dir_enumNext(ar);
} // if
// push this dir on the stack. Next enum will start there.
pushDirStack(&inst->dirs, fullpath, dir);
} // else if
else
{
assert(false && "possible file i/o error?");
Apr 29, 2007
Apr 29, 2007
566
} // else
Mar 25, 2006
Mar 25, 2006
567
May 4, 2007
May 4, 2007
568
free(fullpath);
Mar 26, 2006
Mar 26, 2006
569
return &ar->prevEnum;
Mar 25, 2006
Mar 25, 2006
570
571
572
573
574
} // MojoArchive_dir_enumNext
static MojoInput *MojoArchive_dir_openCurrentEntry(MojoArchive *ar)
{
Apr 29, 2007
Apr 29, 2007
575
MojoInput *retval = NULL;
Mar 25, 2006
Mar 25, 2006
576
MojoArchiveDirInstance *inst = (MojoArchiveDirInstance *) ar->opaque;
Apr 29, 2007
Apr 29, 2007
577
May 2, 2007
May 2, 2007
578
if ((inst->dirs != NULL) && (ar->prevEnum.type == MOJOARCHIVE_ENTRY_FILE))
Apr 29, 2007
Apr 29, 2007
579
{
May 4, 2007
May 4, 2007
580
581
582
char *fullpath = (char *) xmalloc(strlen(inst->base) +
strlen(ar->prevEnum.filename) + 2);
sprintf(fullpath, "%s/%s", inst->base, ar->prevEnum.filename);
Apr 29, 2007
Apr 29, 2007
583
retval = MojoInput_newFromFile(fullpath);
May 4, 2007
May 4, 2007
584
free(fullpath);
Apr 29, 2007
Apr 29, 2007
585
586
587
} // if
return retval;
Mar 25, 2006
Mar 25, 2006
588
589
590
591
592
593
} // MojoArchive_dir_openCurrentEntry
static void MojoArchive_dir_close(MojoArchive *ar)
{
MojoArchiveDirInstance *inst = (MojoArchiveDirInstance *) ar->opaque;
Apr 29, 2007
Apr 29, 2007
594
freeDirStack(&inst->dirs);
Mar 25, 2006
Mar 25, 2006
595
free(inst->base);
Mar 26, 2006
Mar 26, 2006
596
free(inst);
May 4, 2007
May 4, 2007
597
MojoArchive_resetEntry(&ar->prevEnum);
Mar 25, 2006
Mar 25, 2006
598
599
600
601
602
603
free(ar);
} // MojoArchive_dir_close
MojoArchive *MojoArchive_newFromDirectory(const char *dirname)
{
Dec 13, 2006
Dec 13, 2006
604
MojoArchive *ar = NULL;
Mar 25, 2006
Mar 25, 2006
605
MojoArchiveDirInstance *inst;
Apr 29, 2007
Apr 29, 2007
606
char *real = MojoPlatform_realpath(dirname);
Dec 14, 2006
Dec 14, 2006
607
Sep 20, 2007
Sep 20, 2007
608
609
610
611
612
613
614
if (real == NULL)
return NULL;
if (!MojoPlatform_exists(real, NULL))
return NULL;
if (!MojoPlatform_isdir(real))
Mar 25, 2006
Mar 25, 2006
615
616
617
return NULL;
inst = (MojoArchiveDirInstance *) xmalloc(sizeof (MojoArchiveDirInstance));
Apr 29, 2007
Apr 29, 2007
618
inst->base = real;
Dec 13, 2006
Dec 13, 2006
619
ar = (MojoArchive *) xmalloc(sizeof (MojoArchive));
Mar 25, 2006
Mar 25, 2006
620
621
622
623
ar->enumerate = MojoArchive_dir_enumerate;
ar->enumNext = MojoArchive_dir_enumNext;
ar->openCurrentEntry = MojoArchive_dir_openCurrentEntry;
ar->close = MojoArchive_dir_close;
Jan 16, 2008
Jan 16, 2008
624
ar->offsetOfStart = -1; // doesn't mean anything here.
Mar 25, 2006
Mar 25, 2006
625
ar->opaque = inst;
Mar 25, 2006
Mar 25, 2006
626
627
628
return ar;
} // MojoArchive_newFromDirectory
Mar 25, 2006
Mar 25, 2006
629
630
Mar 26, 2006
Mar 26, 2006
631
Mar 25, 2006
Mar 25, 2006
632
MojoArchive *GBaseArchive = NULL;
May 20, 2007
May 20, 2007
633
const char *GBaseArchivePath = NULL;
Mar 25, 2006
Mar 25, 2006
634
635
636
MojoArchive *MojoArchive_initBaseArchive(void)
{
May 20, 2007
May 20, 2007
637
638
639
640
char *basepath = NULL;
const char *cmd = NULL;
MojoInput *io = NULL;
Mar 25, 2006
Mar 25, 2006
641
if (GBaseArchive != NULL)
May 20, 2007
May 20, 2007
642
643
644
645
return GBaseArchive; // already initialized.
if ((cmd = cmdlinestr("base", "MOJOSETUP_BASE", NULL)) != NULL)
{
Sep 20, 2007
Sep 20, 2007
646
647
char *real = MojoPlatform_realpath(cmd);
if (real != NULL)
May 20, 2007
May 20, 2007
648
{
Sep 20, 2007
Sep 20, 2007
649
650
651
652
653
654
655
656
if (MojoPlatform_isdir(real))
GBaseArchive = MojoArchive_newFromDirectory(real);
else
{
io = MojoInput_newFromFile(real);
if (io != NULL)
GBaseArchive = MojoArchive_newFromInput(io, real);
} // else
May 20, 2007
May 20, 2007
657
Sep 20, 2007
Sep 20, 2007
658
659
660
661
662
if (GBaseArchive != NULL)
basepath = real;
else
free(real);
} // if
May 20, 2007
May 20, 2007
663
664
} // else if
Mar 25, 2006
Mar 25, 2006
665
666
else
{
May 20, 2007
May 20, 2007
667
668
basepath = MojoPlatform_appBinaryPath();
io = MojoInput_newFromFile(basepath);
Mar 25, 2006
Mar 25, 2006
669
670
if (io != NULL)
May 5, 2007
May 5, 2007
671
GBaseArchive = MojoArchive_newFromInput(io, basepath);
Mar 25, 2006
Mar 25, 2006
672
673
if (GBaseArchive == NULL)
Dec 10, 2006
Dec 10, 2006
674
675
676
677
678
679
{
// Just use the same directory as the binary instead.
char *ptr = strrchr(basepath, '/');
if (ptr != NULL)
*ptr = '\0';
else
May 20, 2007
May 20, 2007
680
681
682
683
684
{
free(basepath); // oh well, try cwd.
basepath = MojoPlatform_currentWorkingDir();
} // else
GBaseArchive = MojoArchive_newFromDirectory(basepath);
May 10, 2007
May 10, 2007
685
686
// !!! FIXME: failing this, maybe default.mojosetup?
Dec 10, 2006
Dec 10, 2006
687
} // if
Mar 25, 2006
Mar 25, 2006
688
689
} // else
May 20, 2007
May 20, 2007
690
691
692
693
694
695
696
if (GBaseArchive == NULL)
{
free(basepath);
basepath = NULL;
} // if
GBaseArchivePath = basepath;
Mar 25, 2006
Mar 25, 2006
697
698
699
700
701
702
703
704
705
706
707
return GBaseArchive;
} // MojoArchive_initBaseArchive
void MojoArchive_deinitBaseArchive(void)
{
if (GBaseArchive != NULL)
{
GBaseArchive->close(GBaseArchive);
GBaseArchive = NULL;
} // if
May 20, 2007
May 20, 2007
708
709
710
free((void *) GBaseArchivePath);
GBaseArchivePath = NULL;
Mar 25, 2006
Mar 25, 2006
711
712
} // MojoArchive_deinitBaseArchive
May 6, 2007
May 6, 2007
713
714
715
// This stub is here if we didn't compile in libfetch...
#if !SUPPORT_URL_HTTP && !SUPPORT_URL_FTP
Jan 17, 2008
Jan 17, 2008
716
MojoInput *MojoInput_newFromURL(const char *url)
May 6, 2007
May 6, 2007
717
{
Jan 15, 2008
Jan 15, 2008
718
logError("No networking support in this build.");
May 6, 2007
May 6, 2007
719
return NULL;
Jan 17, 2008
Jan 17, 2008
720
} // MojoInput_newFromURL
May 6, 2007
May 6, 2007
721
722
#endif
723
// end of fileio.c ...