22
21
#include "clamav-config.h"
30
27
#include <string.h>
33
28
#include <sys/types.h>
36
29
#include <sys/stat.h>
41
38
#include "others.h"
42
#else /* HAVE_SYS_MMAN_H */
42
46
#include "clamav.h"
43
47
#include "scanners.h"
46
#define EC32(x) le32_to_host(x)
47
#define EC16(x) le16_to_host(x)
49
static int real_scansis(FILE *, cli_ctx *, const char *);
50
static int real_scansis9x(FILE *, cli_ctx *, const char *);
52
/*************************************************
53
This is the wrapper to the old and new
54
format handlers - see below.
55
*************************************************/
57
int cli_scansis(int desc, cli_ctx *ctx) {
63
cli_dbgmsg("in scansis()\n");
65
if (!(tmpd = cli_gentemp(ctx->engine->tmpdir)))
67
if (mkdir(tmpd, 0700)) {
68
cli_dbgmsg("SIS: Can't create temporary directory %s\n", tmpd);
72
if (ctx->engine->keeptmp)
73
cli_dbgmsg("SIS: Extracting files to %s\n", tmpd);
75
if ((i=dup(desc))==-1) {
76
cli_dbgmsg("SIS: dup() failed\n");
81
if (!(f=fdopen(i, "rb"))) {
82
cli_dbgmsg("SIS: fdopen() failed\n");
89
if (fread(uid, 16, 1, f)!=1) {
90
cli_dbgmsg("SIS: unable to read UIDs\n");
97
cli_dbgmsg("SIS: UIDS %x %x %x - %x\n", EC32(uid[0]), EC32(uid[1]), EC32(uid[2]), EC32(uid[3]));
98
if (uid[2]==EC32(0x10000419))
99
i=real_scansis(f, ctx, tmpd);
100
else if(uid[0]==EC32(0x10201a7a)) {
101
i=real_scansis9x(f, ctx, tmpd);
104
if (!ctx->engine->keeptmp)
113
/*************************************************
114
This is the handler for the old (pre 0.9)
116
*************************************************/
119
PKGfile, /* I'm a real file */
120
PKGlangfile, /* Ich bin auch eine Datei */
121
PKGoption, /* options */
123
PKGelsif, /* #ELSIF */
125
PKGendif /* #ENDIF */
143
memcpy(buff, buff+smax-sleft, sleft); \
144
if ((smax=fread(buff+sleft,1,BUFSIZ-sleft,f)+sleft)<4) { \
145
cli_dbgmsg("SIS: EOF\n"); \
151
VAR = cli_readint32(&buff[smax-sleft]); \
155
#define GETD2(VAR) {\
157
memcpy(buff, buff+smax-sleft, sleft); \
158
if ((smax=fread(buff+sleft,1,BUFSIZ-sleft,f)+sleft)<4) { \
159
cli_dbgmsg("SIS: EOF\n"); \
166
VAR = cli_readint32(&buff[smax-sleft]); \
171
if (sleft>=(N)) sleft-=(N); \
174
cli_dbgmsg("SIS: Refusing to seek back\n"); \
178
fseek(f, (N)-sleft, SEEK_CUR); \
179
sleft=smax=fread(buff,1,BUFSIZ,f); \
182
const char *sislangs[] = {"UNKNOWN", "UK English","French", "German", "Spanish", "Italian", "Swedish", "Danish", "Norwegian", "Finnish", "American", "Swiss French", "Swiss German", "Portuguese", "Turkish", "Icelandic", "Russian", "Hungarian", "Dutch", "Belgian Flemish", "Australian English", "Belgian French", "Austrian German", "New Zealand English", "International French", "Czech", "Slovak", "Polish", "Slovenian", "Taiwanese Chinese", "Hong Kong Chinese", "PRC Chinese", "Japanese", "Thai", "Afrikaans", "Albanian", "Amharic", "Arabic", "Armenian", "Tagalog", "Belarussian", "Bengali", "Bulgarian", "Burmese", "Catalan", "Croation", "Canadian English", "International English", "South African English", "Estonian", "Farsi", "Canadian French", "Gaelic", "Georgian", "Greek", "Cyprus Greek", "Gujarati", "Hebrew", "Hindi", "Indonesian", "Irish", "Swiss Italian", "Kannada", "Kazakh", "Kmer", "Korean", "Lao", "Latvian", "Lithuanian", "Macedonian", "Malay", "Malayalam", "Marathi", "Moldovian", "Mongolian", "Norwegian Nynorsk", "Brazilian Portuguese", "Punjabi", "Romanian", "Serbian", "Sinhalese", "Somali", "International Spanish", "American Spanish", "Swahili", "Finland Swedish", "Reserved", "Tamil", "Telugu", "Tibetan", "Tigrinya", "Cyprus Turkish", "Turkmen", "Ukrainian", "Urdu", "Reserved", "Vietnamese", "Welsh", "Zulu", "Other"};
183
#define MAXLANG (sizeof(sislangs)/sizeof(sislangs[0]))
185
static char *getsistring(FILE *f, uint32_t ptr, uint32_t len) {
189
if (!len) return NULL;
190
if (len>400) len=400;
191
name = cli_malloc(len);
193
cli_dbgmsg("SIS: OOM\n");
196
fseek(f, ptr, SEEK_SET);
197
if (fread(name, len, 1, f)!=1) {
198
cli_dbgmsg("SIS: Unable to read string\n");
202
for (i = 0 ; i < len; i+=2) name[i/2] = name[i];
207
static int spamsisnames(FILE *f, uint16_t langs, const char **alangs) {
208
uint32_t *lens, *ptrs;
211
if (!(lens = cli_malloc(sizeof(uint32_t) * langs * 2))) {
212
cli_dbgmsg("SIS: OOM\n");
215
if (fread(lens, sizeof(uint32_t) * langs * 2, 1, f)!=1) {
216
cli_dbgmsg("SIS: Unable to read lengths and pointers\n");
222
for (j=0; j<langs; j++) {
223
char *name = getsistring(f,EC32(ptrs[j]),EC32(lens[j]));
225
cli_dbgmsg("\t%s (%s - @%x, len %d)\n", name, alangs[j], EC32(ptrs[j]), EC32(lens[j]));
233
static int real_scansis(FILE *f, cli_ctx *ctx, const char *tmpd) {
261
unsigned int i, sleft=0, smax=0, umped=0;
262
uint8_t compd, buff[BUFSIZ];
264
if (fread(&sis,sizeof(sis),1,f)!=1) {
265
cli_dbgmsg("SIS: Unable to read header\n");
268
/* cli_dbgmsg("SIS HEADER INFO: \nFile checksum: %x\nLangs: %d\nFiles: %d\nDeps: %d\nUsed langs: %d\nInstalled files: %d\nDest drive: %d\nCapabilities: %d\nSIS Version: %d\nFlags: %x\nType: %d\nVersion: %d.%d.%d\nLangs@: %x\nFiles@: %x\nDeps@: %x\nCerts@: %x\nName@: %x\nSig@: %x\nCaps@: %x\nUspace: %d\nNspace: %d\n\n", sis.filesum, sis.langs, sis.files, sis.deps, sis.ulangs, sis.instfiles, sis.drive, sis.caps, sis.version, sis.flags, sis.type, sis.verhi, sis.verlo, sis.versub, sis.plangs, sis.pfiles, sis.pdeps, sis.pcerts, sis.pnames, sis.psig, sis.pcaps, sis.uspace, sis.nspace);
271
#if WORDS_BIGENDIAN != 0
272
sis.langs=EC16(sis.langs);
273
sis.files=EC16(sis.files);
274
sis.deps=EC16(sis.deps);
275
sis.flags=EC16(sis.flags);
276
sis.plangs=EC32(sis.plangs);
277
sis.pfiles=EC32(sis.pfiles);
278
sis.pdeps=EC32(sis.pdeps);
279
sis.pnames=EC32(sis.pnames);
280
sis.pcaps=EC32(sis.pcaps);
51
#define EC32(x) le32_to_host(x) /* Convert little endian to host */
52
#define EC16(x) le16_to_host(x) /* Convert little endian to host */
54
extern short cli_leavetemps_flag;
56
static const char *langcodes[] = {
57
"", "EN", "FR", "GE", "SP", "IT", "SW", "DA", "NO", "FI", "AM",
58
"SF", "SG", "PO", "TU", "IC", "RU", "HU", "DU", "BL", "AU", "BG",
59
"AS", "NZ", "IF", "CS", "SK", "PL", "SL", "TC", "HK", "ZH", "JA",
60
"TH", "AF", "SQ", "AH", "AR", "HY", "TL", "BE", "BN", "BG", "MY",
61
"CA", "HR", "CE", "IE", "SF", "ET", "FA", "CF", "GD", "KA", "EL",
62
"CG", "GU", "HE", "HI", "IN", "GA", "SZ", "KN", "KK", "KM", "KO",
63
"LO", "LV", "LT", "MK", "MS", "ML", "MR", "MO", "MN", "NN", "BP",
64
"PA", "RO", "SR", "SI", "SO", "OS", "LS", "SH", "FS", "TA", "TE",
65
"BO", "TI", "CT", "TK", "UK", "UR", "", "VI", "CY", "ZU"
283
if (!sis.langs || sis.langs>=MAXLANG) {
284
cli_dbgmsg("SIS: Too many or too few languages found\n");
287
fseek(f, sis.plangs, SEEK_SET);
288
if (!(llangs=cli_malloc(sis.langs * sizeof(uint16_t)))) {
289
cli_dbgmsg("SIS: OOM\n");
292
if (fread(llangs, sis.langs * sizeof(uint16_t), 1, f)!=1) {
293
cli_dbgmsg("SIS: Unable to read languages\n");
297
if (!(alangs=cli_malloc(sis.langs * sizeof(char *)))) {
298
cli_dbgmsg("SIS: OOM\n");
302
for (i = 0; i< sis.langs; i++)
303
alangs[i]=EC32(llangs[i])<MAXLANG ? sislangs[EC32(llangs[i])] : sislangs[0];
307
cli_dbgmsg("SIS: Application without a name?\n");
309
fseek(f, sis.pnames, SEEK_SET);
310
cli_dbgmsg("SIS: Application name:\n");
311
if (!spamsisnames(f, sis.langs, alangs)) {
318
cli_dbgmsg("SIS: Application without capabilities?\n");
320
fseek(f, sis.pcaps, SEEK_SET);
321
cli_dbgmsg("SIS: Provides:\n");
322
if (!spamsisnames(f, sis.langs, alangs)) {
329
cli_dbgmsg("SIS: No dependencies set for this application\n");
331
cli_dbgmsg("SIS: Depends on:\n");
332
for (i = 0; i< sis.deps; i++) {
340
fseek(f, sis.pdeps + i*(sizeof(dep) + sis.langs*2*sizeof(uint32_t)), SEEK_SET);
341
if (fread(&dep, sizeof(dep), 1, f)!=1) {
342
cli_dbgmsg("SIS: Unable to read dependencies\n");
344
cli_dbgmsg("\tUID: %x v. %d.%d.%d\n\taka:\n", EC32(dep.uid), EC16(dep.verhi), EC16(dep.verlo), EC32(dep.versub));
345
if (!spamsisnames(f, sis.langs, alangs)) {
353
compd = !(sis.flags & 0x0008);
354
cli_dbgmsg("SIS: Package is%s compressed\n", (compd)?"":" not");
356
fseek(f, sis.pfiles, SEEK_SET);
357
for (i=0; i<sis.files; i++) {
358
uint32_t pkgtype, fcount=1;
362
cli_dbgmsg("SIS: Pkgtype: %d\n", pkgtype);
367
uint32_t ftype,options,ssname,psname,sdname,pdname;
369
uint32_t *ptrs, *lens, *olens;
387
sftype = "component";
402
sftype = "conatiner sis";
405
sftype = "uninstall text";
408
sftype = "not to be intalled";
413
cli_dbgmsg("SIS: File details:\n\tOptions: %d\n\tType: %s\n", options, sftype);
415
if ((fn=getsistring(f, psname, ssname))) {
416
cli_dbgmsg("\tOriginal filename: %s\n", fn);
419
if ((fn=getsistring(f, pdname, sdname))) {
420
cli_dbgmsg("\tInstalled to: %s\n", fn);
423
fseek(f,fpos,SEEK_SET);
425
if (!(ptrs=cli_malloc(fcount*sizeof(uint32_t)*3))) {
426
cli_dbgmsg("\tOOM\n");
431
olens=&ptrs[fcount*2];
432
for (j=0; j<fcount; j++)
434
for (j=0; j<fcount; j++)
436
for (j=0; j<fcount; j++)
445
for (j=0; j<fcount; j++) {
450
cli_dbgmsg("\tSkipping empty file\n");
453
if (cli_checklimits("sis", ctx,lens[j], 0, 0)!=CL_CLEAN) continue;
454
cli_dbgmsg("\tUnpacking lang#%d - ptr:%x csize:%x osize:%x\n", j, ptrs[j], lens[j], olens[j]);
455
if (!(comp=cli_malloc(lens[j]))) {
456
cli_dbgmsg("\tOOM\n");
461
fseek(f,ptrs[j],SEEK_SET);
462
if (fread(comp, lens[j], 1, f)!=1) {
463
cli_dbgmsg("\tSkipping ghost or otherwise out of archive file\n");
468
if (olens[j]<=lens[j]*3 && cli_checklimits("sis", ctx, lens[j]*3, 0, 0)==CL_CLEAN)
470
else if (cli_checklimits("sis", ctx, olens[j], 0, 0)==CL_CLEAN)
477
if (!(decomp=cli_malloc(olen))) {
478
cli_dbgmsg("\tOOM\n");
484
if (uncompress(decomp, &olen, comp, lens[j])!=Z_OK) {
485
cli_dbgmsg("\tUnpacking failure\n");
495
snprintf(ofn, 1024, "%s"PATHSEP"sis%02d", tmpd, umped);
497
if ((fd=open(ofn, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0600))==-1) {
498
cli_errmsg("SIS: unable to create output file %s - aborting.", ofn);
504
if (cli_writen(fd, decomp, olen)!=(int)olen) {
512
if (cli_magic_scandesc(fd, ctx) == CL_VIRUS) {
72
#define SIS_MAX_NAME 512
73
#define SIS_MAX_SIZE 134217728
75
static char *sis_utf16_decode(const char *str, uint32_t length)
81
if(!length || length % 2) {
82
cli_warnmsg("SIS: sis_utf16_decode: Broken filename (length == %d)\n", length);
86
if(!(decoded = cli_calloc(length / 2 + 1, sizeof(char))))
89
for(i = 0, j = 0; i < length; i += 2, j++) {
90
decoded[j] = str[i + 1] << 4;
99
static int sis_extract_simple(int fd, char *mfile, uint32_t length, uint32_t offset, uint16_t nlangs, uint8_t compressed, uint8_t *ifile, const char *dir, cli_ctx *ctx)
101
const char *typedir = NULL;
102
char *sname = NULL, *dname = NULL, *subdir, *fname, *buff;
104
uint8_t get_dname = 1;
105
uint32_t namelen, nameoff, filelen, fileoff;
111
if(offset + 24 + 8 * nlangs >= length) {
112
cli_errmsg("SIS: sis_extract_simple: Broken file record\n");
116
switch(cli_readint32(mfile + offset)) {
118
cli_dbgmsg("SIS: File type: Standard file\n");
119
typedir = "standard";
122
cli_dbgmsg("SIS: File type: Text file\n");
127
cli_dbgmsg("SIS: File type: Component file\n");
128
typedir = "component";
132
cli_dbgmsg("SIS: File type: Run file\n");
134
switch(cli_readint32(mfile + offset + 4)) {
136
cli_dbgmsg("SIS: * During installation only\n");
139
cli_dbgmsg("SIS: * During removal only\n");
142
cli_dbgmsg("SIS: * During installation and removal\n");
145
cli_dbgmsg("SIS: * Ends when installation finished\n");
148
cli_dbgmsg("SIS: * Waits until closed before continuing\n");
151
cli_warnmsg("SIS: sis_extract_simple: Unknown value in file details\n");
155
cli_dbgmsg("SIS: File type: Null file\n");
158
cli_dbgmsg("SIS: File type: MIME file\n");
161
cli_warnmsg("SIS: Unknown file type in file record\n");
165
namelen = (uint32_t) cli_readint32(mfile + offset + 8);
166
if(namelen > SIS_MAX_NAME) {
167
cli_warnmsg("SIS: sis_extract_simple: Source name too long and will not be decoded\n");
169
nameoff = cli_readint32(mfile + offset + 12);
170
if(nameoff >= length || nameoff + namelen >= length) {
171
cli_errmsg("SIS: sis_extract_simple: Broken source name data\n");
175
if((sname = sis_utf16_decode(mfile + nameoff, namelen)))
176
cli_dbgmsg("SIS: Source name: %s\n", sname);
178
cli_warnmsg("SIS: Source name not decoded\n");
181
/* Destination name */
183
namelen = (uint32_t) cli_readint32(mfile + offset + 16);
184
if(namelen > SIS_MAX_NAME) {
185
cli_warnmsg("SIS: sis_extract_simple: Destination name too long and will not be decoded\n");
187
nameoff = cli_readint32(mfile + offset + 20);
188
if(nameoff >= length || nameoff + namelen >= length) {
189
cli_errmsg("SIS: sis_extract_simple: Broken destination name data\n");
195
if((dname = sis_utf16_decode(mfile + nameoff, namelen)))
196
cli_dbgmsg("SIS: Destination name: %s\n", dname);
198
cli_warnmsg("SIS: Destination name not decoded\n");
202
if(!cli_leavetemps_flag) {
211
if(!(subdir = cli_malloc(strlen(dir) + strlen(typedir) + 2)))
213
sprintf(subdir, "%s/%s", dir, typedir);
215
if(!(subdir = cli_strdup(dir)))
219
if(stat(subdir, &sb) == -1) {
220
if(mkdir(subdir, 0700) == -1) {
226
for(i = 0; i < nlangs; i++) {
227
filelen = cli_readint32(mfile + offset + 24 + 4 * i);
228
fileoff = cli_readint32(mfile + offset + 24 + 4 * i + 4 * nlangs);
230
if(fileoff == length) {
231
cli_dbgmsg("SIS: Null file (installation record)\n");
234
} else if (fileoff > length) {
236
cli_errmsg("SIS: sis_extract_simple: Broken file data (fileoff)\n");
240
cli_dbgmsg("SIS: Null file (installation track)\n");
245
if(filelen >= length || filelen + fileoff > length) {
246
cli_errmsg("SIS: sis_extract_simple: Broken file data (filelen, fileoff)\n");
251
if(!(fname = cli_gentemp(subdir))) {
257
csize = (uLong) filelen;
258
filelen = cli_readint32(mfile + offset + 24 + 4 * i + 8 * nlangs);
259
osize = (uLongf) filelen;
262
cli_dbgmsg("SIS: Empty file, skipping\n");
267
cli_dbgmsg("SIS: Compressed size: %d\n", csize);
268
cli_dbgmsg("SIS: Original size: %d\n", osize);
270
if(ctx->limits && ctx->limits->maxfilesize && osize > ctx->limits->maxfilesize) {
271
cli_dbgmsg("SIS: Size exceeded (%d, max: %ld)\n", osize, ctx->limits->maxfilesize);
273
*ctx->virname = "SIS.ExceededFileSize";
278
/* osize is not reliable so continue */
281
if((osize <= 3 * csize) || (ctx->limits && ctx->limits->maxfilesize && osize > ctx->limits->maxfilesize))
284
if(!(buff = cli_malloc((size_t) osize))) {
285
cli_errmsg("SIS: sis_extract_simple: Can't allocate decompression buffer\n");
291
if(uncompress((Bytef *) buff, &osize , (Bytef *) mfile + fileoff, csize) != Z_OK) {
292
cli_errmsg("SIS: sis_extract_simple: File decompression failed\n");
299
if(osize != (uLongf) filelen) {
300
cli_dbgmsg("SIS: WARNING: Real original size: %u\n", osize);
301
filelen = (uint32_t) osize;
305
buff = mfile + fileoff;
308
if((desc = open(fname, O_CREAT|O_WRONLY|O_TRUNC|O_BINARY, S_IRUSR|S_IWUSR)) == -1) {
309
cli_errmsg("SIS: sis_extract_simple: Can't create new file %s\n", fname);
317
if((uint32_t) cli_writen(desc, buff, filelen) != filelen) {
318
cli_errmsg("SIS: sis_extract_simple: Can't write %d bytes to %s\n", filelen, fname);
326
cli_dbgmsg("SIS: File decompressed into %s\n", fname);
328
cli_dbgmsg("SIS: File saved into %s\n", fname);
331
if(close(desc) == -1) {
332
cli_errmsg("SIS: sis_extract_simple: Can't close descriptor %d\n", desc);
350
int cli_scansis(int desc, cli_ctx *ctx)
352
struct sis_file_hdr file_hdr;
353
struct sis_file_hdr6 file_hdr6;
354
uint8_t release = 0, compressed, ifile = 0;
355
uint16_t opts, nlangs, *langrecs, nfiles;
358
char *mfile = NULL, *langs, *dir;
363
if(fstat(desc, &sb) == -1) {
364
cli_errmsg("SIS: fstat() failed\n");
368
if(sb.st_size < sizeof(struct sis_file_hdr)) {
369
cli_dbgmsg("SIS: Broken or not a SIS file (too small)\n");
375
if(length <= SIS_MAX_SIZE) {
376
mfile = (char *) mmap(NULL, length, PROT_READ, MAP_PRIVATE, desc, 0);
377
if(mfile == MAP_FAILED) {
378
cli_errmsg("SIS: mmap() failed\n");
381
cli_dbgmsg("SIS: mmap'ed file\n");
382
memcpy(&file_hdr, mfile, sizeof(struct sis_file_hdr));
385
cli_warnmsg("SIS: File too large (> %d)\n", SIS_MAX_SIZE);
389
if(EC32(file_hdr.uid3) != 0x10000419) {
390
cli_dbgmsg("SIS: Not a SIS file\n");
391
munmap(mfile, length);
395
switch(EC32(file_hdr.uid2)) {
397
cli_dbgmsg("SIS: EPOC release 3, 4 or 5\n");
401
cli_dbgmsg("SIS: EPOC release 6\n");
406
cli_dbgmsg("SIS: Application(?)\n");
409
cli_warnmsg("SIS: Unknown value of UID 2 (EPOC release == 0x%x) -> not a real SIS file??\n", EC32(file_hdr.uid2));
410
munmap(mfile, length);
414
/* TODO: Verify checksums (uid4 and checksum) */
417
nlangs = EC16(file_hdr.nlangs);
418
cli_dbgmsg("SIS: Number of languages: %d\n", nlangs);
420
if(nlangs && nlangs < 100) {
422
if(EC32(file_hdr.plangs) >= length || EC32(file_hdr.plangs) + nlangs * 2 >= sb.st_size) {
423
cli_errmsg("SIS: Broken file structure (language records)\n");
424
munmap(mfile, length);
428
if(!(langrecs = (uint16_t *) cli_malloc(nlangs * 2))) {
429
munmap(mfile, length);
433
memcpy(langrecs, mfile + EC32(file_hdr.plangs), nlangs * 2);
435
if(!(langs = (char *) cli_calloc(nlangs * 3 + 1, sizeof(char)))) {
436
munmap(mfile, length);
441
for(i = 0; i < nlangs; i++) {
442
strncat(langs, langcodes[EC16(langrecs[i]) % 98], 2);
444
strncat(langs, " ", 1);
446
cli_dbgmsg("SIS: Supported languages: %s\n", langs);
451
cli_errmsg("SIS: Incorrect number of languages (%d)\n", nlangs);
452
munmap(mfile, length);
456
cli_dbgmsg("SIS: Offset of languages records: %d\n", EC32(file_hdr.plangs));
458
if(EC16(file_hdr.ilang))
459
cli_dbgmsg("SIS: Installation language: %d\n", EC16(file_hdr.ilang));
462
cli_dbgmsg("SIS: Number of requisites: %d\n", EC16(file_hdr.nreqs));
463
cli_dbgmsg("SIS: Offset of requisites records: %d\n", EC32(file_hdr.preqs));
466
opts = EC16(file_hdr.options);
467
cli_dbgmsg("SIS: Options:\n");
469
cli_dbgmsg("SIS: * File is in Unicode format\n");
471
cli_dbgmsg("SIS: * File is distributable\n");
473
cli_dbgmsg("SIS: * Packed files are not compressed\n");
476
cli_dbgmsg("SIS: * Packed files are compressed\n");
480
cli_dbgmsg("SIS: * File installation shuts down all applications\n");
483
switch(EC16(file_hdr.type)) {
485
cli_dbgmsg("SIS: Type: Contains an application\n");
488
cli_dbgmsg("SIS: Type: Contains a shared/system component\n");
491
cli_dbgmsg("SIS: Type: Contains an optional (selectable) component\n");
494
cli_dbgmsg("SIS: Type: Configures an existing application or service\n");
497
cli_dbgmsg("SIS: Type: Patches an existing component\n");
500
cli_dbgmsg("SIS: Type: Upgrades an existing component\n");
503
cli_warnmsg("SIS: Unknown value of type\n");
506
cli_dbgmsg("SIS: Major version: %d\n", EC16(file_hdr.majorver));
507
cli_dbgmsg("SIS: Minor version: %d\n", EC16(file_hdr.minorver));
511
if(sizeof(struct sis_file_hdr) + sizeof(struct sis_file_hdr6) >= length) {
512
cli_errmsg("SIS: Broken file structure (language records)\n");
513
munmap(mfile, length);
517
memcpy(&file_hdr6, mfile + sizeof(struct sis_file_hdr), sizeof(struct sis_file_hdr6));
518
cli_dbgmsg("SIS: Maximum space required: %d\n", EC32(file_hdr6.maxispace));
522
nfiles = EC16(file_hdr.nfiles);
524
if(ctx->limits && ctx->limits->maxfiles && nfiles > ctx->limits->maxfiles) {
525
cli_dbgmsg("SIS: Files limit reached (max: %d)\n", ctx->limits->maxfiles);
527
*ctx->virname = "SIS.ExceededFilesLimit";
528
munmap(mfile, length);
521
fseek(f,fpos,SEEK_SET);
524
fcount=2*sizeof(uint32_t);
528
cli_dbgmsg("SIS: I'm an option\n");
530
fcount*=sis.langs*2*sizeof(uint32_t);
533
cli_dbgmsg("SIS: #if\n");
537
cli_dbgmsg("SIS: #elsif\n");
541
cli_dbgmsg("SIS: #else\n");
545
cli_dbgmsg("SIS: #endif\n");
549
cli_dbgmsg("SIS: Unknown PKGtype, expect troubles\n");
560
/*************************************************
561
This is the handler for the new (post 9.x)
563
*************************************************/
565
enum { T_INVALID, T_STRING, T_ARRAY, T_COMPRESSED, T_VERSION, T_VERSIONRANGE, T_DATE, T_TIME, T_DATETIME, T_UID, T_UNUSED, T_LANGUAGE, T_CONTENTS, T_CONTROLLER, T_INFO, T_SUPPORTEDLANGUAGES, T_SUPPORTEDOPTIONS, T_PREREQUISITES, T_DEPENDENCY, T_PROPERTIES, T_PROPERTY, T_SIGNATURES, T_CERTIFICATECHAIN, T_LOGO, T_FILEDESCRIPTION, T_HASH, T_IF, T_ELSEIF, T_INSTALLBLOCK, T_EXPRESSION, T_DATA, T_DATAUNIT, T_FILEDATA, T_SUPPORTEDOPTION, T_CONTROLLERCHECKSUM, T_DATACHECKSUM, T_SIGNATURE, T_BLOB, T_SIGNATUREALGORITHM, T_SIGNATURECERTIFICATECHAIN, T_DATAINDEX, T_CAPABILITIES, T_MAXVALUE };
567
const char *sisfields[] = {"Invalid", "String", "Array", "Compressed", "Version", "VersionRange", "Date", "Time", "DateTime", "Uid", "Unused", "Language", "Contents", "Controller", "Info", "SupportedLanguages", "SupportedOptions", "Prerequisites", "Dependency", "Properties", "Property", "Signatures", "CertificateChain", "Logo", "FileDescription", "Hash", "If", "ElseIf", "InstallBlock", "Expression", "Data", "DataUnit", "FileData", "SupportedOption", "ControllerChecksum", "DataChecksum", "Signature", "Blob", "SignatureAlgorithm", "SignatureCertificateChain", "DataIndex", "Capabilities"};
569
#define ALIGN4(x) (((x)&~3) + ((((x)&1)|(((x)>>1)&1))<<2))
571
#define HERE printf("here\n"),abort();
575
uint8_t buff[BUFSIZ];
583
static inline int getd(struct SISTREAM *s, uint32_t *v) {
585
memcpy(s->buff, s->buff + s->smax - s->sleft, s->sleft);
586
if ((s->sleft=s->smax=fread(&s->buff[s->sleft], 1, BUFSIZ - s->sleft, s->f) + s->sleft)<4) {
590
*v = cli_readint32(&s->buff[s->smax - s->sleft]);
595
static inline int getsize(struct SISTREAM *s) {
596
uint32_t *fsize = &s->fsize[s->level];
597
if(getd(s, fsize) || !*fsize || (*fsize)>>31 || (s->level && *fsize > s->fsize[s->level-1] * 2)) return 1;
598
/* To handle crafted archives we allow the content to overflow the container but only up to 2 times the container size */
599
s->fnext[s->level] = ftell(s->f) - s->sleft + *fsize;
603
static inline int getfield(struct SISTREAM *s, uint32_t *field) {
605
if(!(ret = getd(s, field)))
608
if (*field<T_MAXVALUE)
609
cli_dbgmsg("SIS: %d:Got %s(%x) field with size %x\n", s->level, sisfields[*field], *field, s->fsize[s->level]);
611
cli_dbgmsg("SIS: %d:Got invalid(%x) field with size %x\n", s->level, *field, s->fsize[s->level]);
616
static inline int skip(struct SISTREAM *s, uint32_t size) {
618
cli_dbgmsg("SIS: skipping %x\n", size);
619
if (s->sleft>=size) s->sleft-=size;
621
seekto = size - s->sleft;
622
if (seekto<0) /* in case sizeof(long)==sizeof(uint32_t) */
624
fseek(s->f, seekto, SEEK_CUR);
625
/* s->sleft = s->smax = fread(s->buff,1,BUFSIZ,s->f); */
626
s->sleft = s->smax = 0;
631
static inline int skipthis(struct SISTREAM *s) {
632
return skip(s, ALIGN4(s->fsize[s->level]));
635
static inline void seeknext(struct SISTREAM *s) {
636
fseek(s->f, s->fnext[s->level], SEEK_SET);
637
/* s->sleft = s->smax = fread(s->buff,1,BUFSIZ,s->f); */
638
s->sleft = s->smax = 0;
642
static int real_scansis9x(FILE *f, cli_ctx *ctx, const char *tmpd) {
643
struct SISTREAM stream;
644
struct SISTREAM *s = &stream;
645
uint32_t field, optst[]={T_CONTROLLERCHECKSUM, T_DATACHECKSUM, T_COMPRESSED};
653
if (getfield(s, &field) || field!=T_CONTENTS)
534
cli_dbgmsg("SIS: Number of files: %d\n", nfiles);
535
cli_dbgmsg("SIS: Offset of files records: %d\n", EC32(file_hdr.pfiles));
537
if(!(dir = cli_gentempdir(NULL))) {
538
cli_errmsg("SIS: Can't generate temporary directory\n");
539
munmap(mfile, length);
543
if((frecord = EC32(file_hdr.pfiles)) >= length) {
544
cli_errmsg("SIS: Broken file structure (frecord)\n");
545
munmap(mfile, length);
550
for(i = 0; i < nfiles; i++) {
552
cli_dbgmsg("SIS: -----\n");
554
if(frecord + 4 >= length) {
555
cli_errmsg("SIS: Broken file structure (frecord)\n");
556
munmap(mfile, length);
557
if(!cli_leavetemps_flag)
563
switch(cli_readint32(mfile + frecord)) {
565
cli_dbgmsg("SIS: Simple file record\n");
566
if((ret = sis_extract_simple(desc, mfile, sb.st_size, frecord + 4, 1, compressed, &ifile, dir, ctx))) {
567
munmap(mfile, length);
568
if(!cli_leavetemps_flag)
575
frecord += 32 + 12 + 4;
577
frecord += 28 + 4 + 4;
581
cli_dbgmsg("SIS: Multiple languages file record\n");
582
/* TODO: Pass language strings into sis_extract */
583
if((ret = sis_extract_simple(desc, mfile, sb.st_size, frecord + 4, nlangs, compressed, &ifile, dir, ctx))) {
584
munmap(mfile, length);
585
if(!cli_leavetemps_flag)
592
frecord += 32 + 12 * nlangs + 4;
594
frecord += 28 + 4 * nlangs + 4;
598
cli_dbgmsg("SIS: Options record\n");
599
if(frecord + 8 >= length) {
600
munmap(mfile, length);
601
if(!cli_leavetemps_flag)
607
n = cli_readint32(mfile + frecord + 4);
608
cli_dbgmsg("SIS: Number of options: %d\n", n);
610
if(n > 128 || frecord + 8 * n * nlangs >= length) {
611
cli_errmsg("SIS: Incorrect number of options\n");
612
munmap(mfile, length);
613
if(!cli_leavetemps_flag)
619
frecord += 8 + 8 * n * nlangs + 16;
624
cli_dbgmsg("SIS: If/ElseIf record\n");
625
if(frecord + 8 >= length) {
626
munmap(mfile, length);
627
if(!cli_leavetemps_flag)
633
n = cli_readint32(mfile + frecord + 4);
634
cli_dbgmsg("SIS: Size of conditional expression: %d\n", n);
637
cli_errmsg("SIS: Incorrect size of conditional expression\n");
638
munmap(mfile, length);
639
if(!cli_leavetemps_flag)
648
cli_dbgmsg("SIS: Else record\n");
652
cli_dbgmsg("SIS: EndIf record\n");
656
cli_warnmsg("SIS: Unknown file record type\n");
660
/* scan extracted files */
661
cli_dbgmsg("SIS: ****** Scanning extracted files ******\n");
662
ret = cli_scandir(dir, ctx);
664
if(!cli_leavetemps_flag)
668
munmap(mfile, length);
673
#else /* HAVE_MMAP */
679
int cli_scansis(int desc, cli_ctx *ctx)
681
cli_warnmsg("Support for SIS files not compiled in!\n");
658
if (getfield(s, &field)) return CL_CLEAN;
660
if (field==optst[i]) {
661
if (skipthis(s)) return CL_CLEAN;
667
if (field!=T_COMPRESSED) return CL_CLEAN;
670
while (1) { /* 1DATA */
671
if (getfield(s, &field) || field!=T_DATA) break;
674
while(1) { /* DATA::ARRAY */
676
if (getfield(s, &field) || field!=T_ARRAY || getd(s, &atype) || atype!=T_DATAUNIT || s->fsize[s->level]<4) break;
677
s->fsize[s->level]-=4;
680
while (s->fsize[s->level-1] && !getsize(s)) { /* FOREACH DATA::ARRAY::DATAUNITs */
681
cli_dbgmsg("SIS: %d:Got dataunit element with size %x\n", s->level, s->fsize[s->level]);
682
if (ALIGN4(s->fsize[s->level]) < s->fsize[s->level-1])
683
s->fsize[s->level-1]-=ALIGN4(s->fsize[s->level]);
685
s->fsize[s->level-1]=0;
688
while(1) { /* DATA::ARRAY::DATAUNIT[x]::ARRAY */
689
if(getfield(s, &field) || field!=T_ARRAY || getd(s, &atype) || atype!=T_FILEDATA || s->fsize[s->level]<4) break;
690
s->fsize[s->level]-=4;
693
while (s->fsize[s->level-1] && !getsize(s)) { /* FOREACH DATA::ARRAY::DATAUNIT[x]::ARRAY::FILEDATA */
694
uint32_t usize, usizeh;
700
cli_dbgmsg("SIS: %d:Got filedata element with size %x\n", s->level, s->fsize[s->level]);
701
if (ALIGN4(s->fsize[s->level]) < s->fsize[s->level-1])
702
s->fsize[s->level-1]-=ALIGN4(s->fsize[s->level]);
704
s->fsize[s->level-1]=0;
707
while(1) { /* DATA::ARRAY::DATAUNIT[x]::ARRAY::FILEDATA[x]::COMPRESSED */
708
if(getfield(s, &field) || field!=T_COMPRESSED || getd(s, &field) || getd(s, &usize) || getd(s, &usizeh) || usizeh) break;
709
s->fsize[s->level]-=12;
710
cli_dbgmsg("SIS: File is%s compressed - size %x -> %x\n", (field)?"":" not", s->fsize[s->level], usize);
711
snprintf(tempf, 1024, "%s"PATHSEP"sis9x%02d", tmpd, i++);
713
fseek(s->f, -(long)s->sleft, SEEK_CUR);
714
s->sleft = s->smax = 0;
716
if (cli_checklimits("sis", ctx,ALIGN4(s->fsize[s->level]), 0, 0)!=CL_CLEAN) break;
717
if (!(src=cli_malloc(ALIGN4(s->fsize[s->level])))) break;
718
if (fread(src, ALIGN4(s->fsize[s->level]),1,s->f) != 1) {
723
if(field) { /* compressed */
726
if (usize<=s->fsize[s->level]*3 && cli_checklimits("sis", ctx, s->fsize[s->level]*3, 0, 0)==CL_CLEAN)
727
uusize=s->fsize[s->level]*3;
728
else if (cli_checklimits("sis", ctx, usize, 0, 0)==CL_CLEAN)
735
if (!(dst=cli_malloc(uusize))) {
739
zresult=uncompress(dst, &uusize, src, s->fsize[s->level]);
742
cli_dbgmsg("SIS: Inflate failure (%d)\n", zresult);
746
if ((uLongf)usize != uusize)
747
cli_dbgmsg("SIS: Warning: expected size %lx but got %lx\n", (uLongf)usize, uusize);
749
cli_dbgmsg("SIS: File successfully inflated\n");
750
} else { /* not compressed */
752
uusize = s->fsize[s->level];
754
if ((fd=open(tempf, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0600))==-1) {
755
cli_errmsg("SIS: unable to create output file %s - aborting.", tempf);
759
if (cli_writen(fd, dst, uusize)!=(int)uusize) {
765
if (cli_magic_scandesc(fd, ctx) == CL_VIRUS) {
771
} /* DATA::ARRAY::DATAUNIT[x]::ARRAY::FILEDATA[x]::COMPRESSED */
774
} /* FOREACH DATA::ARRAY::DATAUNIT[x]::ARRAY::FILEDATAs */
777
} /* DATA::ARRAY::DATAUNIT[x]::ARRAY */
780
} /* FOREACH DATA::ARRAY::DATAUNITs */
790
/*************************************************
791
An (incomplete) FSM approach to sis9x unpacking
792
maybe needed if sisdataindex gets exploited
793
*************************************************/
795
/* #include <stdio.h> */
796
/* #include <stdint.h> */
797
/* #include <stdlib.h> */
798
/* #include <string.h> */
799
/* #include <zlib.h> */
801
/* /\* FIXME: RESEEK before spamming strings if not compressed *\/ */
802
/* #define SPAMSARRAY(WHO) \ */
805
/* if(field!=T_STRING) { \ */
806
/* printf(WHO" - Unexpected array type, skipping\n"); \ */
809
/* while(fsz>4) { \ */
812
/* if(field && fsz<=sleft && field<=fsz) { \ */
813
/* stringifycbuff(&cbuff[smax-sleft], field); \ */
814
/* printf(WHO" - \"%s\"\n", &cbuff[smax-sleft]); \ */
816
/* printf(WHO" - Name not decoded\n"); \ */
819
/* SKIP(ALIGN4(field)); \ */
820
/* fsz-=(ALIGN4(field)); \ */
821
/* if((int32_t)fsz<0) fsz=0; \ */
825
/* enum { T_INVALID, T_STRING, T_ARRAY, T_COMPRESSED, T_VERSION, T_VERSIONRANGE, T_DATE, T_TIME, T_DATETIME, T_UID, T_UNUSED, T_LANGUAGE, T_CONTENTS, T_CONTROLLER, T_INFO, T_SUPPORTEDLANGUAGES, T_SUPPORTEDOPTIONS, T_PREREQUISITES, T_DEPENDENCY, T_PROPERTIES, T_PROPERTY, T_SIGNATURES, T_CERTIFICATECHAIN, T_LOGO, T_FILEDESCRIPTION, T_HASH, T_IF, T_ELSEIF, T_INSTALLBLOCK, T_EXPRESSION, T_DATA, T_DATAUNIT, T_FILEDATA, T_SUPPORTEDOPTION, T_CONTROLLERCHECKSUM, T_DATACHECKSUM, T_SIGNATURE, T_BLOB, T_SIGNATUREALGORITHM, T_SIGNATURECERTIFICATECHAIN, T_DATAINDEX, T_CAPABILITIES, T_MAXVALUE, CUST_SKIP }; */
828
/* #define GETD(VAR) \ */
830
/* if (sleft<4) { \ */
831
/* printf("Unespectedly reached end of compressed buffer\n"); \ */
834
/* smax=sleft=0; \ */
836
/* VAR = cli_readint32(&cbuff[smax-sleft]); \ */
840
/* if (sleft<4) { \ */
841
/* memcpy(buff, buff+smax-sleft, sleft); \ */
842
/* if ((smax=fread(buff+sleft,1,BUFSIZ-sleft,f)+sleft)<4) { \ */
843
/* printf("EOF\n"); \ */
848
/* VAR = cli_readint32(&buff[smax-sleft]); \ */
853
/* #define SKIP(N) \ */
854
/* if (cbuff && sleft<=(N)) { \ */
857
/* smax=sleft=0; \ */
859
/* if (sleft>=(N)) sleft-=(N); \ */
861
/* if ((ssize_t)((N)-sleft)<0) { \ */
862
/* printf("Refusing to seek back\n"); \ */
865
/* fseek(f, (N)-sleft, SEEK_CUR); \ */
866
/* sleft=smax=fread(buff,1,BUFSIZ,f); \ */
869
/* #define RESEEK() \ */
870
/* if (!cbuff) { \ */
871
/* fseek(f, -(long)sleft, SEEK_CUR); \ */
872
/* sleft=smax=fread(buff,1,BUFSIZ,f); \ */
876
/* #define GETSZ \ */
878
/* if(fsz>>31) { \ */
879
/* printf("Size too big\n"); \ */
883
/* #define GETSIZE(TREE) \ */
885
/* if(!fsz || (fsz>>31)) { \ */
886
/* printf(TREE" - Wrong field size\n"); \ */
887
/* goto SIS_ERROR; \ */
891
/* static void stringifycbuff(uint8_t *ptr, uint32_t len) { */
894
/* if (len>400) len=400; */
895
/* for(i = 0 ; i < len; i+=2) ptr[i/2] = ptr[i]; */
900
/* const char *sisfields[] = {"Invalid", "String", "Array", "Compressed", "Version", "VersionRange", "Date", "Time", "DateTime", "Uid", "Unused", "Language", "Contents", "Controller", "Info", "SupportedLanguages", "SupportedOptions", "Prerequisites", "Dependency", "Properties", "Property", "Signatures", "CertificateChain", "Logo", "FileDescription", "Hash", "If", "ElseIf", "InstallBlock", "Expression", "Data", "DataUnit", "FileData", "SupportedOption", "ControllerChecksum", "DataChecksum", "Signature", "Blob", "SignatureAlgorithm", "SignatureCertificateChain", "DataIndex", "Capabilities", "PLACEHOLDER"}; */
902
/* const char *sislangs[] = {"UNKNOWN", "UK English","French", "German", "Spanish", "Italian", "Swedish", "Danish", "Norwegian", "Finnish", "American", "Swiss French", "Swiss German", "Portuguese", "Turkish", "Icelandic", "Russian", "Hungarian", "Dutch", "Belgian Flemish", "Australian English", "Belgian French", "Austrian German", "New Zealand English", "International French", "Czech", "Slovak", "Polish", "Slovenian", "Taiwanese Chinese", "Hong Kong Chinese", "PRC Chinese", "Japanese", "Thai", "Afrikaans", "Albanian", "Amharic", "Arabic", "Armenian", "Tagalog", "Belarussian", "Bengali", "Bulgarian", "Burmese", "Catalan", "Croation", "Canadian English", "International English", "South African English", "Estonian", "Farsi", "Canadian French", "Gaelic", "Georgian", "Greek", "Cyprus Greek", "Gujarati", "Hebrew", "Hindi", "Indonesian", "Irish", "Swiss Italian", "Kannada", "Kazakh", "Kmer", "Korean", "Lao", "Latvian", "Lithuanian", "Macedonian", "Malay", "Malayalam", "Marathi", "Moldovian", "Mongolian", "Norwegian Nynorsk", "Brazilian Portuguese", "Punjabi", "Romanian", "Serbian", "Sinhalese", "Somali", "International Spanish", "American Spanish", "Swahili", "Finland Swedish", "Reserved", "Tamil", "Telugu", "Tibetan", "Tigrinya", "Cyprus Turkish", "Turkmen", "Ukrainian", "Urdu", "Reserved", "Vietnamese", "Welsh", "Zulu", "Other"}; */
903
/* #define MAXLANG (sizeof(sislangs)/sizeof(sislangs[0])) */
906
/* int main(int argc, char **argv) { */
907
/* FILE *f = fopen(argv[1], "r"); */
908
/* uint32_t uid[4]; */
909
/* unsigned int i, sleft=0, smax=0, level=0; */
910
/* uint8_t buff[BUFSIZ], *cbuff=NULL; */
911
/* uint32_t field, fsz; */
915
/* char tree[200]; */
916
/* unsigned int next[200]; */
917
/* unsigned int count; */
920
/* const struct PIPPO { */
921
/* uint32_t expect; */
922
/* uint8_t optional; */
924
/* struct PIPPO *next; */
927
/* { T_CONTENTS, 0, 1, &s[1], ""}, */
928
/* { T_CONTROLLERCHECKSUM, 1, 0, &s[2], ""}, */
929
/* { T_DATACHECKSUM, 1, 0, &s[3], ""}, */
930
/* { T_COMPRESSED, 0, 1, &s[4], ""}, */
931
/* { T_CONTROLLER, 0, 1, &s[5], ""}, */
932
/* { T_INFO, 0, 1, &s[6], ""}, */
933
/* { T_UID, 0, 0, &s[7], "App UID"}, */
934
/* { T_STRING, 0, 0, &s[8], "Vendor name"}, */
935
/* { T_ARRAY, 0, 0, &s[9], "App names"}, */
936
/* { T_ARRAY, 0, 0, &s[10], "Vendor names"}, */
937
/* { T_VERSION, 0, 0, &s[11], "App Version"}, */
938
/* { T_DATETIME, 0, 0, &s[12], ""}, */
939
/* { T_DATE, 0, 0, &s[13], "Creation Date"}, */
940
/* { T_TIME, 0, 0, &s[14], "Creation Time"}, */
941
/* { CUST_SKIP, 4, 0, &s[15], ""}, */
942
/* { T_SUPPORTEDOPTIONS, 0, 2, &s[16], ""}, */
943
/* { T_SUPPORTEDLANGUAGES, 0, 1, &s[17], ""}, */
944
/* { T_ARRAY, 0, 0, &s[18], "Supported Languages"}, */
945
/* { T_PREREQUISITES, 0, 2, &s[19], ""}, */
946
/* { T_PROPERTIES, 0, 0, &s[20], ""}, */
947
/* { T_LOGO, 1, 0, &s[21], ""}, */
948
/* { T_INSTALLBLOCK, 0, 0, &s[22], ""}, */
949
/* { T_SIGNATURECERTIFICATECHAIN, 1, 0, &s[23], ""}, */
950
/* { T_DATAINDEX, 0, 0, &s[24], ""}, */
951
/* { T_DATA, 0, 3, NULL, NULL} */
953
/* struct PIPPO *this; */
956
/* struct PIPPO s; */
957
/* uint32_t totalsize; */
958
/* struct PIPPO *next; */
966
/* printf("UIDS: %x %x %x - %x\n",uid[0],uid[1],uid[2],uid[3]); */
968
/* sstack.next[0]=0; */
969
/* sstack.count=0; */
971
/* for (this=&s[0]; this; this=this->next) { */
972
/* if(this->expect==CUST_SKIP) { */
973
/* SKIP(this->optional); */
976
/* if (this!=&t_array) { */
978
/* GETSIZE("FIXME"); */
980
/* GETSIZE("FIXME"); */
981
/* if (t_array.totalsize<=(ALIGN4(fsz)+4)) */
982
/* this->next = t_array.next; */
983
/* t_array.totalsize-=ALIGN4(fsz)+4; */
984
/* field = this->expect; */
986
/* if(field>=T_MAXVALUE) { */
987
/* printf("Bogus field found\n"); */
991
/* for( ; this && this->optional && this->expect!=field; this=this->next) */
992
/* printf("Skipping optional state %s\n", sisfields[this->expect]); */
994
/* printf("Broken SIS file\n"); */
997
/* if(!this->optional && this->expect!=field) { */
998
/* printf("Error: expecing %s but found %s\n", sisfields[this->expect], sisfields[field]); */
999
/* goto SIS_ERROR; */
1001
/* printf("Got %s field (%d) with size %x(%u)\n", sisfields[field], field, fsz, fsz); */
1003
/* switch(this->dir) { */
1004
/* case 1: /\* up *\/ */
1005
/* strncpy(&sstack.tree[sstack.next[sstack.count]], sisfields[field], 200-sstack.next[sstack.count]); */
1006
/* strncat(sstack.tree, ":", 200); */
1007
/* sstack.count++; */
1008
/* sstack.tree[199]='\0'; */
1009
/* sstack.next[sstack.count]=strlen(sstack.tree); */
1012
/* sstack.count--; */
1014
/* sstack.count-=this->dir-1; */
1015
/* strncpy(&sstack.tree[sstack.next[sstack.count]], sisfields[field], 200-sstack.next[sstack.count]); */
1016
/* strncat(sstack.tree, ":", 200); */
1017
/* sstack.tree[199]='\0'; */
1020
/* printf("%s\n", sstack.tree); */
1022
/* switch(field) { */
1023
/* case T_CONTENTS: */
1025
/* case T_CONTROLLERCHECKSUM: */
1027
/* case T_DATACHECKSUM: */
1029
/* case T_COMPRESSED: */
1031
/* printf("Found nested compressed streams, aborting\n"); */
1032
/* goto SIS_ERROR; */
1034
/* uint32_t method; */
1035
/* uint32_t usize; */
1036
/* uint32_t misc; */
1038
/* uint8_t *dbuff; */
1039
/* uLongf uusize; */
1046
/* printf("%s filesize too big\n", sstack.tree); */
1047
/* goto SIS_ERROR; */
1049
/* printf("%s compression %d, size %d, usize %d\n", sstack.tree, method, fsz, usize); */
1051
/* fseek(f, -(long)sleft, SEEK_CUR); */
1054
/* if(!(dbuff=malloc(ALIGN4(fsz)))) { */
1055
/* printf("%s Out of memory\n", sstack.tree); */
1056
/* goto SIS_ERROR; */
1058
/* if(!(cbuff=malloc(usize))) { */
1060
/* printf("%s Out of memory\n", sstack.tree); */
1061
/* goto SIS_ERROR; */
1063
/* if (fread(dbuff,ALIGN4(fsz),1,f) != 1) { */
1064
/* printf("%s Failed to read compressed data\n", sstack.tree); */
1066
/* goto SIS_ERROR; */
1068
/* zresult=uncompress(cbuff, &uusize, dbuff, fsz); */
1070
/* if (zresult!=Z_OK) { */
1071
/* printf("%s Unpacking failure, skipping block\n", sstack.tree); */
1072
/* goto SIS_ERROR; */
1074
/* if ((uLongf)usize != uusize) { */
1075
/* printf("%s Expected size %lx but got %lx\n", sstack.tree, (uLongf)usize, uusize); */
1076
/* goto SIS_ERROR; */
1078
/* smax=sleft=uusize; */
1079
/* fwrite(cbuff, uusize, 1, fopen("/tmp/gunz", "w")); */
1083
/* case T_CONTROLLER: */
1090
/* printf("%s %s = %x\n", sstack.tree, this->what, field); */
1092
/* case T_STRING: */
1094
/* if(fsz && fsz<=sleft) { */
1095
/* char *t=(cbuff)?&cbuff[smax-sleft]:&buff[smax-sleft]; */
1096
/* stringifycbuff(t, fsz); */
1097
/* printf("%s %s = \"%s\"\n", sstack.tree, this->what, t); */
1098
/* } else printf("%s %s not decoded\n", sstack.tree, this->what); */
1103
/* t_array.s.expect = field; */
1104
/* t_array.s.optional = 0; */
1105
/* t_array.s.dir = 0; */
1106
/* t_array.s.next = &t_array; */
1107
/* t_array.s.what = this->what; */
1108
/* t_array.next = this->next; */
1109
/* t_array.totalsize = ALIGN4(fsz); */
1110
/* this = &t_array; */
1112
/* case T_VERSION: { */
1113
/* uint32_t maj,min,bld; */
1117
/* printf("%s %s = %u.%u.%u\n", sstack.tree, this->what, maj, min, bld); */
1121
/* case T_DATETIME: */
1126
/* printf("%s %s = %u-%u-%u\n", sstack.tree, this->what, field&0xffff, (field>>16)&0xff, (field>>24)&0xff); */
1130
/* fsz-=4; /\* -1 aligns to 0 *\/ */
1131
/* printf("%s %s = %u:%u:%u\n", sstack.tree, this->what, field&0xff, (field>>8)&0xff, (field>>16)&0xff); */
1133
/* case T_SUPPORTEDOPTIONS: */
1134
/* /\* FIXME: ANYTHING USEFUL HERE? *\/ */
1136
/* case T_SUPPORTEDLANGUAGES: */
1138
/* case T_LANGUAGE: */
1141
/* printf("%s %s = \"%s\"\n", sstack.tree, this->what, field>=MAXLANG ? "Bad Language" : sislangs[field]); */
1143
/* case T_PREREQUISITES: */
1145
/* case T_PROPERTIES: */
1149
/* case T_INSTALLBLOCK: */
1151
/* case T_SIGNATURECERTIFICATECHAIN: */
1152
/* t_array.s.expect = field; */
1153
/* t_array.s.optional = 1; */
1154
/* t_array.s.dir = 0; */
1155
/* t_array.s.next = this; */
1156
/* this = &t_array; */
1158
/* case T_DATAINDEX: */
1161
/* printf("%s %s = %x\n", sstack.tree, this->what, field); */
1163
/* if(ALIGN4(fsz) || sleft) */
1164
/* printf("Trailing garbage found in compressed controller\n"); */
1165
/* fsz=sleft=smax=0; */
1171
/* printf("Error: unhandled field %d\n", field); */
1172
/* goto SIS_ERROR; */
1174
/* SKIP(ALIGN4(fsz)); */
1179
/* if(cbuff) free(cbuff); */
685
#endif /* HAVE_MMAP */