Skip to content

Latest commit

 

History

History
703 lines (561 loc) · 20.5 KB

archiver_lzma.c

File metadata and controls

703 lines (561 loc) · 20.5 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
10
11
12
* by Igor Pavlov.
*/
#define __PHYSICSFS_INTERNAL__
#include "physfs_internal.h"
Mar 23, 2012
Mar 23, 2012
13
14
#if PHYSFS_SUPPORTS_7Z
Jan 23, 2008
Jan 23, 2008
15
16
17
#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
18
19
Jan 23, 2008
Jan 23, 2008
20
21
/* 7z internal from 7zIn.c */
extern int TestSignatureCandidate(Byte *testBytes);
Sep 27, 2006
Sep 27, 2006
22
23
Jan 23, 2008
Jan 23, 2008
24
25
26
#ifdef _LZMA_IN_CB
# define BUFFER_SIZE (1 << 12)
#endif /* _LZMA_IN_CB */
Sep 27, 2006
Sep 27, 2006
27
Jan 23, 2008
Jan 23, 2008
29
30
31
32
/*
* Carries filestream metadata through 7z
*/
typedef struct _FileInputStream
Jan 23, 2008
Jan 23, 2008
34
35
36
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 */
Aug 30, 2010
Aug 30, 2010
37
PHYSFS_Io *io; /* Filehandle, used by read implementation */
Jan 23, 2008
Jan 23, 2008
38
39
40
41
#ifdef _LZMA_IN_CB
Byte buffer[BUFFER_SIZE]; /* Buffer, used by read implementation */
#endif /* _LZMA_IN_CB */
} FileInputStream;
Nov 5, 2006
Nov 5, 2006
43
/*
Jan 23, 2008
Jan 23, 2008
44
* In the 7z format archives are splited into blocks, those are called folders
Nov 5, 2006
Nov 5, 2006
45
46
47
48
49
50
* 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
51
52
PHYSFS_uint8 *cache; /* Cached folder */
size_t size; /* Size of folder */
Nov 5, 2006
Nov 5, 2006
53
54
55
56
57
58
} LZMAfolder;
/*
* Set by LZMA_openArchive(), except folder which gets it's values
* in LZMA_read()
*/
Sep 27, 2006
Sep 27, 2006
59
typedef struct _LZMAarchive
Jan 23, 2008
Jan 23, 2008
61
62
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
63
CArchiveDatabaseEx db; /* For 7z: Database */
Jan 23, 2008
Jan 23, 2008
64
FileInputStream stream; /* For 7z: Input file incl. read and seek callbacks */
Jan 23, 2008
Jan 23, 2008
67
68
/* Set by LZMA_openArchive(), except offset which is set by LZMA_read() */
typedef struct _LZMAfile
Jan 23, 2008
Jan 23, 2008
70
PHYSFS_uint32 index; /* Index of file in archive */
Sep 27, 2006
Sep 27, 2006
71
LZMAarchive *archive; /* Link to corresponding archive */
Jan 23, 2008
Jan 23, 2008
72
73
LZMAfolder *folder; /* Link to corresponding folder */
CFileItem *item; /* For 7z: File info, eg. name, size */
Nov 5, 2006
Nov 5, 2006
74
size_t offset; /* Offset in folder */
Jan 23, 2008
Jan 23, 2008
75
76
size_t position; /* Current "virtual" position in file */
} LZMAfile;
Sep 27, 2006
Sep 27, 2006
79
80
/* Memory management implementations to be passed to 7z */
81
82
83
84
85
86
87
88
89
90
91
92
93
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
94
95
96
97
/* Filesystem implementations to be passed to 7z */
#ifdef _LZMA_IN_CB
Jan 23, 2008
Jan 23, 2008
98
99
100
101
/*
* 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
102
103
SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxReqSize,
size_t *processedSize)
Jan 28, 2010
Jan 28, 2010
105
FileInputStream *s = (FileInputStream *)(object - offsetof(FileInputStream, inStream)); /* HACK! */
Jan 23, 2008
Jan 23, 2008
106
107
108
109
PHYSFS_sint64 processedSizeLoc = 0;
if (maxReqSize > BUFFER_SIZE)
maxReqSize = BUFFER_SIZE;
Aug 30, 2010
Aug 30, 2010
110
processedSizeLoc = s->io->read(s->io, s->buffer, maxReqSize);
Jan 23, 2008
Jan 23, 2008
111
*buffer = s->buffer;
Mar 19, 2007
Mar 19, 2007
112
113
if (processedSize != NULL)
*processedSize = (size_t) processedSizeLoc;
Jan 23, 2008
Jan 23, 2008
114
Sep 27, 2006
Sep 27, 2006
115
116
117
118
return SZ_OK;
} /* SzFileReadImp */
#else
Jan 23, 2008
Jan 23, 2008
120
121
122
123
/*
* 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
124
125
126
SZ_RESULT SzFileReadImp(void *object, void *buffer, size_t size,
size_t *processedSize)
{
Jan 28, 2010
Jan 28, 2010
127
FileInputStream *s = (FileInputStream *)((unsigned long)object - offsetof(FileInputStream, inStream)); /* HACK! */
Aug 30, 2010
Aug 30, 2010
128
129
const size_t processedSizeLoc = s->io->read(s->io, buffer, size);
if (processedSize != NULL)
Sep 27, 2006
Sep 27, 2006
130
*processedSize = processedSizeLoc;
131
132
133
return SZ_OK;
} /* SzFileReadImp */
Sep 27, 2006
Sep 27, 2006
134
#endif
Jan 23, 2008
Jan 23, 2008
136
137
138
139
/*
* Seek implementation, to be passed to 7z
* WARNING: If the ISzInStream in 'object' is not contained in a valid FileInputStream this _will_ break horribly!
*/
140
141
SZ_RESULT SzFileSeekImp(void *object, CFileSize pos)
{
Jan 28, 2010
Jan 28, 2010
142
FileInputStream *s = (FileInputStream *)((unsigned long)object - offsetof(FileInputStream, inStream)); /* HACK! */
Aug 30, 2010
Aug 30, 2010
143
if (s->io->seek(s->io, (PHYSFS_uint64) pos))
144
145
146
147
148
return SZ_OK;
return SZE_FAIL;
} /* SzFileSeekImp */
Sep 27, 2006
Sep 27, 2006
149
/*
Jan 23, 2008
Jan 23, 2008
150
* Translate Microsoft FILETIME (used by 7zip) into UNIX timestamp
Sep 27, 2006
Sep 27, 2006
151
*/
Jan 23, 2008
Jan 23, 2008
152
static PHYSFS_sint64 lzma_filetime_to_unix_timestamp(CArchiveFileTime *ft)
Jan 23, 2008
Jan 23, 2008
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/* 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
172
return strcmp(name, file->item->Name);
Jan 23, 2008
Jan 23, 2008
173
} /* lzma_file_cmp_posix */
Jan 23, 2008
Jan 23, 2008
175
176
177
178
179
/*
* Compare two files with each other based on the name
* Used for sorting
*/
Jun 1, 2012
Jun 1, 2012
180
static int lzma_file_cmp(void *_a, size_t one, size_t two)
Jan 23, 2008
Jan 23, 2008
181
182
{
LZMAfile *files = (LZMAfile *) _a;
Jan 28, 2010
Jan 28, 2010
183
return strcmp(files[one].item->Name, files[two].item->Name);
Jan 23, 2008
Jan 23, 2008
184
185
186
187
188
189
} /* lzma_file_cmp */
/*
* Swap two entries in the file array
*/
Jun 1, 2012
Jun 1, 2012
190
static void lzma_file_swap(void *_a, size_t one, size_t two)
Jan 23, 2008
Jan 23, 2008
191
192
193
194
195
196
197
198
199
200
201
202
203
{
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
204
static LZMAfile * lzma_find_file(const LZMAarchive *archive, const char *name)
Jan 23, 2008
Jan 23, 2008
205
{
Jan 28, 2010
Jan 28, 2010
206
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
207
Nov 28, 2012
Nov 28, 2012
208
BAIL_IF_MACRO(file == NULL, PHYSFS_ERR_NOT_FOUND, NULL);
Jan 23, 2008
Jan 23, 2008
209
Jan 28, 2010
Jan 28, 2010
210
return file;
Jan 23, 2008
Jan 23, 2008
211
} /* lzma_find_file */
Sep 27, 2006
Sep 27, 2006
214
/*
Jan 23, 2008
Jan 23, 2008
215
* Load metadata for the file at given index
Sep 27, 2006
Sep 27, 2006
216
*/
Jan 23, 2008
Jan 23, 2008
217
static int lzma_file_init(LZMAarchive *archive, PHYSFS_uint32 fileIndex)
Jan 23, 2008
Jan 23, 2008
219
220
221
LZMAfile *file = &archive->files[fileIndex];
PHYSFS_uint32 folderIndex = archive->db.FileIndexToFolderIndexMap[fileIndex];
Jan 28, 2010
Jan 28, 2010
222
file->index = fileIndex; /* Store index into 7z array, since we sort our own. */
Jan 23, 2008
Jan 23, 2008
223
file->archive = archive;
Jan 28, 2010
Jan 28, 2010
224
225
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
226
227
228
file->position = 0;
file->offset = 0; /* Offset will be set by LZMA_read() */
Jan 28, 2010
Jan 28, 2010
229
return 1;
Jan 23, 2008
Jan 23, 2008
230
} /* lzma_load_file */
Jan 23, 2008
Jan 23, 2008
233
234
235
236
237
238
/*
* 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
240
for (fileIndex = 0; fileIndex < numFiles; fileIndex++ )
Jan 23, 2008
Jan 23, 2008
242
if (!lzma_file_init(archive, fileIndex))
Jan 28, 2010
Jan 28, 2010
244
return 0; /* FALSE on failure */
Jan 23, 2008
Jan 23, 2008
245
246
247
}
} /* for */
Jun 1, 2012
Jun 1, 2012
248
__PHYSFS_sort(archive->files, (size_t) numFiles, lzma_file_cmp, lzma_file_swap);
Jan 23, 2008
Jan 23, 2008
249
Jan 28, 2010
Jan 28, 2010
250
return 1;
Jan 23, 2008
Jan 23, 2008
251
} /* lzma_load_files */
Jan 23, 2008
Jan 23, 2008
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
/*
* 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);
}
284
285
286
287
288
289
290
291
292
293
/*
* 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 */
Mar 20, 2012
Mar 20, 2012
294
__PHYSFS_setError(PHYSFS_ERR_CORRUPT); /*!!!FIXME: was "PHYSFS_ERR_DATA_ERROR" */
295
296
break;
case SZE_OUTOFMEMORY:
Mar 20, 2012
Mar 20, 2012
297
__PHYSFS_setError(PHYSFS_ERR_OUT_OF_MEMORY);
298
299
break;
case SZE_CRC_ERROR:
Mar 20, 2012
Mar 20, 2012
300
__PHYSFS_setError(PHYSFS_ERR_CORRUPT);
301
302
break;
case SZE_NOTIMPL:
Mar 20, 2012
Mar 20, 2012
303
__PHYSFS_setError(PHYSFS_ERR_UNSUPPORTED);
304
305
break;
case SZE_FAIL:
Mar 20, 2012
Mar 20, 2012
306
__PHYSFS_setError(PHYSFS_ERR_OTHER_ERROR); /* !!! FIXME: right? */
307
308
break;
case SZE_ARCHIVE_ERROR:
Mar 20, 2012
Mar 20, 2012
309
__PHYSFS_setError(PHYSFS_ERR_CORRUPT); /* !!! FIXME: right? */
Mar 20, 2012
Mar 20, 2012
312
__PHYSFS_setError(PHYSFS_ERR_OTHER_ERROR);
Jan 28, 2010
Jan 28, 2010
315
return rc;
316
317
318
} /* lzma_err */
Aug 30, 2010
Aug 30, 2010
319
static PHYSFS_sint64 LZMA_read(PHYSFS_Io *io, void *outBuf, PHYSFS_uint64 len)
Aug 30, 2010
Aug 30, 2010
321
LZMAfile *file = (LZMAfile *) io->opaque;
Aug 21, 2010
Aug 21, 2010
323
size_t wantedSize = (size_t) len;
Aug 30, 2010
Aug 30, 2010
324
const size_t remainingSize = file->item->Size - file->position;
Jan 23, 2008
Jan 23, 2008
325
size_t fileSize = 0;
Mar 12, 2007
Mar 12, 2007
326
Mar 20, 2012
Mar 20, 2012
327
328
BAIL_IF_MACRO(wantedSize == 0, ERRPASS, 0); /* quick rejection. */
BAIL_IF_MACRO(remainingSize == 0, PHYSFS_ERR_PAST_EOF, 0);
Aug 21, 2010
Aug 21, 2010
330
331
if (wantedSize > remainingSize)
wantedSize = remainingSize;
Aug 30, 2010
Aug 30, 2010
333
/* Only decompress the folder if it is not already cached */
Jan 23, 2008
Jan 23, 2008
334
if (file->folder->cache == NULL)
Mar 10, 2007
Mar 10, 2007
335
{
Aug 30, 2010
Aug 30, 2010
336
const int rc = lzma_err(SzExtract(
Jan 23, 2008
Jan 23, 2008
337
338
339
&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
340
/* Index of cached folder, will be changed by SzExtract */
Jan 23, 2008
Jan 23, 2008
341
&file->folder->index,
Nov 5, 2006
Nov 5, 2006
342
/* Cache for decompressed folder, allocated/freed by SzExtract */
Jan 23, 2008
Jan 23, 2008
343
&file->folder->cache,
Nov 5, 2006
Nov 5, 2006
344
/* Size of cache, will be changed by SzExtract */
Jan 23, 2008
Jan 23, 2008
345
&file->folder->size,
Nov 5, 2006
Nov 5, 2006
346
/* Offset of this file inside the cache, set by SzExtract */
Jan 23, 2008
Jan 23, 2008
347
&file->offset,
Nov 5, 2006
Nov 5, 2006
348
&fileSize, /* Size of this file */
Jan 23, 2008
Jan 23, 2008
349
350
&file->archive->stream.allocImp,
&file->archive->stream.allocTempImp));
Mar 10, 2007
Mar 10, 2007
351
352
if (rc != SZ_OK)
Nov 5, 2006
Nov 5, 2006
353
return -1;
Mar 10, 2007
Mar 10, 2007
354
} /* if */
Sep 27, 2006
Sep 27, 2006
355
Aug 21, 2010
Aug 21, 2010
356
/* Copy wanted bytes over from cache to outBuf */
Aug 30, 2010
Aug 30, 2010
357
memcpy(outBuf, (file->folder->cache + file->offset + file->position),
Jan 23, 2008
Jan 23, 2008
358
359
360
wantedSize);
file->position += wantedSize; /* Increase virtual position */
Aug 21, 2010
Aug 21, 2010
361
return wantedSize;
362
363
364
} /* LZMA_read */
Aug 30, 2010
Aug 30, 2010
365
static PHYSFS_sint64 LZMA_write(PHYSFS_Io *io, const void *b, PHYSFS_uint64 len)
Mar 22, 2012
Mar 22, 2012
367
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, -1);
368
369
370
} /* LZMA_write */
Aug 30, 2010
Aug 30, 2010
371
static PHYSFS_sint64 LZMA_tell(PHYSFS_Io *io)
Aug 30, 2010
Aug 30, 2010
373
374
LZMAfile *file = (LZMAfile *) io->opaque;
return file->position;
375
376
377
} /* LZMA_tell */
Aug 30, 2010
Aug 30, 2010
378
static int LZMA_seek(PHYSFS_Io *io, PHYSFS_uint64 offset)
Aug 30, 2010
Aug 30, 2010
380
LZMAfile *file = (LZMAfile *) io->opaque;
Mar 20, 2012
Mar 20, 2012
382
BAIL_IF_MACRO(offset > file->item->Size, PHYSFS_ERR_PAST_EOF, 0);
Jan 23, 2008
Jan 23, 2008
383
384
file->position = offset; /* We only use a virtual position... */
Sep 27, 2006
Sep 27, 2006
386
return 1;
387
388
389
} /* LZMA_seek */
Aug 30, 2010
Aug 30, 2010
390
static PHYSFS_sint64 LZMA_length(PHYSFS_Io *io)
Aug 30, 2010
Aug 30, 2010
392
const LZMAfile *file = (LZMAfile *) io->opaque;
Jan 23, 2008
Jan 23, 2008
393
return (file->item->Size);
Aug 30, 2010
Aug 30, 2010
394
} /* LZMA_length */
Aug 30, 2010
Aug 30, 2010
397
static PHYSFS_Io *LZMA_duplicate(PHYSFS_Io *_io)
Aug 30, 2010
Aug 30, 2010
399
400
/* !!! FIXME: this archiver needs to be reworked to allow multiple
* !!! FIXME: opens before we worry about duplication. */
Mar 20, 2012
Mar 20, 2012
401
BAIL_MACRO(PHYSFS_ERR_UNSUPPORTED, NULL);
Aug 30, 2010
Aug 30, 2010
402
} /* LZMA_duplicate */
Nov 5, 2006
Nov 5, 2006
404
Aug 30, 2010
Aug 30, 2010
405
static int LZMA_flush(PHYSFS_Io *io) { return 1; /* no write support. */ }
Aug 30, 2010
Aug 30, 2010
408
static void LZMA_destroy(PHYSFS_Io *io)
Aug 30, 2010
Aug 30, 2010
410
LZMAfile *file = (LZMAfile *) io->opaque;
Aug 30, 2010
Aug 30, 2010
412
if (file->folder != NULL)
Jan 23, 2008
Jan 23, 2008
413
{
Aug 30, 2010
Aug 30, 2010
414
415
416
417
418
419
420
421
422
423
424
425
/* 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)
{
/* Free the cache which might have been allocated by LZMA_read() */
allocator.Free(file->folder->cache);
file->folder->cache = NULL;
}
/* !!! FIXME: we don't free (file) or (file->folder)?! */
} /* if */
} /* LZMA_destroy */
Sep 27, 2006
Sep 27, 2006
426
Aug 30, 2010
Aug 30, 2010
428
429
static const PHYSFS_Io LZMA_Io =
{
Mar 25, 2012
Mar 25, 2012
430
CURRENT_PHYSFS_IO_API_VERSION, NULL,
Aug 30, 2010
Aug 30, 2010
431
432
433
434
435
436
437
LZMA_read,
LZMA_write,
LZMA_seek,
LZMA_tell,
LZMA_length,
LZMA_duplicate,
LZMA_flush,
Mar 25, 2012
Mar 25, 2012
438
LZMA_destroy
Aug 30, 2010
Aug 30, 2010
439
};
Aug 30, 2010
Aug 30, 2010
442
static void *LZMA_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
Aug 30, 2010
Aug 30, 2010
444
PHYSFS_uint8 sig[k7zSignatureSize];
Jan 23, 2008
Jan 23, 2008
445
size_t len = 0;
Sep 27, 2006
Sep 27, 2006
446
LZMAarchive *archive = NULL;
Aug 30, 2010
Aug 30, 2010
448
449
assert(io != NULL); /* shouldn't ever happen. */
Mar 20, 2012
Mar 20, 2012
450
BAIL_IF_MACRO(forWriting, PHYSFS_ERR_READ_ONLY, NULL);
Aug 30, 2010
Aug 30, 2010
451
452
if (io->read(io, sig, k7zSignatureSize) != k7zSignatureSize)
Mar 20, 2012
Mar 20, 2012
453
454
455
return 0;
BAIL_IF_MACRO(!TestSignatureCandidate(sig), PHYSFS_ERR_UNSUPPORTED, NULL);
BAIL_IF_MACRO(!io->seek(io, 0), ERRPASS, NULL);
Sep 27, 2006
Sep 27, 2006
456
457
archive = (LZMAarchive *) allocator.Malloc(sizeof (LZMAarchive));
Mar 20, 2012
Mar 20, 2012
458
BAIL_IF_MACRO(archive == NULL, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
Sep 27, 2006
Sep 27, 2006
459
Jan 23, 2008
Jan 23, 2008
460
lzma_archive_init(archive);
Aug 30, 2010
Aug 30, 2010
461
archive->stream.io = io;
Jan 23, 2008
Jan 23, 2008
463
CrcGenerateTable();
464
SzArDbExInit(&archive->db);
Jan 23, 2008
Jan 23, 2008
465
466
467
468
if (lzma_err(SzArchiveOpen(&archive->stream.inStream,
&archive->db,
&archive->stream.allocImp,
&archive->stream.allocTempImp)) != SZ_OK)
Jan 23, 2008
Jan 23, 2008
470
471
SzArDbExFree(&archive->db, SzFreePhysicsFS);
lzma_archive_exit(archive);
Jan 28, 2010
Jan 28, 2010
472
return NULL; /* Error is set by lzma_err! */
Jan 23, 2008
Jan 23, 2008
475
476
477
478
479
480
len = archive->db.Database.NumFiles * sizeof (LZMAfile);
archive->files = (LZMAfile *) allocator.Malloc(len);
if (archive->files == NULL)
{
SzArDbExFree(&archive->db, SzFreePhysicsFS);
lzma_archive_exit(archive);
Mar 20, 2012
Mar 20, 2012
481
BAIL_MACRO(PHYSFS_ERR_OUT_OF_MEMORY, NULL);
Jan 23, 2008
Jan 23, 2008
482
483
484
485
486
487
488
489
}
/*
* 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
490
len = archive->db.Database.NumFolders * sizeof (LZMAfolder);
Jan 23, 2008
Jan 23, 2008
491
492
493
494
495
archive->folders = (LZMAfolder *) allocator.Malloc(len);
if (archive->folders == NULL)
{
SzArDbExFree(&archive->db, SzFreePhysicsFS);
lzma_archive_exit(archive);
Mar 20, 2012
Mar 20, 2012
496
BAIL_MACRO(PHYSFS_ERR_OUT_OF_MEMORY, NULL);
Jan 23, 2008
Jan 23, 2008
497
}
Nov 5, 2006
Nov 5, 2006
498
499
500
501
502
/*
* 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
503
504
505
506
507
508
memset(archive->folders, 0, len);
if(!lzma_files_init(archive))
{
SzArDbExFree(&archive->db, SzFreePhysicsFS);
lzma_archive_exit(archive);
Mar 20, 2012
Mar 20, 2012
509
BAIL_MACRO(PHYSFS_ERR_OTHER_ERROR, NULL);
Jan 23, 2008
Jan 23, 2008
510
}
Nov 5, 2006
Nov 5, 2006
511
Jan 28, 2010
Jan 28, 2010
512
return archive;
513
514
515
516
517
518
519
520
} /* 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
521
const char *odir, const char *str, size_t flen)
Jan 23, 2008
Jan 23, 2008
523
char *newstr = __PHYSFS_smallAlloc(flen + 1);
524
525
526
if (newstr == NULL)
return;
Jan 23, 2008
Jan 23, 2008
527
528
memcpy(newstr, str, flen);
newstr[flen] = '\0';
529
cb(callbackdata, odir, newstr);
Mar 24, 2007
Mar 24, 2007
530
__PHYSFS_smallFree(newstr);
531
532
533
} /* doEnumCallback */
Nov 28, 2012
Nov 28, 2012
534
static void LZMA_enumerateFiles(void *opaque, const char *dname,
Nov 29, 2012
Nov 29, 2012
535
PHYSFS_EnumFilesCallback cb,
536
537
const char *origdir, void *callbackdata)
{
Jan 23, 2008
Jan 23, 2008
538
539
size_t dlen = strlen(dname),
dlen_inc = dlen + ((dlen > 0) ? 1 : 0);
540
LZMAarchive *archive = (LZMAarchive *) opaque;
Feb 2, 2008
Feb 2, 2008
541
542
543
544
545
LZMAfile *file = NULL,
*lastFile = &archive->files[archive->db.Database.NumFiles];
if (dlen)
{
file = lzma_find_file(archive, dname);
Jan 28, 2010
Jan 28, 2010
546
if (file != NULL) /* if 'file' is NULL it should stay so, otherwise errors will not be handled */
Feb 2, 2008
Feb 2, 2008
547
548
549
550
551
552
file += 1;
}
else
{
file = archive->files;
}
Nov 28, 2012
Nov 28, 2012
554
BAIL_IF_MACRO(file == NULL, PHYSFS_ERR_NOT_FOUND, );
Jan 23, 2008
Jan 23, 2008
556
while (file < lastFile)
Jan 23, 2008
Jan 23, 2008
558
559
560
561
562
563
564
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
566
567
568
569
570
571
572
573
574
file++;
continue;
}
/* Do the actual callback... */
doEnumCallback(cb, callbackdata, origdir, dirNameEnd, strlen(dirNameEnd));
file++;
}
575
576
577
} /* LZMA_enumerateFiles */
Nov 28, 2012
Nov 28, 2012
578
static PHYSFS_Io *LZMA_openRead(void *opaque, const char *name,
Mar 25, 2012
Mar 25, 2012
579
int *fileExists)
580
581
{
LZMAarchive *archive = (LZMAarchive *) opaque;
Jan 23, 2008
Jan 23, 2008
582
LZMAfile *file = lzma_find_file(archive, name);
Aug 30, 2010
Aug 30, 2010
583
PHYSFS_Io *io = NULL;
Sep 27, 2006
Sep 27, 2006
584
Jan 23, 2008
Jan 23, 2008
585
*fileExists = (file != NULL);
Nov 28, 2012
Nov 28, 2012
586
BAIL_IF_MACRO(file == NULL, PHYSFS_ERR_NOT_FOUND, NULL);
Mar 20, 2012
Mar 20, 2012
587
BAIL_IF_MACRO(file->folder == NULL, PHYSFS_ERR_NOT_A_FILE, NULL);
Jun 21, 2009
Jun 21, 2009
589
file->position = 0;
Jan 28, 2010
Jan 28, 2010
590
file->folder->references++; /* Increase refcount for automatic cleanup... */
Nov 5, 2006
Nov 5, 2006
591
Aug 30, 2010
Aug 30, 2010
592
io = (PHYSFS_Io *) allocator.Malloc(sizeof (PHYSFS_Io));
Mar 20, 2012
Mar 20, 2012
593
BAIL_IF_MACRO(io == NULL, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
Aug 30, 2010
Aug 30, 2010
594
595
596
597
memcpy(io, &LZMA_Io, sizeof (*io));
io->opaque = file;
return io;
598
599
600
} /* LZMA_openRead */
Nov 28, 2012
Nov 28, 2012
601
static PHYSFS_Io *LZMA_openWrite(void *opaque, const char *filename)
Mar 22, 2012
Mar 22, 2012
603
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
604
605
606
} /* LZMA_openWrite */
Nov 28, 2012
Nov 28, 2012
607
static PHYSFS_Io *LZMA_openAppend(void *opaque, const char *filename)
Mar 22, 2012
Mar 22, 2012
609
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
610
611
612
} /* LZMA_openAppend */
Nov 28, 2012
Nov 28, 2012
613
static void LZMA_closeArchive(void *opaque)
Sep 27, 2006
Sep 27, 2006
615
616
LZMAarchive *archive = (LZMAarchive *) opaque;
Aug 30, 2010
Aug 30, 2010
617
618
#if 0 /* !!! FIXME: you shouldn't have to do this. */
PHYSFS_uint32 fileIndex = 0, numFiles = archive->db.Database.NumFiles;
Jan 23, 2008
Jan 23, 2008
619
for (fileIndex = 0; fileIndex < numFiles; fileIndex++)
Sep 27, 2006
Sep 27, 2006
620
{
Jan 23, 2008
Jan 23, 2008
621
622
LZMA_fileClose(&archive->files[fileIndex]);
} /* for */
Aug 30, 2010
Aug 30, 2010
623
#endif
Sep 27, 2006
Sep 27, 2006
625
SzArDbExFree(&archive->db, SzFreePhysicsFS);
Aug 30, 2010
Aug 30, 2010
626
archive->stream.io->destroy(archive->stream.io);
Jan 23, 2008
Jan 23, 2008
627
lzma_archive_exit(archive);
Mar 24, 2012
Mar 24, 2012
628
} /* LZMA_closeArchive */
Nov 28, 2012
Nov 28, 2012
631
static int LZMA_remove(void *opaque, const char *name)
Mar 22, 2012
Mar 22, 2012
633
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
634
635
636
} /* LZMA_remove */
Nov 28, 2012
Nov 28, 2012
637
static int LZMA_mkdir(void *opaque, const char *name)
Mar 22, 2012
Mar 22, 2012
639
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
640
641
} /* LZMA_mkdir */
Nov 28, 2012
Nov 28, 2012
642
static int LZMA_stat(void *opaque, const char *filename,
Mar 25, 2012
Mar 25, 2012
643
int *exists, PHYSFS_Stat *stat)
Feb 15, 2010
Feb 15, 2010
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
{
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
675
return 1;
Feb 15, 2010
Feb 15, 2010
676
677
} /* LZMA_stat */
678
679
680
const PHYSFS_Archiver __PHYSFS_Archiver_LZMA =
{
Nov 28, 2012
Nov 28, 2012
681
CURRENT_PHYSFS_ARCHIVER_API_VERSION,
Mar 25, 2012
Mar 25, 2012
682
683
684
685
686
687
{
"7Z",
"LZMA (7zip) format",
"Dennis Schridde <devurandom@gmx.net>",
"http://icculus.org/physfs/",
},
Nov 29, 2012
Nov 29, 2012
688
0, /* supportsSymlinks */
689
690
691
692
693
694
695
LZMA_openArchive, /* openArchive() method */
LZMA_enumerateFiles, /* enumerateFiles() method */
LZMA_openRead, /* openRead() method */
LZMA_openWrite, /* openWrite() method */
LZMA_openAppend, /* openAppend() method */
LZMA_remove, /* remove() method */
LZMA_mkdir, /* mkdir() method */
Mar 24, 2012
Mar 24, 2012
696
LZMA_closeArchive, /* closeArchive() method */
Aug 30, 2010
Aug 30, 2010
697
LZMA_stat /* stat() method */
Mar 9, 2007
Mar 9, 2007
700
#endif /* defined PHYSFS_SUPPORTS_7Z */
701
702
/* end of lzma.c ... */