Sindbad~EG File Manager
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <mspack.h>
#include "mspack/macros.h"
#define FILENAME ".chminfo-temp"
unsigned char *load_sys_data(struct mschm_decompressor *chmd,
struct mschmd_header *chm,
const char *filename,
off_t *length_ptr)
{
struct mschmd_file *file;
unsigned char *data;
FILE *fh;
for (file = chm->sysfiles; file; file = file->next) {
if (strcmp(file->filename, filename) == 0) break;
}
if (!file || file->section->id != 0) return NULL;
if (chmd->extract(chmd, file, FILENAME)) return NULL;
if (length_ptr) *length_ptr = file->length;
if (!(data = (unsigned char *) malloc((size_t) file->length))) return NULL;
if ((fh = fopen(FILENAME, "rb"))) {
fread(data, (size_t) file->length, 1, fh);
fclose(fh);
}
else {
free(data);
data = NULL;
}
unlink(FILENAME);
return data;
}
char *guid(unsigned char *data) {
static char result[43];
snprintf(result, sizeof(result),
"{%08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X%02X%02X}",
EndGetI32(&data[0]),
data[4] | (data[5] << 8),
data[6] | (data[7] << 8),
data[8] | (data[9] << 8),
data[10], data[11], data[12], data[13],
data[14], data[15], data[16], data[17]);
return result;
}
#define READ_ENCINT(var, label) do { \
(var) = 0; \
do { \
if (p > pend) goto label; \
(var) = ((var) << 7) | (*p & 0x7F); \
} while (*p++ & 0x80); \
} while (0)
void print_dir(struct mschmd_header *chm, char *filename) {
unsigned char dir[0x54], *chunk;
unsigned int i;
FILE *fh;
if (!(chunk = (unsigned char *) malloc(chm->chunk_size))) return;
if ((fh = fopen(filename, "rb"))) {
#if HAVE_FSEEKO
fseeko(fh, chm->dir_offset - 84, SEEK_SET);
#else
fseek(fh, chm->dir_offset - 84, SEEK_SET);
#endif
fread(&dir[0], 84, 1, fh);
printf(" chmhs1_Signature = %4.4s\n", &dir[0]);
printf(" chmhs1_Version = %d\n", EndGetI32(&dir[4]));
printf(" chmhs1_HeaderLen = %d\n", EndGetI32(&dir[8]));
printf(" chmhs1_Unknown1 = %d\n", EndGetI32(&dir[12]));
printf(" chmhs1_ChunkSize = %d\n", EndGetI32(&dir[16]));
printf(" chmhs1_Density = %d\n", EndGetI32(&dir[20]));
printf(" chmhs1_Depth = %d\n", EndGetI32(&dir[24]));
printf(" chmhs1_IndexRoot = %d\n", EndGetI32(&dir[28]));
printf(" chmhs1_FirstPMGL = %d\n", EndGetI32(&dir[32]));
printf(" chmhs1_LastPMGL = %d\n", EndGetI32(&dir[36]));
printf(" chmhs1_Unknown2 = %d\n", EndGetI32(&dir[40]));
printf(" chmhs1_NumChunks = %d\n", EndGetI32(&dir[44]));
printf(" chmhs1_LanguageID = %d\n", EndGetI32(&dir[48]));
printf(" chmhs1_GUID = %s\n", guid(&dir[52]));
printf(" chmhs1_Unknown3 = %d\n", EndGetI32(&dir[68]));
printf(" chmhs1_Unknown4 = %d\n", EndGetI32(&dir[72]));
printf(" chmhs1_Unknown5 = %d\n", EndGetI32(&dir[76]));
printf(" chmhs1_Unknown6 = %d\n", EndGetI32(&dir[80]));
for (i = 0; i < chm->num_chunks; i++) {
unsigned int num_entries, quickref_size, j, k;
unsigned char *p, *pend, *name;
printf(" CHUNK %u:\n", i);
fread(chunk, chm->chunk_size, 1, fh);
if ((chunk[0] == 'P') && (chunk[1] == 'M') &&
(chunk[2] == 'G') && (chunk[3] == 'L'))
{
k = chm->chunk_size - 2;
num_entries = chunk[k] | (chunk[k+1] << 8);
quickref_size = EndGetI32(&chunk[4]);
if (quickref_size > (chm->chunk_size - 20)) {
printf(" QR size of %d too large (max is %d)\n",
quickref_size, chm->chunk_size - 20);
quickref_size = chm->chunk_size - 20;
}
printf(" PMGL entries=%u qrsize=%u zero=%u prev=%d next=%d\n",
num_entries, quickref_size, EndGetI32(&chunk[8]),
EndGetI32(&chunk[12]), EndGetI32(&chunk[16]));
printf(" QR: entry %4u = offset %u\n", 0, 20);
j = (1 << chm->density) + 1;
while (j < num_entries) {
k -= 2;
if (k < (chm->chunk_size - quickref_size)) break;
printf(" QR: entry %4u = offset %u\n",
j, (chunk[k] | (chunk[k+1] << 8)) + 20);
j += (1 << chm->density) + 1;
}
p = &chunk[20];
pend = &chunk[chm->chunk_size-2];
for (j = 0; j < num_entries; j++) {
off_t name_len = 0, section = 0, offset = 0, length = 0;
printf(" %4d: ", (int) (p - &chunk[0]));
READ_ENCINT(name_len, PMGL_end);
if (name_len < 0 || name_len > (pend - p)) goto PMGL_end;
name = p; p += name_len;
READ_ENCINT(section, PMGL_end);
READ_ENCINT(offset, PMGL_end);
READ_ENCINT(length, PMGL_end);
printf("sec=%" LD " off=%-9" LD " len=%-9" LD " name=\"",
section, offset, length);
if (name_len) fwrite(name, 1, name_len, stdout);
printf("\"\n");
}
PMGL_end:
if (j != num_entries) printf("premature end of chunk\n");
}
else if ((chunk[0] == 'P') && (chunk[1] == 'M') &&
(chunk[2] == 'G') && (chunk[3] == 'I'))
{
k = chm->chunk_size - 2;
num_entries = chunk[k] | (chunk[k+1] << 8);
quickref_size = EndGetI32(&chunk[4]);
printf(" PMGI entries=%u free=%u\n", num_entries, quickref_size);
printf(" QR: entry %4u = offset %u\n", 0, 8);
j = (1 << chm->density) + 1;
while (j < num_entries) {
k -= 2;
printf(" QR: entry %4u = offset %u\n",
j, (chunk[k] | (chunk[k+1] << 8)) + 8);
j += (1 << chm->density) + 1;
}
p = &chunk[8];
pend = &chunk[chm->chunk_size-2];
for (j = 0; j < num_entries; j++) {
off_t name_len, section;
printf(" %4d: ", (int) (p - &chunk[0]));
READ_ENCINT(name_len, PMGI_end);
if (name_len < 0 || name_len > (pend - p)) goto PMGI_end;
name = p; p += name_len;
READ_ENCINT(section, PMGI_end);
printf("chunk=%-4" LD " name=\"",section);
if (name_len) fwrite(name, 1, name_len, stdout);
printf("\"\n");
}
PMGI_end:
if (j != num_entries) printf("premature end of chunk\n");
}
else {
printf(" unknown format\n");
}
}
fclose(fh);
}
free(chunk);
}
int main(int argc, char *argv[]) {
struct mschm_decompressor *chmd;
struct mschmd_header *chm;
struct mschmd_file *file;
unsigned int numf, i;
unsigned char *data;
off_t pos, len;
setbuf(stdout, NULL);
setbuf(stderr, NULL);
MSPACK_SYS_SELFTEST(i);
if (i) return 0;
if ((chmd = mspack_create_chm_decompressor(NULL))) {
for (argv++; *argv; argv++) {
printf("%s\n", *argv);
if ((chm = chmd->open(chmd, *argv))) {
printf(" chmhead_Version %u\n", chm->version);
printf(" chmhead_Timestamp %u\n", chm->timestamp);
printf(" chmhead_LanguageID %u\n", chm->language);
printf(" chmhs0_FileLen %" LD "\n", chm->length);
printf(" chmhst_OffsetHS1 %" LD "\n", chm->dir_offset);
printf(" chmhst3_OffsetCS0 %" LD "\n", chm->sec0.offset);
print_dir(chm, *argv);
if ((data = load_sys_data(chmd, chm,
"::DataSpace/Storage/MSCompressed/ControlData", &len)))
{
printf(" lzxcd_Length %u\n", EndGetI32(&data[0]));
printf(" lzxcd_Signature %4.4s\n", &data[4]);
printf(" lzxcd_Version %u\n", EndGetI32(&data[8]));
printf(" lzxcd_ResetInterval %u\n", EndGetI32(&data[12]));
printf(" lzxcd_WindowSize %u\n", EndGetI32(&data[16]));
printf(" lzxcd_CacheSize %u\n", EndGetI32(&data[20]));
printf(" lzxcd_Unknown1 %u\n", EndGetI32(&data[24]));
free(data);
}
if ((data = load_sys_data(chmd, chm,
"::DataSpace/Storage/MSCompressed/Transform/{7FC28940-"
"9D31-11D0-9B27-00A0C91E9C7C}/InstanceData/ResetTable", &len)))
{
off_t contents = chm->sec0.offset;
printf(" lzxrt_Unknown1 %u\n", EndGetI32(&data[0]));
printf(" lzxrt_NumEntries %u\n", EndGetI32(&data[4]));
printf(" lzxrt_EntrySize %u\n", EndGetI32(&data[8]));
printf(" lzxrt_TableOffset %u\n", EndGetI32(&data[12]));
printf(" lzxrt_UncompLen %llu\n", EndGetI64(&data[16]));
printf(" lzxrt_CompLen %llu\n", EndGetI64(&data[24]));
printf(" lzxrt_FrameLen %u\n", EndGetI32(&data[32]));
for (file = chm->sysfiles; file; file = file->next) {
if (strcmp(file->filename,
"::DataSpace/Storage/MSCompressed/Content") == 0)
{
contents += file->offset;
break;
}
}
printf(" - reset table (uncomp offset -> stream offset "
"[real offset, length in file]\n");
numf = EndGetI32(&data[4]);
pos = ((unsigned int) EndGetI32(&data[12]));
switch (EndGetI32(&data[8])) {
case 4:
for (i = 0; i < numf && pos < len; i++, pos += 4) {
unsigned int rtdata = EndGetI32(&data[pos]);
printf(" %-10u -> %-10u [ %" LD " %u ]\n",
i * EndGetI32(&data[32]),
rtdata,
contents + rtdata,
(i == (numf-1))
? (EndGetI32(&data[24]) - rtdata)
: (EndGetI32(&data[pos + 4]) - rtdata)
);
}
break;
case 8:
for (i = 0; i < numf && pos < len; i++, pos += 8) {
unsigned long long int rtdata = EndGetI64(&data[pos]);
printf(" %-10llu -> %-10llu [ %llu %llu ]\n",
i * EndGetI64(&data[32]), rtdata, contents + rtdata,
(i == (numf-1))
? (EndGetI64(&data[24]) - rtdata)
: (EndGetI64(&data[pos + 8]) - rtdata)
);
}
break;
}
free(data);
}
chmd->close(chmd, chm);
}
}
mspack_destroy_chm_decompressor(chmd);
}
return 0;
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists