/
lzma.c
735 lines (580 loc) · 21.7 KB
1
2
3
/*
* LZMA support routines for PhysicsFS.
*
4
* Please see the file lzma.txt in the lzma/ directory.
5
*
6
* This file was written by Dennis Schridde, with some peeking at "7zMain.c"
7
8
9
* by Igor Pavlov.
*/
10
#if (defined PHYSFS_SUPPORTS_7Z)
11
12
13
#include <stdlib.h>
#include <string.h>
14
#include <time.h>
15
16
17
18
19
20
#include "physfs.h"
#define __PHYSICSFS_INTERNAL__
#include "physfs_internal.h"
21
22
23
#include "lzma/C/7zCrc.h"
#include "lzma/C/Archive/7z/7zIn.h"
#include "lzma/C/Archive/7z/7zExtract.h"
24
25
26
27
/* 7z internal from 7zIn.c */
extern int TestSignatureCandidate(Byte *testBytes);
28
29
30
31
32
#ifdef _LZMA_IN_CB
# define BUFFER_SIZE (1 << 12)
#endif /* _LZMA_IN_CB */
33
34
35
36
37
38
/*
* Carries filestream metadata through 7z
*/
typedef struct _FileInputStream
39
{
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;
48
49
/*
50
* In the 7z format archives are splited into blocks, those are called folders
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 */
57
58
PHYSFS_uint8 *cache; /* Cached folder */
size_t size; /* Size of folder */
59
60
61
62
63
64
} LZMAfolder;
/*
* Set by LZMA_openArchive(), except folder which gets it's values
* in LZMA_read()
*/
65
typedef struct _LZMAarchive
66
{
67
68
struct _LZMAfile *files; /* Array of files, size == archive->db.Database.NumFiles */
LZMAfolder *folders; /* Array of folders, size == archive->db.Database.NumFolders */
69
CArchiveDatabaseEx db; /* For 7z: Database */
70
FileInputStream stream; /* For 7z: Input file incl. read and seek callbacks */
71
72
} LZMAarchive;
73
74
/* Set by LZMA_openArchive(), except offset which is set by LZMA_read() */
typedef struct _LZMAfile
75
{
76
PHYSFS_uint32 index; /* Index of file in archive */
77
LZMAarchive *archive; /* Link to corresponding archive */
78
79
LZMAfolder *folder; /* Link to corresponding folder */
CFileItem *item; /* For 7z: File info, eg. name, size */
80
size_t offset; /* Offset in folder */
81
82
size_t position; /* Current "virtual" position in file */
} LZMAfile;
83
84
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 */
100
101
102
103
/* Filesystem implementations to be passed to 7z */
#ifdef _LZMA_IN_CB
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!
*/
108
109
SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxReqSize,
size_t *processedSize)
110
{
111
112
113
114
115
116
117
FileInputStream *s = (FileInputStream *)(object - offsetof(FileInputStream, inStream)); // HACK!
PHYSFS_sint64 processedSizeLoc = 0;
if (maxReqSize > BUFFER_SIZE)
maxReqSize = BUFFER_SIZE;
processedSizeLoc = __PHYSFS_platformRead(s->file, s->buffer, 1, maxReqSize);
*buffer = s->buffer;
118
119
if (processedSize != NULL)
*processedSize = (size_t) processedSizeLoc;
120
121
122
123
124
return SZ_OK;
} /* SzFileReadImp */
#else
125
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!
*/
130
131
132
SZ_RESULT SzFileReadImp(void *object, void *buffer, size_t size,
size_t *processedSize)
{
133
FileInputStream *s = (FileInputStream *)((unsigned long)object - offsetof(FileInputStream, inStream)); // HACK!
134
size_t processedSizeLoc = __PHYSFS_platformRead(s->file, buffer, 1, size);
135
136
if (processedSize != 0)
*processedSize = processedSizeLoc;
137
138
139
return SZ_OK;
} /* SzFileReadImp */
140
#endif
141
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)
{
148
FileInputStream *s = (FileInputStream *)((unsigned long)object - offsetof(FileInputStream, inStream)); // HACK!
149
if (__PHYSFS_platformSeek(s->file, (PHYSFS_uint64) pos))
150
151
152
153
154
return SZ_OK;
return SZE_FAIL;
} /* SzFileSeekImp */
155
/*
156
* Translate Microsoft FILETIME (used by 7zip) into UNIX timestamp
157
*/
158
static PHYSFS_sint64 lzma_filetime_to_unix_timestamp(CArchiveFileTime *ft)
159
{
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 */
180
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
212
213
214
215
216
217
/*
* 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)
{
LZMAfile *file = bsearch(name, archive->files, archive->db.Database.NumFiles, sizeof(*archive->files), lzma_file_cmp_stdlib); // FIXME: Should become __PHYSFS_search!!!
BAIL_IF_MACRO(file == NULL, ERR_NO_SUCH_FILE, NULL);
return(file);
} /* lzma_find_file */
218
219
220
/*
221
* Load metadata for the file at given index
222
*/
223
static int lzma_file_init(LZMAarchive *archive, PHYSFS_uint32 fileIndex)
224
{
225
226
227
228
229
230
231
232
233
234
235
236
LZMAfile *file = &archive->files[fileIndex];
PHYSFS_uint32 folderIndex = archive->db.FileIndexToFolderIndexMap[fileIndex];
file->index = fileIndex; // Store index into 7z array, since we sort our own.
file->archive = archive;
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
file->position = 0;
file->offset = 0; /* Offset will be set by LZMA_read() */
return(1);
} /* lzma_load_file */
237
238
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;
245
246
for (fileIndex = 0; fileIndex < numFiles; fileIndex++ )
247
{
248
if (!lzma_file_init(archive, fileIndex))
249
{
250
251
252
253
254
255
256
257
return(0); // FALSE on failure
}
} /* for */
__PHYSFS_sort(archive->files, numFiles, lzma_file_cmp, lzma_file_swap);
return(1);
} /* lzma_load_files */
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
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)
{
328
LZMAfile *file = (LZMAfile *) opaque;
329
330
331
332
size_t wantedSize = objSize*objCount;
size_t remainingSize = file->item->Size - file->position;
size_t fileSize = 0;
333
334
335
BAIL_IF_MACRO(wantedSize == 0, NULL, 0); /* quick rejection. */
BAIL_IF_MACRO(remainingSize == 0, ERR_PAST_EOF, 0);
336
337
if (remainingSize < wantedSize)
338
{
339
340
wantedSize = remainingSize - (remainingSize % objSize);
objCount = (PHYSFS_uint32) (remainingSize / objSize);
341
BAIL_IF_MACRO(objCount == 0, ERR_PAST_EOF, 0); /* quick rejection. */
342
__PHYSFS_setError(ERR_PAST_EOF); /* this is always true here. */
343
344
} /* if */
345
/* Only decompress the folder if it is not allready cached */
346
if (file->folder->cache == NULL)
347
348
{
int rc = lzma_err(SzExtract(
349
350
351
&file->archive->stream.inStream, /* compressed data */
&file->archive->db, /* 7z's database, containing everything */
file->index, /* Index into database arrays */
352
/* Index of cached folder, will be changed by SzExtract */
353
&file->folder->index,
354
/* Cache for decompressed folder, allocated/freed by SzExtract */
355
&file->folder->cache,
356
/* Size of cache, will be changed by SzExtract */
357
&file->folder->size,
358
/* Offset of this file inside the cache, set by SzExtract */
359
&file->offset,
360
&fileSize, /* Size of this file */
361
362
&file->archive->stream.allocImp,
&file->archive->stream.allocTempImp));
363
364
if (rc != SZ_OK)
365
return -1;
366
} /* if */
367
368
/* Copy wanted bytes over from cache to outBuffer */
369
370
371
372
373
374
memcpy(outBuffer,
(file->folder->cache +
file->offset + file->position),
wantedSize);
file->position += wantedSize; /* Increase virtual position */
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)
{
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)
{
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)
{
402
LZMAfile *file = (LZMAfile *) opaque;
403
404
BAIL_IF_MACRO(offset < 0, ERR_SEEK_OUT_OF_RANGE, 0);
405
406
407
BAIL_IF_MACRO(offset > file->item->Size, ERR_PAST_EOF, 0);
file->position = offset; /* We only use a virtual position... */
408
409
return 1;
410
411
412
413
414
} /* LZMA_seek */
static PHYSFS_sint64 LZMA_fileLength(fvoid *opaque)
{
415
416
LZMAfile *file = (LZMAfile *) opaque;
return (file->item->Size);
417
418
419
420
421
} /* LZMA_fileLength */
static int LZMA_fileClose(fvoid *opaque)
{
422
LZMAfile *file = (LZMAfile *) opaque;
423
424
BAIL_IF_MACRO(file->folder == NULL, ERR_NOT_A_FILE, 0);
425
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)
430
{
431
432
433
/* Free the cache which might have been allocated by LZMA_read() */
allocator.Free(file->folder->cache);
file->folder->cache = NULL;
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);
450
/* Read signature bytes */
451
if (__PHYSFS_platformRead(in, sig, k7zSignatureSize, 1) != 1)
452
453
{
__PHYSFS_platformClose(in); // Don't forget to close the file before returning...
454
BAIL_MACRO(NULL, 0);
455
}
456
457
458
__PHYSFS_platformClose(in);
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)
{
466
size_t len = 0;
467
LZMAarchive *archive = NULL;
468
469
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, NULL);
470
BAIL_IF_MACRO(!LZMA_isArchive(name,forWriting), ERR_UNSUPPORTED_ARCHIVE, 0);
471
472
473
474
archive = (LZMAarchive *) allocator.Malloc(sizeof (LZMAarchive));
BAIL_IF_MACRO(archive == NULL, ERR_OUT_OF_MEMORY, NULL);
475
lzma_archive_init(archive);
476
477
if ( (archive->stream.file = __PHYSFS_platformOpenRead(name)) == NULL )
478
{
479
480
481
482
__PHYSFS_platformClose(archive->stream.file);
lzma_archive_exit(archive);
return(NULL); // Error is set by platformOpenRead!
}
483
484
CrcGenerateTable();
485
SzArDbExInit(&archive->db);
486
487
488
489
if (lzma_err(SzArchiveOpen(&archive->stream.inStream,
&archive->db,
&archive->stream.allocImp,
&archive->stream.allocTempImp)) != SZ_OK)
490
{
491
492
493
494
SzArDbExFree(&archive->db, SzFreePhysicsFS);
__PHYSFS_platformClose(archive->stream.file);
lzma_archive_exit(archive);
return NULL; // Error is set by lzma_err!
495
496
} /* if */
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);
513
len = archive->db.Database.NumFolders * sizeof (LZMAfolder);
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);
}
522
523
524
525
526
/*
* Init with 0 so we know when a folder is already cached
* Values will be set by LZMA_read()
*/
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);
}
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,
546
const char *odir, const char *str, size_t flen)
547
{
548
char *newstr = __PHYSFS_smallAlloc(flen + 1);
549
550
551
if (newstr == NULL)
return;
552
553
memcpy(newstr, str, flen);
newstr[flen] = '\0';
554
cb(callbackdata, odir, newstr);
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)
{
563
564
size_t dlen = strlen(dname),
dlen_inc = dlen + ((dlen > 0) ? 1 : 0);
565
LZMAarchive *archive = (LZMAarchive *) opaque;
566
567
568
569
570
571
572
573
574
575
576
577
LZMAfile *file = NULL,
*lastFile = &archive->files[archive->db.Database.NumFiles];
if (dlen)
{
file = lzma_find_file(archive, dname);
if (file != NULL) // if 'file' is NULL it should stay so, otherwise errors will not be handled
file += 1;
}
else
{
file = archive->files;
}
578
579
BAIL_IF_MACRO(file == NULL, ERR_NO_SUCH_FILE, );
580
581
while (file < lastFile)
582
{
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 */
590
{
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)
{
605
LZMAarchive *archive = (LZMAarchive *) opaque;
606
return(lzma_find_file(archive, name) != NULL);
607
608
609
610
} /* LZMA_exists */
static PHYSFS_sint64 LZMA_getLastModTime(dvoid *opaque,
611
612
const char *name,
int *fileExists)
613
{
614
615
616
617
618
619
620
621
622
LZMAarchive *archive = (LZMAarchive *) opaque;
LZMAfile *file = lzma_find_file(archive, name);
*fileExists = (file != NULL);
BAIL_IF_MACRO(file == NULL, NULL, -1);
BAIL_IF_MACRO(!file->item->IsLastWriteTimeDefined, NULL, -1); // write-time may not be defined for every file
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)
{
628
LZMAarchive *archive = (LZMAarchive *) opaque;
629
LZMAfile *file = lzma_find_file(archive, name);
630
631
*fileExists = (file != NULL);
632
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;
646
LZMAfile *file = lzma_find_file(archive, name);
647
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);
651
652
file->folder->references++; // Increase refcount for automatic cleanup...
653
654
return(file);
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
} /* 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)
{
672
LZMAarchive *archive = (LZMAarchive *) opaque;
673
PHYSFS_uint32 fileIndex = 0, numFiles = archive->db.Database.NumFiles;
674
675
for (fileIndex = 0; fileIndex < numFiles; fileIndex++)
676
{
677
678
LZMA_fileClose(&archive->files[fileIndex]);
} /* for */
679
680
SzArDbExFree(&archive->db, SzFreePhysicsFS);
681
682
__PHYSFS_platformClose(archive->stream.file);
lzma_archive_exit(archive);
683
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
} /* 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 */
};
732
#endif /* defined PHYSFS_SUPPORTS_7Z */
733
734
/* end of lzma.c ... */