Skip to content

Latest commit

 

History

History
766 lines (604 loc) · 22.4 KB

archiver_lzma.c

File metadata and controls

766 lines (604 loc) · 22.4 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
PHYSFS_sint64 processedSizeLoc = 0;
if (maxReqSize > BUFFER_SIZE)
maxReqSize = BUFFER_SIZE;
Aug 21, 2010
Aug 21, 2010
116
processedSizeLoc = __PHYSFS_platformRead(s->file, s->buffer, maxReqSize);
Jan 23, 2008
Jan 23, 2008
117
*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! */
Aug 21, 2010
Aug 21, 2010
134
size_t processedSizeLoc = __PHYSFS_platformRead(s->file, buffer, 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
/* 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;
Jan 28, 2010
Jan 28, 2010
178
return strcmp(name, file->item->Name);
Jan 23, 2008
Jan 23, 2008
179
} /* lzma_file_cmp_posix */
Jan 23, 2008
Jan 23, 2008
181
182
183
184
185
186
187
188
/*
* 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;
Jan 28, 2010
Jan 28, 2010
189
return strcmp(files[one].item->Name, files[two].item->Name);
Jan 23, 2008
Jan 23, 2008
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
} /* 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'
*/
Feb 15, 2010
Feb 15, 2010
210
static LZMAfile * lzma_find_file(const LZMAarchive *archive, const char *name)
Jan 23, 2008
Jan 23, 2008
211
{
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
BAIL_IF_MACRO(file == NULL, ERR_NO_SUCH_FILE, NULL);
Jan 28, 2010
Jan 28, 2010
216
return file;
Jan 23, 2008
Jan 23, 2008
217
} /* 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
file->position = 0;
file->offset = 0; /* Offset will be set by LZMA_read() */
Jan 28, 2010
Jan 28, 2010
235
return 1;
Jan 23, 2008
Jan 23, 2008
236
} /* 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
}
} /* for */
__PHYSFS_sort(archive->files, numFiles, lzma_file_cmp, lzma_file_swap);
Jan 28, 2010
Jan 28, 2010
256
return 1;
Jan 23, 2008
Jan 23, 2008
257
} /* 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
/*
* 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 */
Jan 28, 2010
Jan 28, 2010
321
return rc;
322
323
324
} /* lzma_err */
Aug 21, 2010
Aug 21, 2010
325
static PHYSFS_sint64 LZMA_read(fvoid *opaque, void *outBuf, PHYSFS_uint64 len)
Jan 23, 2008
Jan 23, 2008
327
LZMAfile *file = (LZMAfile *) opaque;
Aug 21, 2010
Aug 21, 2010
329
size_t wantedSize = (size_t) len;
Jan 23, 2008
Jan 23, 2008
330
331
size_t remainingSize = file->item->Size - file->position;
size_t fileSize = 0;
Mar 12, 2007
Mar 12, 2007
332
Sep 27, 2006
Sep 27, 2006
333
334
BAIL_IF_MACRO(wantedSize == 0, NULL, 0); /* quick rejection. */
BAIL_IF_MACRO(remainingSize == 0, ERR_PAST_EOF, 0);
Aug 21, 2010
Aug 21, 2010
336
337
if (wantedSize > remainingSize)
wantedSize = remainingSize;
Nov 5, 2006
Nov 5, 2006
339
/* Only decompress the folder if it is not allready cached */
Jan 23, 2008
Jan 23, 2008
340
if (file->folder->cache == NULL)
Mar 10, 2007
Mar 10, 2007
341
342
{
int rc = lzma_err(SzExtract(
Jan 23, 2008
Jan 23, 2008
343
344
345
&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
346
/* Index of cached folder, will be changed by SzExtract */
Jan 23, 2008
Jan 23, 2008
347
&file->folder->index,
Nov 5, 2006
Nov 5, 2006
348
/* Cache for decompressed folder, allocated/freed by SzExtract */
Jan 23, 2008
Jan 23, 2008
349
&file->folder->cache,
Nov 5, 2006
Nov 5, 2006
350
/* Size of cache, will be changed by SzExtract */
Jan 23, 2008
Jan 23, 2008
351
&file->folder->size,
Nov 5, 2006
Nov 5, 2006
352
/* Offset of this file inside the cache, set by SzExtract */
Jan 23, 2008
Jan 23, 2008
353
&file->offset,
Nov 5, 2006
Nov 5, 2006
354
&fileSize, /* Size of this file */
Jan 23, 2008
Jan 23, 2008
355
356
&file->archive->stream.allocImp,
&file->archive->stream.allocTempImp));
Mar 10, 2007
Mar 10, 2007
357
358
if (rc != SZ_OK)
Nov 5, 2006
Nov 5, 2006
359
return -1;
Mar 10, 2007
Mar 10, 2007
360
} /* if */
Sep 27, 2006
Sep 27, 2006
361
Aug 21, 2010
Aug 21, 2010
362
363
/* Copy wanted bytes over from cache to outBuf */
memcpy(outBuf,
Jan 23, 2008
Jan 23, 2008
364
365
366
367
368
(file->folder->cache +
file->offset + file->position),
wantedSize);
file->position += wantedSize; /* Increase virtual position */
Aug 21, 2010
Aug 21, 2010
369
return wantedSize;
370
371
372
} /* LZMA_read */
Aug 21, 2010
Aug 21, 2010
373
static PHYSFS_sint64 LZMA_write(fvoid *f, const void *buf, PHYSFS_uint64 len)
374
375
376
377
378
379
380
{
BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
} /* LZMA_write */
static int LZMA_eof(fvoid *opaque)
{
Jan 23, 2008
Jan 23, 2008
381
382
LZMAfile *file = (LZMAfile *) opaque;
return (file->position >= file->item->Size);
383
384
385
386
387
} /* LZMA_eof */
static PHYSFS_sint64 LZMA_tell(fvoid *opaque)
{
Jan 23, 2008
Jan 23, 2008
388
389
LZMAfile *file = (LZMAfile *) opaque;
return (file->position);
390
391
392
393
394
} /* LZMA_tell */
static int LZMA_seek(fvoid *opaque, PHYSFS_uint64 offset)
{
Jan 23, 2008
Jan 23, 2008
395
LZMAfile *file = (LZMAfile *) opaque;
396
397
BAIL_IF_MACRO(offset < 0, ERR_SEEK_OUT_OF_RANGE, 0);
Jan 23, 2008
Jan 23, 2008
398
399
400
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
402
return 1;
403
404
405
406
407
} /* LZMA_seek */
static PHYSFS_sint64 LZMA_fileLength(fvoid *opaque)
{
Jan 23, 2008
Jan 23, 2008
408
409
LZMAfile *file = (LZMAfile *) opaque;
return (file->item->Size);
410
411
412
413
414
} /* LZMA_fileLength */
static int LZMA_fileClose(fvoid *opaque)
{
Jan 23, 2008
Jan 23, 2008
415
LZMAfile *file = (LZMAfile *) opaque;
Jan 23, 2008
Jan 23, 2008
417
BAIL_IF_MACRO(file->folder == NULL, ERR_NOT_A_FILE, 0);
Jan 23, 2008
Jan 23, 2008
419
420
421
422
/* 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
423
{
Jan 23, 2008
Jan 23, 2008
424
425
426
/* 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
427
428
}
Jan 28, 2010
Jan 28, 2010
429
return 1;
430
431
432
433
434
435
436
437
438
439
440
441
442
} /* 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
443
/* Read signature bytes */
Aug 21, 2010
Aug 21, 2010
444
if (__PHYSFS_platformRead(in, sig, k7zSignatureSize) != k7zSignatureSize)
Jan 23, 2008
Jan 23, 2008
445
{
Jan 28, 2010
Jan 28, 2010
446
__PHYSFS_platformClose(in); /* Don't forget to close the file before returning... */
447
BAIL_MACRO(NULL, 0);
Jan 23, 2008
Jan 23, 2008
448
}
Sep 27, 2006
Sep 27, 2006
449
450
451
__PHYSFS_platformClose(in);
Jan 23, 2008
Jan 23, 2008
452
/* Test whether sig is the 7z signature */
Jan 28, 2010
Jan 28, 2010
453
return TestSignatureCandidate(sig);
454
455
456
457
458
} /* LZMA_isArchive */
static void *LZMA_openArchive(const char *name, int forWriting)
{
Jan 23, 2008
Jan 23, 2008
459
size_t len = 0;
Sep 27, 2006
Sep 27, 2006
460
LZMAarchive *archive = NULL;
461
462
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, NULL);
Nov 5, 2006
Nov 5, 2006
463
BAIL_IF_MACRO(!LZMA_isArchive(name,forWriting), ERR_UNSUPPORTED_ARCHIVE, 0);
Sep 27, 2006
Sep 27, 2006
464
465
466
467
archive = (LZMAarchive *) allocator.Malloc(sizeof (LZMAarchive));
BAIL_IF_MACRO(archive == NULL, ERR_OUT_OF_MEMORY, NULL);
Jan 23, 2008
Jan 23, 2008
468
lzma_archive_init(archive);
Jan 23, 2008
Jan 23, 2008
470
if ( (archive->stream.file = __PHYSFS_platformOpenRead(name)) == NULL )
Jan 23, 2008
Jan 23, 2008
472
473
__PHYSFS_platformClose(archive->stream.file);
lzma_archive_exit(archive);
Jan 28, 2010
Jan 28, 2010
474
return NULL; /* Error is set by platformOpenRead! */
Jan 23, 2008
Jan 23, 2008
475
}
Jan 23, 2008
Jan 23, 2008
477
CrcGenerateTable();
478
SzArDbExInit(&archive->db);
Jan 23, 2008
Jan 23, 2008
479
480
481
482
if (lzma_err(SzArchiveOpen(&archive->stream.inStream,
&archive->db,
&archive->stream.allocImp,
&archive->stream.allocTempImp)) != SZ_OK)
Jan 23, 2008
Jan 23, 2008
484
485
486
SzArDbExFree(&archive->db, SzFreePhysicsFS);
__PHYSFS_platformClose(archive->stream.file);
lzma_archive_exit(archive);
Jan 28, 2010
Jan 28, 2010
487
return NULL; /* Error is set by lzma_err! */
Jan 23, 2008
Jan 23, 2008
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
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
506
len = archive->db.Database.NumFolders * sizeof (LZMAfolder);
Jan 23, 2008
Jan 23, 2008
507
508
509
510
511
512
513
514
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
515
516
517
518
519
/*
* 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
520
521
522
523
524
525
526
527
528
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
529
Jan 28, 2010
Jan 28, 2010
530
return archive;
531
532
533
534
535
536
537
538
} /* 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
539
const char *odir, const char *str, size_t flen)
Jan 23, 2008
Jan 23, 2008
541
char *newstr = __PHYSFS_smallAlloc(flen + 1);
542
543
544
if (newstr == NULL)
return;
Jan 23, 2008
Jan 23, 2008
545
546
memcpy(newstr, str, flen);
newstr[flen] = '\0';
547
cb(callbackdata, odir, newstr);
Mar 24, 2007
Mar 24, 2007
548
__PHYSFS_smallFree(newstr);
549
550
551
552
553
554
555
} /* 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
556
557
size_t dlen = strlen(dname),
dlen_inc = dlen + ((dlen > 0) ? 1 : 0);
558
LZMAarchive *archive = (LZMAarchive *) opaque;
Feb 2, 2008
Feb 2, 2008
559
560
561
562
563
LZMAfile *file = NULL,
*lastFile = &archive->files[archive->db.Database.NumFiles];
if (dlen)
{
file = lzma_find_file(archive, dname);
Jan 28, 2010
Jan 28, 2010
564
if (file != NULL) /* if 'file' is NULL it should stay so, otherwise errors will not be handled */
Feb 2, 2008
Feb 2, 2008
565
566
567
568
569
570
file += 1;
}
else
{
file = archive->files;
}
Jan 23, 2008
Jan 23, 2008
572
BAIL_IF_MACRO(file == NULL, ERR_NO_SUCH_FILE, );
Jan 23, 2008
Jan 23, 2008
574
while (file < lastFile)
Jan 23, 2008
Jan 23, 2008
576
577
578
579
580
581
582
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
584
585
586
587
588
589
590
591
592
file++;
continue;
}
/* Do the actual callback... */
doEnumCallback(cb, callbackdata, origdir, dirNameEnd, strlen(dirNameEnd));
file++;
}
593
594
595
596
597
} /* LZMA_enumerateFiles */
static int LZMA_exists(dvoid *opaque, const char *name)
{
Sep 27, 2006
Sep 27, 2006
598
LZMAarchive *archive = (LZMAarchive *) opaque;
Jan 28, 2010
Jan 28, 2010
599
return (lzma_find_file(archive, name) != NULL);
600
601
602
603
} /* LZMA_exists */
static PHYSFS_sint64 LZMA_getLastModTime(dvoid *opaque,
Sep 27, 2006
Sep 27, 2006
604
605
const char *name,
int *fileExists)
Jan 23, 2008
Jan 23, 2008
607
608
609
610
611
612
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
613
BAIL_IF_MACRO(!file->item->IsLastWriteTimeDefined, NULL, -1); /* write-time may not be defined for every file */
Jan 23, 2008
Jan 23, 2008
614
Jan 28, 2010
Jan 28, 2010
615
return lzma_filetime_to_unix_timestamp(&file->item->LastWriteTime);
616
617
618
619
620
} /* LZMA_getLastModTime */
static int LZMA_isDirectory(dvoid *opaque, const char *name, int *fileExists)
{
Sep 27, 2006
Sep 27, 2006
621
LZMAarchive *archive = (LZMAarchive *) opaque;
Jan 23, 2008
Jan 23, 2008
622
LZMAfile *file = lzma_find_file(archive, name);
Jan 23, 2008
Jan 23, 2008
624
*fileExists = (file != NULL);
Jan 28, 2010
Jan 28, 2010
626
return ((file == NULL) ? 0 : file->item->IsDirectory);
627
628
629
630
631
632
633
634
635
636
637
638
} /* 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
639
LZMAfile *file = lzma_find_file(archive, name);
Sep 27, 2006
Sep 27, 2006
640
Jan 23, 2008
Jan 23, 2008
641
642
643
*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
645
file->position = 0;
Jan 28, 2010
Jan 28, 2010
646
file->folder->references++; /* Increase refcount for automatic cleanup... */
Nov 5, 2006
Nov 5, 2006
647
Jan 28, 2010
Jan 28, 2010
648
return file;
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
} /* 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
666
LZMAarchive *archive = (LZMAarchive *) opaque;
Jan 23, 2008
Jan 23, 2008
667
PHYSFS_uint32 fileIndex = 0, numFiles = archive->db.Database.NumFiles;
Sep 27, 2006
Sep 27, 2006
668
Jan 23, 2008
Jan 23, 2008
669
for (fileIndex = 0; fileIndex < numFiles; fileIndex++)
Sep 27, 2006
Sep 27, 2006
670
{
Jan 23, 2008
Jan 23, 2008
671
672
LZMA_fileClose(&archive->files[fileIndex]);
} /* for */
Sep 27, 2006
Sep 27, 2006
674
SzArDbExFree(&archive->db, SzFreePhysicsFS);
Jan 23, 2008
Jan 23, 2008
675
676
__PHYSFS_platformClose(archive->stream.file);
lzma_archive_exit(archive);
677
678
679
680
681
682
683
684
685
686
687
688
689
690
} /* 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 */
Aug 22, 2010
Aug 22, 2010
691
static int LZMA_stat(dvoid *opaque, const char *filename, int *exists,
Feb 15, 2010
Feb 15, 2010
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
PHYSFS_Stat *stat)
{
const LZMAarchive *archive = (const LZMAarchive *) opaque;
const LZMAfile *file = lzma_find_file(archive, filename);
*exists = (file != 0);
if (!file)
return 0;
if(file->item->IsDirectory)
{
stat->filesize = 0;
stat->filetype = PHYSFS_FILETYPE_DIRECTORY;
} /* if */
else
{
stat->filesize = (PHYSFS_sint64) file->item->Size;
stat->filetype = PHYSFS_FILETYPE_REGULAR;
} /* else */
/* !!! FIXME: the 0's should be -1's? */
if (file->item->IsLastWriteTimeDefined)
stat->modtime = lzma_filetime_to_unix_timestamp(&file->item->LastWriteTime);
else
stat->modtime = 0;
/* real create and accesstype are currently not in the lzma SDK */
stat->createtime = stat->modtime;
stat->accesstime = 0;
stat->readonly = 1; /* 7zips are always read only */
Aug 21, 2010
Aug 21, 2010
724
return 1;
Feb 15, 2010
Feb 15, 2010
725
726
} /* LZMA_stat */
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
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 */
Feb 15, 2010
Feb 15, 2010
759
760
LZMA_fileClose, /* fileClose() method */
LZMA_stat /* stat() method */
Mar 9, 2007
Mar 9, 2007
763
#endif /* defined PHYSFS_SUPPORTS_7Z */
764
765
/* end of lzma.c ... */