Skip to content

Latest commit

 

History

History
736 lines (581 loc) · 21.8 KB

lzma.c

File metadata and controls

736 lines (581 loc) · 21.8 KB
 
1
2
3
/*
* LZMA support routines for PhysicsFS.
*
Jan 23, 2008
Jan 23, 2008
4
* Please see the file lzma.txt in the lzma/ directory.
Jan 23, 2008
Jan 23, 2008
6
* This file was written by Dennis Schridde, with some peeking at "7zMain.c"
7
8
9
* by Igor Pavlov.
*/
Mar 9, 2007
Mar 9, 2007
10
#if (defined PHYSFS_SUPPORTS_7Z)
11
12
13
#include <stdlib.h>
#include <string.h>
Jan 23, 2008
Jan 23, 2008
14
#include <time.h>
15
16
17
18
19
20
#include "physfs.h"
#define __PHYSICSFS_INTERNAL__
#include "physfs_internal.h"
Jan 23, 2008
Jan 23, 2008
21
22
23
#include "lzma/C/7zCrc.h"
#include "lzma/C/Archive/7z/7zIn.h"
#include "lzma/C/Archive/7z/7zExtract.h"
Sep 27, 2006
Sep 27, 2006
24
25
Jan 23, 2008
Jan 23, 2008
26
27
/* 7z internal from 7zIn.c */
extern int TestSignatureCandidate(Byte *testBytes);
Sep 27, 2006
Sep 27, 2006
28
29
Jan 23, 2008
Jan 23, 2008
30
31
32
#ifdef _LZMA_IN_CB
# define BUFFER_SIZE (1 << 12)
#endif /* _LZMA_IN_CB */
Sep 27, 2006
Sep 27, 2006
33
Jan 23, 2008
Jan 23, 2008
35
36
37
38
/*
* Carries filestream metadata through 7z
*/
typedef struct _FileInputStream
Jan 23, 2008
Jan 23, 2008
40
41
42
43
44
45
46
47
ISzAlloc allocImp; /* Allocation implementation, used by 7z */
ISzAlloc allocTempImp; /* Temporary allocation implementation, used by 7z */
ISzInStream inStream; /* Input stream with read callbacks, used by 7z */
void *file; /* Filehandle, used by read implementation */
#ifdef _LZMA_IN_CB
Byte buffer[BUFFER_SIZE]; /* Buffer, used by read implementation */
#endif /* _LZMA_IN_CB */
} FileInputStream;
Nov 5, 2006
Nov 5, 2006
49
/*
Jan 23, 2008
Jan 23, 2008
50
* In the 7z format archives are splited into blocks, those are called folders
Nov 5, 2006
Nov 5, 2006
51
52
53
54
55
56
* Set by LZMA_read()
*/
typedef struct _LZMAfolder
{
PHYSFS_uint32 index; /* Index of folder in archive */
PHYSFS_uint32 references; /* Number of files using this block */
Jan 23, 2008
Jan 23, 2008
57
58
PHYSFS_uint8 *cache; /* Cached folder */
size_t size; /* Size of folder */
Nov 5, 2006
Nov 5, 2006
59
60
61
62
63
64
} LZMAfolder;
/*
* Set by LZMA_openArchive(), except folder which gets it's values
* in LZMA_read()
*/
Sep 27, 2006
Sep 27, 2006
65
typedef struct _LZMAarchive
Jan 23, 2008
Jan 23, 2008
67
68
struct _LZMAfile *files; /* Array of files, size == archive->db.Database.NumFiles */
LZMAfolder *folders; /* Array of folders, size == archive->db.Database.NumFolders */
Sep 27, 2006
Sep 27, 2006
69
CArchiveDatabaseEx db; /* For 7z: Database */
Jan 23, 2008
Jan 23, 2008
70
FileInputStream stream; /* For 7z: Input file incl. read and seek callbacks */
Jan 23, 2008
Jan 23, 2008
73
74
/* Set by LZMA_openArchive(), except offset which is set by LZMA_read() */
typedef struct _LZMAfile
Jan 23, 2008
Jan 23, 2008
76
PHYSFS_uint32 index; /* Index of file in archive */
Sep 27, 2006
Sep 27, 2006
77
LZMAarchive *archive; /* Link to corresponding archive */
Jan 23, 2008
Jan 23, 2008
78
79
LZMAfolder *folder; /* Link to corresponding folder */
CFileItem *item; /* For 7z: File info, eg. name, size */
Nov 5, 2006
Nov 5, 2006
80
size_t offset; /* Offset in folder */
Jan 23, 2008
Jan 23, 2008
81
82
size_t position; /* Current "virtual" position in file */
} LZMAfile;
Sep 27, 2006
Sep 27, 2006
85
86
/* Memory management implementations to be passed to 7z */
87
88
89
90
91
92
93
94
95
96
97
98
99
static void *SzAllocPhysicsFS(size_t size)
{
return ((size == 0) ? NULL : allocator.Malloc(size));
} /* SzAllocPhysicsFS */
static void SzFreePhysicsFS(void *address)
{
if (address != NULL)
allocator.Free(address);
} /* SzFreePhysicsFS */
Sep 27, 2006
Sep 27, 2006
100
101
102
103
/* Filesystem implementations to be passed to 7z */
#ifdef _LZMA_IN_CB
Jan 23, 2008
Jan 23, 2008
104
105
106
107
/*
* Read implementation, to be passed to 7z
* WARNING: If the ISzInStream in 'object' is not contained in a valid FileInputStream this _will_ break horribly!
*/
Sep 27, 2006
Sep 27, 2006
108
109
SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxReqSize,
size_t *processedSize)
Jan 28, 2010
Jan 28, 2010
111
FileInputStream *s = (FileInputStream *)(object - offsetof(FileInputStream, inStream)); /* HACK! */
Jan 23, 2008
Jan 23, 2008
112
113
114
115
116
117
PHYSFS_sint64 processedSizeLoc = 0;
if (maxReqSize > BUFFER_SIZE)
maxReqSize = BUFFER_SIZE;
processedSizeLoc = __PHYSFS_platformRead(s->file, s->buffer, 1, maxReqSize);
*buffer = s->buffer;
Mar 19, 2007
Mar 19, 2007
118
119
if (processedSize != NULL)
*processedSize = (size_t) processedSizeLoc;
Jan 23, 2008
Jan 23, 2008
120
Sep 27, 2006
Sep 27, 2006
121
122
123
124
return SZ_OK;
} /* SzFileReadImp */
#else
Jan 23, 2008
Jan 23, 2008
126
127
128
129
/*
* Read implementation, to be passed to 7z
* WARNING: If the ISzInStream in 'object' is not contained in a valid FileInputStream this _will_ break horribly!
*/
Sep 27, 2006
Sep 27, 2006
130
131
132
SZ_RESULT SzFileReadImp(void *object, void *buffer, size_t size,
size_t *processedSize)
{
Jan 28, 2010
Jan 28, 2010
133
FileInputStream *s = (FileInputStream *)((unsigned long)object - offsetof(FileInputStream, inStream)); /* HACK! */
Jan 23, 2008
Jan 23, 2008
134
size_t processedSizeLoc = __PHYSFS_platformRead(s->file, buffer, 1, size);
Sep 27, 2006
Sep 27, 2006
135
136
if (processedSize != 0)
*processedSize = processedSizeLoc;
137
138
139
return SZ_OK;
} /* SzFileReadImp */
Sep 27, 2006
Sep 27, 2006
140
#endif
Jan 23, 2008
Jan 23, 2008
142
143
144
145
/*
* Seek implementation, to be passed to 7z
* WARNING: If the ISzInStream in 'object' is not contained in a valid FileInputStream this _will_ break horribly!
*/
146
147
SZ_RESULT SzFileSeekImp(void *object, CFileSize pos)
{
Jan 28, 2010
Jan 28, 2010
148
FileInputStream *s = (FileInputStream *)((unsigned long)object - offsetof(FileInputStream, inStream)); /* HACK! */
Jan 23, 2008
Jan 23, 2008
149
if (__PHYSFS_platformSeek(s->file, (PHYSFS_uint64) pos))
150
151
152
153
154
return SZ_OK;
return SZE_FAIL;
} /* SzFileSeekImp */
Sep 27, 2006
Sep 27, 2006
155
/*
Jan 23, 2008
Jan 23, 2008
156
* Translate Microsoft FILETIME (used by 7zip) into UNIX timestamp
Sep 27, 2006
Sep 27, 2006
157
*/
Jan 23, 2008
Jan 23, 2008
158
static PHYSFS_sint64 lzma_filetime_to_unix_timestamp(CArchiveFileTime *ft)
Jan 23, 2008
Jan 23, 2008
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/* MS counts in nanoseconds ... */
const PHYSFS_uint64 FILETIME_NANOTICKS_PER_SECOND = __PHYSFS_UI64(10000000);
/* MS likes to count seconds since 01.01.1601 ... */
const PHYSFS_uint64 FILETIME_UNIX_DIFF = __PHYSFS_UI64(11644473600);
PHYSFS_uint64 filetime = ft->Low | ((PHYSFS_uint64)ft->High << 32);
return filetime/FILETIME_NANOTICKS_PER_SECOND - FILETIME_UNIX_DIFF;
} /* lzma_filetime_to_unix_timestamp */
/*
* Compare a file with a given name, C89 stdlib variant
* Used for sorting
*/
static int lzma_file_cmp_stdlib(const void *key, const void *object)
{
const char *name = (const char *) key;
LZMAfile *file = (LZMAfile *) object;
return(strcmp(name, file->item->Name));
} /* lzma_file_cmp_posix */
Jan 23, 2008
Jan 23, 2008
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
/*
* Compare two files with each other based on the name
* Used for sorting
*/
static int lzma_file_cmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
{
LZMAfile *files = (LZMAfile *) _a;
return(strcmp(files[one].item->Name, files[two].item->Name));
} /* lzma_file_cmp */
/*
* Swap two entries in the file array
*/
static void lzma_file_swap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
{
LZMAfile tmp;
LZMAfile *first = &(((LZMAfile *) _a)[one]);
LZMAfile *second = &(((LZMAfile *) _a)[two]);
memcpy(&tmp, first, sizeof (LZMAfile));
memcpy(first, second, sizeof (LZMAfile));
memcpy(second, &tmp, sizeof (LZMAfile));
} /* lzma_file_swap */
/*
* Find entry 'name' in 'archive'
*/
static LZMAfile * lzma_find_file(LZMAarchive *archive, const char *name)
{
Jan 28, 2010
Jan 28, 2010
212
LZMAfile *file = bsearch(name, archive->files, archive->db.Database.NumFiles, sizeof(*archive->files), lzma_file_cmp_stdlib); /* FIXME: Should become __PHYSFS_search!!! */
Jan 23, 2008
Jan 23, 2008
213
214
215
216
217
BAIL_IF_MACRO(file == NULL, ERR_NO_SUCH_FILE, NULL);
return(file);
} /* lzma_find_file */
Sep 27, 2006
Sep 27, 2006
220
/*
Jan 23, 2008
Jan 23, 2008
221
* Load metadata for the file at given index
Sep 27, 2006
Sep 27, 2006
222
*/
Jan 23, 2008
Jan 23, 2008
223
static int lzma_file_init(LZMAarchive *archive, PHYSFS_uint32 fileIndex)
Jan 23, 2008
Jan 23, 2008
225
226
227
LZMAfile *file = &archive->files[fileIndex];
PHYSFS_uint32 folderIndex = archive->db.FileIndexToFolderIndexMap[fileIndex];
Jan 28, 2010
Jan 28, 2010
228
file->index = fileIndex; /* Store index into 7z array, since we sort our own. */
Jan 23, 2008
Jan 23, 2008
229
file->archive = archive;
Jan 28, 2010
Jan 28, 2010
230
231
file->folder = (folderIndex != (PHYSFS_uint32)-1 ? &archive->folders[folderIndex] : NULL); /* Directories don't have a folder (they contain no own data...) */
file->item = &archive->db.Database.Files[fileIndex]; /* Holds crucial data and is often referenced -> Store link */
Jan 23, 2008
Jan 23, 2008
232
233
234
235
236
file->position = 0;
file->offset = 0; /* Offset will be set by LZMA_read() */
return(1);
} /* lzma_load_file */
Jan 23, 2008
Jan 23, 2008
239
240
241
242
243
244
/*
* Load metadata for all files
*/
static int lzma_files_init(LZMAarchive *archive)
{
PHYSFS_uint32 fileIndex = 0, numFiles = archive->db.Database.NumFiles;
Jan 23, 2008
Jan 23, 2008
246
for (fileIndex = 0; fileIndex < numFiles; fileIndex++ )
Jan 23, 2008
Jan 23, 2008
248
if (!lzma_file_init(archive, fileIndex))
Jan 28, 2010
Jan 28, 2010
250
return(0); /* FALSE on failure */
Jan 23, 2008
Jan 23, 2008
251
252
253
254
255
256
257
}
} /* for */
__PHYSFS_sort(archive->files, numFiles, lzma_file_cmp, lzma_file_swap);
return(1);
} /* lzma_load_files */
Jan 23, 2008
Jan 23, 2008
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
/*
* Initialise specified archive
*/
static void lzma_archive_init(LZMAarchive *archive)
{
memset(archive, 0, sizeof(*archive));
/* Prepare callbacks for 7z */
archive->stream.inStream.Read = SzFileReadImp;
archive->stream.inStream.Seek = SzFileSeekImp;
archive->stream.allocImp.Alloc = SzAllocPhysicsFS;
archive->stream.allocImp.Free = SzFreePhysicsFS;
archive->stream.allocTempImp.Alloc = SzAllocPhysicsFS;
archive->stream.allocTempImp.Free = SzFreePhysicsFS;
}
/*
* Deinitialise archive
*/
static void lzma_archive_exit(LZMAarchive *archive)
{
/* Free arrays */
allocator.Free(archive->folders);
allocator.Free(archive->files);
allocator.Free(archive);
}
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
/*
* Wrap all 7z calls in this, so the physfs error state is set appropriately.
*/
static int lzma_err(SZ_RESULT rc)
{
switch (rc)
{
case SZ_OK: /* Same as LZMA_RESULT_OK */
break;
case SZE_DATA_ERROR: /* Same as LZMA_RESULT_DATA_ERROR */
__PHYSFS_setError(ERR_DATA_ERROR);
break;
case SZE_OUTOFMEMORY:
__PHYSFS_setError(ERR_OUT_OF_MEMORY);
break;
case SZE_CRC_ERROR:
__PHYSFS_setError(ERR_CORRUPTED);
break;
case SZE_NOTIMPL:
__PHYSFS_setError(ERR_NOT_IMPLEMENTED);
break;
case SZE_FAIL:
__PHYSFS_setError(ERR_UNKNOWN_ERROR); /* !!! FIXME: right? */
break;
case SZE_ARCHIVE_ERROR:
__PHYSFS_setError(ERR_CORRUPTED); /* !!! FIXME: right? */
break;
default:
__PHYSFS_setError(ERR_UNKNOWN_ERROR);
} /* switch */
return(rc);
} /* lzma_err */
static PHYSFS_sint64 LZMA_read(fvoid *opaque, void *outBuffer,
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
{
Jan 23, 2008
Jan 23, 2008
328
LZMAfile *file = (LZMAfile *) opaque;
Jan 23, 2008
Jan 23, 2008
330
331
332
size_t wantedSize = objSize*objCount;
size_t remainingSize = file->item->Size - file->position;
size_t fileSize = 0;
Mar 12, 2007
Mar 12, 2007
333
Sep 27, 2006
Sep 27, 2006
334
335
BAIL_IF_MACRO(wantedSize == 0, NULL, 0); /* quick rejection. */
BAIL_IF_MACRO(remainingSize == 0, ERR_PAST_EOF, 0);
Sep 27, 2006
Sep 27, 2006
337
if (remainingSize < wantedSize)
Sep 27, 2006
Sep 27, 2006
339
340
wantedSize = remainingSize - (remainingSize % objSize);
objCount = (PHYSFS_uint32) (remainingSize / objSize);
341
BAIL_IF_MACRO(objCount == 0, ERR_PAST_EOF, 0); /* quick rejection. */
Sep 27, 2006
Sep 27, 2006
342
__PHYSFS_setError(ERR_PAST_EOF); /* this is always true here. */
Nov 5, 2006
Nov 5, 2006
345
/* Only decompress the folder if it is not allready cached */
Jan 23, 2008
Jan 23, 2008
346
if (file->folder->cache == NULL)
Mar 10, 2007
Mar 10, 2007
347
348
{
int rc = lzma_err(SzExtract(
Jan 23, 2008
Jan 23, 2008
349
350
351
&file->archive->stream.inStream, /* compressed data */
&file->archive->db, /* 7z's database, containing everything */
file->index, /* Index into database arrays */
Nov 5, 2006
Nov 5, 2006
352
/* Index of cached folder, will be changed by SzExtract */
Jan 23, 2008
Jan 23, 2008
353
&file->folder->index,
Nov 5, 2006
Nov 5, 2006
354
/* Cache for decompressed folder, allocated/freed by SzExtract */
Jan 23, 2008
Jan 23, 2008
355
&file->folder->cache,
Nov 5, 2006
Nov 5, 2006
356
/* Size of cache, will be changed by SzExtract */
Jan 23, 2008
Jan 23, 2008
357
&file->folder->size,
Nov 5, 2006
Nov 5, 2006
358
/* Offset of this file inside the cache, set by SzExtract */
Jan 23, 2008
Jan 23, 2008
359
&file->offset,
Nov 5, 2006
Nov 5, 2006
360
&fileSize, /* Size of this file */
Jan 23, 2008
Jan 23, 2008
361
362
&file->archive->stream.allocImp,
&file->archive->stream.allocTempImp));
Mar 10, 2007
Mar 10, 2007
363
364
if (rc != SZ_OK)
Nov 5, 2006
Nov 5, 2006
365
return -1;
Mar 10, 2007
Mar 10, 2007
366
} /* if */
Sep 27, 2006
Sep 27, 2006
367
368
/* Copy wanted bytes over from cache to outBuffer */
Jan 23, 2008
Jan 23, 2008
369
370
371
372
373
374
memcpy(outBuffer,
(file->folder->cache +
file->offset + file->position),
wantedSize);
file->position += wantedSize; /* Increase virtual position */
Sep 27, 2006
Sep 27, 2006
375
return objCount;
376
377
378
379
380
381
382
383
384
385
386
387
} /* LZMA_read */
static PHYSFS_sint64 LZMA_write(fvoid *opaque, const void *buf,
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
} /* LZMA_write */
static int LZMA_eof(fvoid *opaque)
{
Jan 23, 2008
Jan 23, 2008
388
389
LZMAfile *file = (LZMAfile *) opaque;
return (file->position >= file->item->Size);
390
391
392
393
394
} /* LZMA_eof */
static PHYSFS_sint64 LZMA_tell(fvoid *opaque)
{
Jan 23, 2008
Jan 23, 2008
395
396
LZMAfile *file = (LZMAfile *) opaque;
return (file->position);
397
398
399
400
401
} /* LZMA_tell */
static int LZMA_seek(fvoid *opaque, PHYSFS_uint64 offset)
{
Jan 23, 2008
Jan 23, 2008
402
LZMAfile *file = (LZMAfile *) opaque;
403
404
BAIL_IF_MACRO(offset < 0, ERR_SEEK_OUT_OF_RANGE, 0);
Jan 23, 2008
Jan 23, 2008
405
406
407
BAIL_IF_MACRO(offset > file->item->Size, ERR_PAST_EOF, 0);
file->position = offset; /* We only use a virtual position... */
Sep 27, 2006
Sep 27, 2006
409
return 1;
410
411
412
413
414
} /* LZMA_seek */
static PHYSFS_sint64 LZMA_fileLength(fvoid *opaque)
{
Jan 23, 2008
Jan 23, 2008
415
416
LZMAfile *file = (LZMAfile *) opaque;
return (file->item->Size);
417
418
419
420
421
} /* LZMA_fileLength */
static int LZMA_fileClose(fvoid *opaque)
{
Jan 23, 2008
Jan 23, 2008
422
LZMAfile *file = (LZMAfile *) opaque;
Jan 23, 2008
Jan 23, 2008
424
BAIL_IF_MACRO(file->folder == NULL, ERR_NOT_A_FILE, 0);
Jan 23, 2008
Jan 23, 2008
426
427
428
429
/* Only decrease refcount if someone actually requested this file... Prevents from overflows and close-on-open... */
if (file->folder->references > 0)
file->folder->references--;
if (file->folder->references == 0)
Nov 5, 2006
Nov 5, 2006
430
{
Jan 23, 2008
Jan 23, 2008
431
432
433
/* Free the cache which might have been allocated by LZMA_read() */
allocator.Free(file->folder->cache);
file->folder->cache = NULL;
Nov 5, 2006
Nov 5, 2006
434
435
}
436
437
438
439
440
441
442
443
444
445
446
447
448
449
return(1);
} /* LZMA_fileClose */
static int LZMA_isArchive(const char *filename, int forWriting)
{
PHYSFS_uint8 sig[k7zSignatureSize];
void *in;
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0);
in = __PHYSFS_platformOpenRead(filename);
BAIL_IF_MACRO(in == NULL, NULL, 0);
Jan 23, 2008
Jan 23, 2008
450
/* Read signature bytes */
451
if (__PHYSFS_platformRead(in, sig, k7zSignatureSize, 1) != 1)
Jan 23, 2008
Jan 23, 2008
452
{
Jan 28, 2010
Jan 28, 2010
453
__PHYSFS_platformClose(in); /* Don't forget to close the file before returning... */
454
BAIL_MACRO(NULL, 0);
Jan 23, 2008
Jan 23, 2008
455
}
Sep 27, 2006
Sep 27, 2006
456
457
458
__PHYSFS_platformClose(in);
Jan 23, 2008
Jan 23, 2008
459
460
/* Test whether sig is the 7z signature */
return(TestSignatureCandidate(sig));
461
462
463
464
465
} /* LZMA_isArchive */
static void *LZMA_openArchive(const char *name, int forWriting)
{
Jan 23, 2008
Jan 23, 2008
466
size_t len = 0;
Sep 27, 2006
Sep 27, 2006
467
LZMAarchive *archive = NULL;
468
469
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, NULL);
Nov 5, 2006
Nov 5, 2006
470
BAIL_IF_MACRO(!LZMA_isArchive(name,forWriting), ERR_UNSUPPORTED_ARCHIVE, 0);
Sep 27, 2006
Sep 27, 2006
471
472
473
474
archive = (LZMAarchive *) allocator.Malloc(sizeof (LZMAarchive));
BAIL_IF_MACRO(archive == NULL, ERR_OUT_OF_MEMORY, NULL);
Jan 23, 2008
Jan 23, 2008
475
lzma_archive_init(archive);
Jan 23, 2008
Jan 23, 2008
477
if ( (archive->stream.file = __PHYSFS_platformOpenRead(name)) == NULL )
Jan 23, 2008
Jan 23, 2008
479
480
__PHYSFS_platformClose(archive->stream.file);
lzma_archive_exit(archive);
Jan 28, 2010
Jan 28, 2010
481
return(NULL); /* Error is set by platformOpenRead! */
Jan 23, 2008
Jan 23, 2008
482
}
Jan 23, 2008
Jan 23, 2008
484
CrcGenerateTable();
485
SzArDbExInit(&archive->db);
Jan 23, 2008
Jan 23, 2008
486
487
488
489
if (lzma_err(SzArchiveOpen(&archive->stream.inStream,
&archive->db,
&archive->stream.allocImp,
&archive->stream.allocTempImp)) != SZ_OK)
Jan 23, 2008
Jan 23, 2008
491
492
493
SzArDbExFree(&archive->db, SzFreePhysicsFS);
__PHYSFS_platformClose(archive->stream.file);
lzma_archive_exit(archive);
Jan 28, 2010
Jan 28, 2010
494
return NULL; /* Error is set by lzma_err! */
Jan 23, 2008
Jan 23, 2008
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
len = archive->db.Database.NumFiles * sizeof (LZMAfile);
archive->files = (LZMAfile *) allocator.Malloc(len);
if (archive->files == NULL)
{
SzArDbExFree(&archive->db, SzFreePhysicsFS);
__PHYSFS_platformClose(archive->stream.file);
lzma_archive_exit(archive);
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
}
/*
* Init with 0 so we know when a folder is already cached
* Values will be set by LZMA_openRead()
*/
memset(archive->files, 0, len);
Nov 5, 2006
Nov 5, 2006
513
len = archive->db.Database.NumFolders * sizeof (LZMAfolder);
Jan 23, 2008
Jan 23, 2008
514
515
516
517
518
519
520
521
archive->folders = (LZMAfolder *) allocator.Malloc(len);
if (archive->folders == NULL)
{
SzArDbExFree(&archive->db, SzFreePhysicsFS);
__PHYSFS_platformClose(archive->stream.file);
lzma_archive_exit(archive);
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
}
Nov 5, 2006
Nov 5, 2006
522
523
524
525
526
/*
* Init with 0 so we know when a folder is already cached
* Values will be set by LZMA_read()
*/
Jan 23, 2008
Jan 23, 2008
527
528
529
530
531
532
533
534
535
memset(archive->folders, 0, len);
if(!lzma_files_init(archive))
{
SzArDbExFree(&archive->db, SzFreePhysicsFS);
__PHYSFS_platformClose(archive->stream.file);
lzma_archive_exit(archive);
BAIL_MACRO(ERR_UNKNOWN_ERROR, NULL);
}
Nov 5, 2006
Nov 5, 2006
536
537
538
539
540
541
542
543
544
545
return(archive);
} /* LZMA_openArchive */
/*
* Moved to seperate function so we can use alloca then immediately throw
* away the allocated stack space...
*/
static void doEnumCallback(PHYSFS_EnumFilesCallback cb, void *callbackdata,
Jan 23, 2008
Jan 23, 2008
546
const char *odir, const char *str, size_t flen)
Jan 23, 2008
Jan 23, 2008
548
char *newstr = __PHYSFS_smallAlloc(flen + 1);
549
550
551
if (newstr == NULL)
return;
Jan 23, 2008
Jan 23, 2008
552
553
memcpy(newstr, str, flen);
newstr[flen] = '\0';
554
cb(callbackdata, odir, newstr);
Mar 24, 2007
Mar 24, 2007
555
__PHYSFS_smallFree(newstr);
556
557
558
559
560
561
562
} /* doEnumCallback */
static void LZMA_enumerateFiles(dvoid *opaque, const char *dname,
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
const char *origdir, void *callbackdata)
{
Jan 23, 2008
Jan 23, 2008
563
564
size_t dlen = strlen(dname),
dlen_inc = dlen + ((dlen > 0) ? 1 : 0);
565
LZMAarchive *archive = (LZMAarchive *) opaque;
Feb 2, 2008
Feb 2, 2008
566
567
568
569
570
LZMAfile *file = NULL,
*lastFile = &archive->files[archive->db.Database.NumFiles];
if (dlen)
{
file = lzma_find_file(archive, dname);
Jan 28, 2010
Jan 28, 2010
571
if (file != NULL) /* if 'file' is NULL it should stay so, otherwise errors will not be handled */
Feb 2, 2008
Feb 2, 2008
572
573
574
575
576
577
file += 1;
}
else
{
file = archive->files;
}
Jan 23, 2008
Jan 23, 2008
579
BAIL_IF_MACRO(file == NULL, ERR_NO_SUCH_FILE, );
Jan 23, 2008
Jan 23, 2008
581
while (file < lastFile)
Jan 23, 2008
Jan 23, 2008
583
584
585
586
587
588
589
const char * fname = file->item->Name;
const char * dirNameEnd = fname + dlen_inc;
if (strncmp(dname, fname, dlen) != 0) /* Stop after mismatch, archive->files is sorted */
break;
if (strchr(dirNameEnd, '/')) /* Skip subdirs */
Jan 23, 2008
Jan 23, 2008
591
592
593
594
595
596
597
598
599
file++;
continue;
}
/* Do the actual callback... */
doEnumCallback(cb, callbackdata, origdir, dirNameEnd, strlen(dirNameEnd));
file++;
}
600
601
602
603
604
} /* LZMA_enumerateFiles */
static int LZMA_exists(dvoid *opaque, const char *name)
{
Sep 27, 2006
Sep 27, 2006
605
LZMAarchive *archive = (LZMAarchive *) opaque;
Jan 23, 2008
Jan 23, 2008
606
return(lzma_find_file(archive, name) != NULL);
607
608
609
610
} /* LZMA_exists */
static PHYSFS_sint64 LZMA_getLastModTime(dvoid *opaque,
Sep 27, 2006
Sep 27, 2006
611
612
const char *name,
int *fileExists)
Jan 23, 2008
Jan 23, 2008
614
615
616
617
618
619
LZMAarchive *archive = (LZMAarchive *) opaque;
LZMAfile *file = lzma_find_file(archive, name);
*fileExists = (file != NULL);
BAIL_IF_MACRO(file == NULL, NULL, -1);
Jan 28, 2010
Jan 28, 2010
620
BAIL_IF_MACRO(!file->item->IsLastWriteTimeDefined, NULL, -1); /* write-time may not be defined for every file */
Jan 23, 2008
Jan 23, 2008
621
622
return(lzma_filetime_to_unix_timestamp(&file->item->LastWriteTime));
623
624
625
626
627
} /* LZMA_getLastModTime */
static int LZMA_isDirectory(dvoid *opaque, const char *name, int *fileExists)
{
Sep 27, 2006
Sep 27, 2006
628
LZMAarchive *archive = (LZMAarchive *) opaque;
Jan 23, 2008
Jan 23, 2008
629
LZMAfile *file = lzma_find_file(archive, name);
Jan 23, 2008
Jan 23, 2008
631
*fileExists = (file != NULL);
Feb 2, 2008
Feb 2, 2008
633
return(file == NULL ? 0 : file->item->IsDirectory);
634
635
636
637
638
639
640
641
642
643
644
645
} /* LZMA_isDirectory */
static int LZMA_isSymLink(dvoid *opaque, const char *name, int *fileExists)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
} /* LZMA_isSymLink */
static fvoid *LZMA_openRead(dvoid *opaque, const char *name, int *fileExists)
{
LZMAarchive *archive = (LZMAarchive *) opaque;
Jan 23, 2008
Jan 23, 2008
646
LZMAfile *file = lzma_find_file(archive, name);
Sep 27, 2006
Sep 27, 2006
647
Jan 23, 2008
Jan 23, 2008
648
649
650
*fileExists = (file != NULL);
BAIL_IF_MACRO(file == NULL, ERR_NO_SUCH_FILE, NULL);
BAIL_IF_MACRO(file->folder == NULL, ERR_NOT_A_FILE, NULL);
Jun 21, 2009
Jun 21, 2009
652
file->position = 0;
Jan 28, 2010
Jan 28, 2010
653
file->folder->references++; /* Increase refcount for automatic cleanup... */
Nov 5, 2006
Nov 5, 2006
654
Jan 23, 2008
Jan 23, 2008
655
return(file);
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
} /* LZMA_openRead */
static fvoid *LZMA_openWrite(dvoid *opaque, const char *filename)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
} /* LZMA_openWrite */
static fvoid *LZMA_openAppend(dvoid *opaque, const char *filename)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
} /* LZMA_openAppend */
static void LZMA_dirClose(dvoid *opaque)
{
Sep 27, 2006
Sep 27, 2006
673
LZMAarchive *archive = (LZMAarchive *) opaque;
Jan 23, 2008
Jan 23, 2008
674
PHYSFS_uint32 fileIndex = 0, numFiles = archive->db.Database.NumFiles;
Sep 27, 2006
Sep 27, 2006
675
Jan 23, 2008
Jan 23, 2008
676
for (fileIndex = 0; fileIndex < numFiles; fileIndex++)
Sep 27, 2006
Sep 27, 2006
677
{
Jan 23, 2008
Jan 23, 2008
678
679
LZMA_fileClose(&archive->files[fileIndex]);
} /* for */
Sep 27, 2006
Sep 27, 2006
681
SzArDbExFree(&archive->db, SzFreePhysicsFS);
Jan 23, 2008
Jan 23, 2008
682
683
__PHYSFS_platformClose(archive->stream.file);
lzma_archive_exit(archive);
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
} /* LZMA_dirClose */
static int LZMA_remove(dvoid *opaque, const char *name)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
} /* LZMA_remove */
static int LZMA_mkdir(dvoid *opaque, const char *name)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
} /* LZMA_mkdir */
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_LZMA =
{
"7Z",
LZMA_ARCHIVE_DESCRIPTION,
"Dennis Schridde <devurandom@gmx.net>",
"http://icculus.org/physfs/",
};
const PHYSFS_Archiver __PHYSFS_Archiver_LZMA =
{
&__PHYSFS_ArchiveInfo_LZMA,
LZMA_isArchive, /* isArchive() method */
LZMA_openArchive, /* openArchive() method */
LZMA_enumerateFiles, /* enumerateFiles() method */
LZMA_exists, /* exists() method */
LZMA_isDirectory, /* isDirectory() method */
LZMA_isSymLink, /* isSymLink() method */
LZMA_getLastModTime, /* getLastModTime() method */
LZMA_openRead, /* openRead() method */
LZMA_openWrite, /* openWrite() method */
LZMA_openAppend, /* openAppend() method */
LZMA_remove, /* remove() method */
LZMA_mkdir, /* mkdir() method */
LZMA_dirClose, /* dirClose() method */
LZMA_read, /* read() method */
LZMA_write, /* write() method */
LZMA_eof, /* eof() method */
LZMA_tell, /* tell() method */
LZMA_seek, /* seek() method */
LZMA_fileLength, /* fileLength() method */
LZMA_fileClose /* fileClose() method */
};
Mar 9, 2007
Mar 9, 2007
733
#endif /* defined PHYSFS_SUPPORTS_7Z */
734
735
/* end of lzma.c ... */