Skip to content

Latest commit

 

History

History
747 lines (591 loc) · 21.8 KB

archiver_lzma.c

File metadata and controls

747 lines (591 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
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
} /* LZMA_fileClose */
Aug 24, 2010
Aug 24, 2010
433
434
/* !!! FIXME: don't open/close file here, merge with openArchive(). */
static int isLzma(const char *filename)
435
436
437
438
439
440
441
{
PHYSFS_uint8 sig[k7zSignatureSize];
void *in;
in = __PHYSFS_platformOpenRead(filename);
BAIL_IF_MACRO(in == NULL, NULL, 0);
Jan 23, 2008
Jan 23, 2008
442
/* Read signature bytes */
Aug 21, 2010
Aug 21, 2010
443
if (__PHYSFS_platformRead(in, sig, k7zSignatureSize) != k7zSignatureSize)
Jan 23, 2008
Jan 23, 2008
444
{
Jan 28, 2010
Jan 28, 2010
445
__PHYSFS_platformClose(in); /* Don't forget to close the file before returning... */
446
BAIL_MACRO(NULL, 0);
Jan 23, 2008
Jan 23, 2008
447
}
Sep 27, 2006
Sep 27, 2006
448
449
450
__PHYSFS_platformClose(in);
Jan 23, 2008
Jan 23, 2008
451
/* Test whether sig is the 7z signature */
Jan 28, 2010
Jan 28, 2010
452
return TestSignatureCandidate(sig);
Aug 24, 2010
Aug 24, 2010
453
} /* isLzma */
454
455
456
457
static void *LZMA_openArchive(const char *name, int forWriting)
{
Jan 23, 2008
Jan 23, 2008
458
size_t len = 0;
Sep 27, 2006
Sep 27, 2006
459
LZMAarchive *archive = NULL;
460
461
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, NULL);
Aug 24, 2010
Aug 24, 2010
462
BAIL_IF_MACRO(!isLzma(name), ERR_UNSUPPORTED_ARCHIVE, NULL);
Sep 27, 2006
Sep 27, 2006
463
464
465
466
archive = (LZMAarchive *) allocator.Malloc(sizeof (LZMAarchive));
BAIL_IF_MACRO(archive == NULL, ERR_OUT_OF_MEMORY, NULL);
Jan 23, 2008
Jan 23, 2008
467
lzma_archive_init(archive);
Jan 23, 2008
Jan 23, 2008
469
if ( (archive->stream.file = __PHYSFS_platformOpenRead(name)) == NULL )
Jan 23, 2008
Jan 23, 2008
471
472
__PHYSFS_platformClose(archive->stream.file);
lzma_archive_exit(archive);
Jan 28, 2010
Jan 28, 2010
473
return NULL; /* Error is set by platformOpenRead! */
Jan 23, 2008
Jan 23, 2008
474
}
Jan 23, 2008
Jan 23, 2008
476
CrcGenerateTable();
477
SzArDbExInit(&archive->db);
Jan 23, 2008
Jan 23, 2008
478
479
480
481
if (lzma_err(SzArchiveOpen(&archive->stream.inStream,
&archive->db,
&archive->stream.allocImp,
&archive->stream.allocTempImp)) != SZ_OK)
Jan 23, 2008
Jan 23, 2008
483
484
485
SzArDbExFree(&archive->db, SzFreePhysicsFS);
__PHYSFS_platformClose(archive->stream.file);
lzma_archive_exit(archive);
Jan 28, 2010
Jan 28, 2010
486
return NULL; /* Error is set by lzma_err! */
Jan 23, 2008
Jan 23, 2008
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
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
505
len = archive->db.Database.NumFolders * sizeof (LZMAfolder);
Jan 23, 2008
Jan 23, 2008
506
507
508
509
510
511
512
513
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
514
515
516
517
518
/*
* 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
519
520
521
522
523
524
525
526
527
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
528
Jan 28, 2010
Jan 28, 2010
529
return archive;
530
531
532
533
534
535
536
537
} /* 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
538
const char *odir, const char *str, size_t flen)
Jan 23, 2008
Jan 23, 2008
540
char *newstr = __PHYSFS_smallAlloc(flen + 1);
541
542
543
if (newstr == NULL)
return;
Jan 23, 2008
Jan 23, 2008
544
545
memcpy(newstr, str, flen);
newstr[flen] = '\0';
546
cb(callbackdata, odir, newstr);
Mar 24, 2007
Mar 24, 2007
547
__PHYSFS_smallFree(newstr);
548
549
550
551
552
553
554
} /* 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
555
556
size_t dlen = strlen(dname),
dlen_inc = dlen + ((dlen > 0) ? 1 : 0);
557
LZMAarchive *archive = (LZMAarchive *) opaque;
Feb 2, 2008
Feb 2, 2008
558
559
560
561
562
LZMAfile *file = NULL,
*lastFile = &archive->files[archive->db.Database.NumFiles];
if (dlen)
{
file = lzma_find_file(archive, dname);
Jan 28, 2010
Jan 28, 2010
563
if (file != NULL) /* if 'file' is NULL it should stay so, otherwise errors will not be handled */
Feb 2, 2008
Feb 2, 2008
564
565
566
567
568
569
file += 1;
}
else
{
file = archive->files;
}
Jan 23, 2008
Jan 23, 2008
571
BAIL_IF_MACRO(file == NULL, ERR_NO_SUCH_FILE, );
Jan 23, 2008
Jan 23, 2008
573
while (file < lastFile)
Jan 23, 2008
Jan 23, 2008
575
576
577
578
579
580
581
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
583
584
585
586
587
588
589
590
591
file++;
continue;
}
/* Do the actual callback... */
doEnumCallback(cb, callbackdata, origdir, dirNameEnd, strlen(dirNameEnd));
file++;
}
592
593
594
595
596
} /* LZMA_enumerateFiles */
static int LZMA_exists(dvoid *opaque, const char *name)
{
Sep 27, 2006
Sep 27, 2006
597
LZMAarchive *archive = (LZMAarchive *) opaque;
Jan 28, 2010
Jan 28, 2010
598
return (lzma_find_file(archive, name) != NULL);
599
600
601
602
603
} /* LZMA_exists */
static int LZMA_isDirectory(dvoid *opaque, const char *name, int *fileExists)
{
Sep 27, 2006
Sep 27, 2006
604
LZMAarchive *archive = (LZMAarchive *) opaque;
Jan 23, 2008
Jan 23, 2008
605
LZMAfile *file = lzma_find_file(archive, name);
Jan 23, 2008
Jan 23, 2008
607
*fileExists = (file != NULL);
Jan 28, 2010
Jan 28, 2010
609
return ((file == NULL) ? 0 : file->item->IsDirectory);
610
611
612
613
614
615
616
617
618
619
620
621
} /* 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
622
LZMAfile *file = lzma_find_file(archive, name);
Sep 27, 2006
Sep 27, 2006
623
Jan 23, 2008
Jan 23, 2008
624
625
626
*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
628
file->position = 0;
Jan 28, 2010
Jan 28, 2010
629
file->folder->references++; /* Increase refcount for automatic cleanup... */
Nov 5, 2006
Nov 5, 2006
630
Jan 28, 2010
Jan 28, 2010
631
return file;
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
} /* 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
649
LZMAarchive *archive = (LZMAarchive *) opaque;
Jan 23, 2008
Jan 23, 2008
650
PHYSFS_uint32 fileIndex = 0, numFiles = archive->db.Database.NumFiles;
Sep 27, 2006
Sep 27, 2006
651
Jan 23, 2008
Jan 23, 2008
652
for (fileIndex = 0; fileIndex < numFiles; fileIndex++)
Sep 27, 2006
Sep 27, 2006
653
{
Jan 23, 2008
Jan 23, 2008
654
655
LZMA_fileClose(&archive->files[fileIndex]);
} /* for */
Sep 27, 2006
Sep 27, 2006
657
SzArDbExFree(&archive->db, SzFreePhysicsFS);
Jan 23, 2008
Jan 23, 2008
658
659
__PHYSFS_platformClose(archive->stream.file);
lzma_archive_exit(archive);
660
661
662
663
664
665
666
667
668
669
670
671
672
673
} /* 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
674
static int LZMA_stat(dvoid *opaque, const char *filename, int *exists,
Feb 15, 2010
Feb 15, 2010
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
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
707
return 1;
Feb 15, 2010
Feb 15, 2010
708
709
} /* LZMA_stat */
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
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_openArchive, /* openArchive() method */
LZMA_enumerateFiles, /* enumerateFiles() method */
LZMA_exists, /* exists() method */
LZMA_isDirectory, /* isDirectory() method */
LZMA_isSymLink, /* isSymLink() 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 */
Aug 22, 2010
Aug 22, 2010
734
LZMA_stat, /* stat() method */
735
736
737
738
739
740
LZMA_read, /* read() method */
LZMA_write, /* write() method */
LZMA_eof, /* eof() method */
LZMA_tell, /* tell() method */
LZMA_seek, /* seek() method */
LZMA_fileLength, /* fileLength() method */
Aug 22, 2010
Aug 22, 2010
741
LZMA_fileClose /* fileClose() method */
Mar 9, 2007
Mar 9, 2007
744
#endif /* defined PHYSFS_SUPPORTS_7Z */
745
746
/* end of lzma.c ... */