2018-03-23 00:30:02 +00:00
|
|
|
#include "macunpack.h"
|
2018-03-23 01:02:26 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2018-03-23 00:30:02 +00:00
|
|
|
#include "globals.h"
|
|
|
|
#include "lzh.h"
|
|
|
|
#include "crc.h"
|
|
|
|
#include "../fileio/wrfile.h"
|
|
|
|
#include "../fileio/machdr.h"
|
|
|
|
#include "../util/masks.h"
|
|
|
|
#include "../util/util.h"
|
|
|
|
#include "bits_be.h"
|
|
|
|
|
|
|
|
#define LZ5LOOKAHEAD 18 /* look ahead buffer size for LArc */
|
|
|
|
#define LZ5BUFFSIZE 8192
|
|
|
|
#define LZ5MASK 8191
|
|
|
|
#define LZSLOOKAHEAD 17
|
|
|
|
#define LZSBUFFSIZE 4096
|
|
|
|
#define LZSMASK 4095
|
|
|
|
#define LZBUFFSIZE 8192 /* Max of above buffsizes */
|
|
|
|
|
|
|
|
extern void de_lzah();
|
|
|
|
extern unsigned char (*lzah_getbyte)();
|
|
|
|
extern void de_lzh();
|
|
|
|
|
|
|
|
typedef struct methodinfo {
|
|
|
|
char *name;
|
|
|
|
int number;
|
2018-03-23 01:02:26 +00:00
|
|
|
} methodinfo;
|
2018-03-23 00:30:02 +00:00
|
|
|
|
|
|
|
static struct methodinfo methods[] = {
|
|
|
|
{"-lh0-", lh0},
|
|
|
|
{"-lh1-", lh1},
|
|
|
|
{"-lh2-", lh2},
|
|
|
|
{"-lh3-", lh3},
|
|
|
|
{"-lh4-", lh4},
|
|
|
|
{"-lh5-", lh5},
|
|
|
|
{"-lz4-", lz4},
|
|
|
|
{"-lz5-", lz5},
|
|
|
|
{"-lzs-", lzs}
|
|
|
|
};
|
|
|
|
static char *lzh_archive;
|
|
|
|
static char *lzh_pointer;
|
|
|
|
static char *lzh_data;
|
|
|
|
static char *lzh_finfo;
|
|
|
|
static int lzh_fsize;
|
|
|
|
static int lzh_kind;
|
|
|
|
static int oldsize;
|
|
|
|
static char *lzh_file;
|
|
|
|
static int lzh_filesize;
|
|
|
|
static char *lzh_current;
|
|
|
|
static char *tmp_out_ptr;
|
|
|
|
static char lzh_lzbuf[LZBUFFSIZE];
|
|
|
|
|
|
|
|
static int lzh_filehdr();
|
|
|
|
static int lzh_checkm();
|
|
|
|
static char *lzh_methname();
|
|
|
|
static void lzh_wrfile();
|
|
|
|
static void lzh_skip();
|
|
|
|
static void lzh_nocomp();
|
|
|
|
#ifdef UNTESTED
|
|
|
|
static void lzh_lzss1();
|
|
|
|
static void lzh_lzss2();
|
|
|
|
#endif /* UNTESTED */
|
|
|
|
static void lzh_lzah();
|
|
|
|
static unsigned char lzh_getbyte();
|
|
|
|
#ifdef UNDEF
|
|
|
|
static void lzh_lh2();
|
|
|
|
static void lzh_lh3();
|
|
|
|
#endif /* UNDEF */
|
|
|
|
#ifdef UNTESTED
|
|
|
|
static void lzh_lzh12();
|
|
|
|
#endif /* UNTESTED */
|
|
|
|
static void lzh_lzh13();
|
|
|
|
|
|
|
|
void lzh(kind)
|
|
|
|
int kind;
|
|
|
|
{
|
|
|
|
struct fileHdr filehdr;
|
|
|
|
int m, i, j;
|
|
|
|
char loc_name[64];
|
|
|
|
char dirinfo[INFOBYTES];
|
|
|
|
|
|
|
|
updcrc = arc_updcrc;
|
|
|
|
crcinit = arc_crcinit;
|
|
|
|
write_it = 1;
|
|
|
|
lzh_fsize = 0;
|
|
|
|
lzh_kind = kind;
|
|
|
|
if(lzh_archive == NULL) {
|
|
|
|
lzh_archive = malloc((unsigned)in_data_size);
|
|
|
|
oldsize = in_data_size;
|
|
|
|
} else if(in_data_size > oldsize) {
|
|
|
|
lzh_archive = realloc(lzh_archive, (unsigned)in_data_size);
|
|
|
|
oldsize = in_data_size;
|
|
|
|
}
|
|
|
|
if(lzh_archive == NULL) {
|
|
|
|
(void)fprintf(stderr, "Insufficient memory for archive.\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
if(fread(lzh_archive, 1, in_data_size, infp) != in_data_size) {
|
|
|
|
(void)fprintf(stderr, "Can't read archive.\n");
|
|
|
|
#ifdef SCAN
|
|
|
|
do_error("macunpack: Can't read archive");
|
|
|
|
#endif /* SCAN */
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
lzh_pointer = lzh_archive;
|
|
|
|
while(1) {
|
|
|
|
if(in_data_size == 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(lzh_filehdr(&filehdr) == 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
m = lzh_checkm(&filehdr);
|
|
|
|
if(m < 0) {
|
|
|
|
(void)fprintf(stderr,
|
|
|
|
"Skipping file: \"%s\"; unknown method: %.5s.\n",
|
|
|
|
text, filehdr.method);
|
|
|
|
lzh_skip(&filehdr);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if(!write_it) {
|
|
|
|
/* We are skipping a folder. Skip the file if lzh_finfo is a
|
|
|
|
prefix of or identical to the folder info in the file. */
|
|
|
|
if(lzh_fsize <= filehdr.extendsize &&
|
|
|
|
!strncmp(lzh_finfo, filehdr.extend, lzh_fsize)) {
|
|
|
|
/* It was true, so we skip. */
|
|
|
|
lzh_skip(&filehdr);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* We have left the folder we were skipping. */
|
|
|
|
}
|
|
|
|
/* Now we must leave folders until lzh_finfo is a proper prefix or
|
|
|
|
identical to the folder info in the file. */
|
|
|
|
while(lzh_fsize > filehdr.extendsize ||
|
|
|
|
strncmp(lzh_finfo, filehdr.extend, lzh_fsize)) {
|
|
|
|
/* Not a proper prefix, leave folder. First determine which! */
|
|
|
|
i = lzh_fsize - 1;
|
|
|
|
while(--i >= 0 && lzh_finfo[i] != ':');
|
|
|
|
i = i + 1;
|
|
|
|
transname(lzh_finfo + i, loc_name, lzh_fsize - i - 1);
|
|
|
|
lzh_fsize = i;
|
|
|
|
if(write_it) {
|
|
|
|
indent--;
|
|
|
|
if(!info_only) {
|
|
|
|
enddir();
|
|
|
|
}
|
|
|
|
if(list) {
|
|
|
|
do_indent(indent);
|
|
|
|
(void)fprintf(stderr, "leaving folder \"%s\"\n", loc_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
write_it = 1;
|
|
|
|
}
|
|
|
|
write_it = 1;
|
|
|
|
/* lzh_finfo is a proper prefix or identical, just show so. */
|
|
|
|
lzh_finfo = filehdr.extend;
|
|
|
|
/* Now enter directories while lzh_finfo is smaller than extend. */
|
|
|
|
while(lzh_fsize < filehdr.extendsize) {
|
|
|
|
i = lzh_fsize;
|
|
|
|
while(lzh_finfo[++i] != ':');
|
|
|
|
transname(lzh_finfo + lzh_fsize, loc_name, i - lzh_fsize);
|
|
|
|
for(j = 0; j < INFOBYTES; j++) {
|
|
|
|
dirinfo[j] = 0;
|
|
|
|
}
|
|
|
|
dirinfo[I_NAMEOFF] = i - lzh_fsize;
|
|
|
|
copy(dirinfo + I_NAMEOFF + 1, lzh_finfo + lzh_fsize, i - lzh_fsize);
|
|
|
|
lzh_fsize = i + 1;
|
|
|
|
if(list) {
|
|
|
|
do_indent(indent);
|
|
|
|
(void)fprintf(stderr, "folder=\"%s\"", loc_name);
|
|
|
|
if(query) {
|
|
|
|
write_it = do_query();
|
|
|
|
} else {
|
|
|
|
(void)fputc('\n', stderr);
|
|
|
|
}
|
|
|
|
if(write_it) {
|
|
|
|
indent++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(write_it && !info_only) {
|
|
|
|
do_mkdir(loc_name, dirinfo);
|
|
|
|
}
|
|
|
|
if(!write_it) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!write_it) {
|
|
|
|
lzh_skip(&filehdr);
|
|
|
|
} else {
|
|
|
|
lzh_wrfile(&filehdr, m);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Leaving some more directories! */
|
|
|
|
while(lzh_fsize != 0) {
|
|
|
|
i = lzh_fsize - 1;
|
|
|
|
while(--i >= 0 && lzh_finfo[i] != ':');
|
|
|
|
i = i + 1;
|
|
|
|
transname(lzh_finfo + i, loc_name, lzh_fsize - i - 1);
|
|
|
|
lzh_fsize = i;
|
|
|
|
if(write_it) {
|
|
|
|
}
|
|
|
|
if(write_it) {
|
|
|
|
indent--;
|
|
|
|
if(!info_only) {
|
|
|
|
enddir();
|
|
|
|
}
|
|
|
|
if(list) {
|
|
|
|
do_indent(indent);
|
|
|
|
(void)fprintf(stderr, "leaving folder \"%s\"\n", loc_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int lzh_filehdr(f)
|
|
|
|
struct fileHdr *f;
|
|
|
|
{
|
|
|
|
register int i;
|
|
|
|
char *hdr;
|
|
|
|
int c;
|
|
|
|
int ext_ptr;
|
|
|
|
int chk_sum = 0;
|
|
|
|
char *ptr;
|
|
|
|
|
|
|
|
if(in_data_size <= 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
for(i = 0; i < INFOBYTES; i++) {
|
|
|
|
info[i] = '\0';
|
|
|
|
}
|
|
|
|
hdr = lzh_pointer;
|
|
|
|
in_data_size -= 2;
|
|
|
|
lzh_pointer += 2;
|
|
|
|
if(in_data_size < 0) {
|
|
|
|
in_data_size++;
|
|
|
|
}
|
|
|
|
f->hsize = (unsigned char)hdr[L_HSIZE];
|
|
|
|
if(f->hsize == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
f->hcrc = (unsigned char)hdr[L_HCRC];
|
|
|
|
ptr = hdr + L_METHOD;
|
|
|
|
in_data_size -= f->hsize;
|
|
|
|
lzh_pointer += f->hsize;
|
|
|
|
copy(&(f->method[0]), hdr + L_METHOD, 5);
|
|
|
|
f->psize = get4i(hdr + L_PSIZE);
|
|
|
|
f->upsize = get4i(hdr + L_UPSIZE);
|
|
|
|
f->lastmod = get4i(hdr + L_LASTMOD);
|
|
|
|
f->attribute = hdr[L_ATTRIBUTE + 1];
|
|
|
|
if(f->attribute < 2) {
|
|
|
|
for(i = 0; i < f->hsize; i++) {
|
|
|
|
chk_sum += *ptr++;
|
|
|
|
}
|
|
|
|
chk_sum &= BYTEMASK;
|
|
|
|
if(chk_sum != f->hcrc) {
|
|
|
|
(void)fprintf(stderr,
|
|
|
|
"Header checksum error; got %.2x, must be %.2x.\n",
|
|
|
|
chk_sum, f->hcrc);
|
|
|
|
#ifdef SCAN
|
|
|
|
do_error("macunpack: Header checksum error");
|
|
|
|
#endif /* SCAN */
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
f->nlength = (unsigned char)hdr[L_NLENGTH];
|
|
|
|
info[I_NAMEOFF] = f->nlength;
|
|
|
|
copy(info + I_NAMEOFF + 1, hdr + L_NAME, (int)f->nlength);
|
|
|
|
transname(hdr + L_NAME, text, (int)f->nlength);
|
|
|
|
ext_ptr = L_NLENGTH + f->nlength + 1;
|
|
|
|
f->crc = get2i(hdr + ext_ptr + L_CRC);
|
|
|
|
if(f->attribute == 1) {
|
|
|
|
f->etype = hdr[ext_ptr + L_ETYPE];
|
|
|
|
f->extendsize = hdr[ext_ptr + L_EXTENDSZ];
|
|
|
|
f->extend = hdr + ext_ptr + L_EXTEND;
|
|
|
|
} else {
|
|
|
|
f->extend = NULL;
|
|
|
|
f->extendsize = 0;
|
|
|
|
}
|
|
|
|
} else if(f->attribute == 2) {
|
|
|
|
in_data_size += 2;
|
|
|
|
lzh_pointer -= 2;
|
|
|
|
f->nlength = hdr[L_2EXTENDSZ] - 3;
|
|
|
|
info[I_NAMEOFF] = f->nlength;
|
|
|
|
copy(info + I_NAMEOFF + 1, hdr + L_2EXTEND + 2, (int)f->nlength);
|
|
|
|
transname(hdr + L_2EXTEND + 2, text, (int)f->nlength);
|
|
|
|
ext_ptr =
|
|
|
|
f->crc = get2i(hdr + L_2CRC);
|
|
|
|
f->etype = hdr[L_2ETYPE];
|
|
|
|
ext_ptr = L_2EXTEND + 2 + f->nlength;
|
|
|
|
f->extendsize = hdr[ext_ptr + L_EEXTENDSZ];
|
|
|
|
f->extend = hdr + ext_ptr + L_EEXTEND;
|
|
|
|
} else {
|
|
|
|
(void)fprintf(stderr, "Unknown file header format (%d).\n",
|
|
|
|
(int)f->attribute);
|
|
|
|
#ifdef SCAN
|
|
|
|
do_error("macunpack: Unknown file header format");
|
|
|
|
#endif /* SCAN */
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
if(f->extend != NULL) {
|
|
|
|
if(f->extendsize > 5) {
|
|
|
|
f->extend += 2;
|
|
|
|
hdr = f->extend;
|
|
|
|
f->extendsize -= 3;
|
|
|
|
for(i = 0; i < f->extendsize; i++) {
|
|
|
|
c = *hdr++;
|
|
|
|
if((c & BYTEMASK) == BYTEMASK) {
|
|
|
|
hdr[-1] = ':';
|
|
|
|
c = ':';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
c = *hdr++;
|
|
|
|
if(c == 5) {
|
|
|
|
hdr += 5;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if(f->extendsize == 5) {
|
|
|
|
hdr = f->extend;
|
|
|
|
f->extend = NULL;
|
|
|
|
f->extendsize = 0;
|
|
|
|
hdr += 5;
|
|
|
|
} else {
|
|
|
|
hdr = f->extend;
|
|
|
|
f->extend = NULL;
|
|
|
|
f->extendsize = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
hdr = hdr + ext_ptr;
|
|
|
|
}
|
|
|
|
lzh_data = hdr;
|
|
|
|
if(f->attribute != 0) {
|
|
|
|
lzh_data++;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int lzh_checkm(f)
|
|
|
|
struct fileHdr *f;
|
|
|
|
{
|
|
|
|
int i, nummeth;
|
|
|
|
char *meth;
|
|
|
|
|
|
|
|
meth = f->method;
|
|
|
|
nummeth = sizeof(methods) / sizeof(struct methodinfo);
|
|
|
|
for(i = 0; i < nummeth; i++) {
|
|
|
|
if(!strncmp(methods[i].name, meth, 5)) {
|
|
|
|
return methods[i].number;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *lzh_methname(n)
|
|
|
|
int n;
|
|
|
|
{
|
|
|
|
if(n > sizeof(methods) / sizeof(struct methodinfo)) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return methods[n].name;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void lzh_wrfile(filehdr, method)
|
|
|
|
struct fileHdr *filehdr;
|
|
|
|
int method;
|
|
|
|
{
|
|
|
|
char ftype[5], fauth[5];
|
|
|
|
int rsrcLength, dataLength;
|
|
|
|
int doit;
|
|
|
|
char *mname;
|
|
|
|
unsigned long crc;
|
|
|
|
|
|
|
|
if(filehdr->upsize > lzh_filesize) {
|
|
|
|
if(lzh_filesize == 0) {
|
|
|
|
lzh_file = malloc((unsigned)filehdr->upsize);
|
|
|
|
} else {
|
|
|
|
lzh_file = realloc(lzh_file, (unsigned)filehdr->upsize);
|
|
|
|
}
|
|
|
|
if(lzh_file == NULL) {
|
|
|
|
(void)fprintf(stderr, "Insufficient memory to unpack file.\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
switch(method) {
|
|
|
|
case lz4:
|
|
|
|
lzh_nocomp((unsigned long)128);
|
|
|
|
break;
|
|
|
|
#ifdef UNTESTED
|
|
|
|
case lz5:
|
|
|
|
lzh_lzss1((unsigned long)128);
|
|
|
|
break;
|
|
|
|
case lzs:
|
|
|
|
lzh_lzss2((unsigned long)128);
|
|
|
|
break;
|
|
|
|
#endif /* UNTESTED */
|
|
|
|
case lh0:
|
|
|
|
lzh_nocomp((unsigned long)128);
|
|
|
|
break;
|
|
|
|
case lh1:
|
|
|
|
lzh_lzah((unsigned long)128);
|
|
|
|
break;
|
|
|
|
#ifdef UNDEF
|
|
|
|
case lh2:
|
|
|
|
lzh_lh2((unsigned long)128);
|
|
|
|
break;
|
|
|
|
case lh3:
|
|
|
|
lzh_lh3((unsigned long)128);
|
|
|
|
break;
|
|
|
|
#endif /* UNDEF */
|
|
|
|
#ifdef UNTESTED
|
|
|
|
case lh4:
|
|
|
|
lzh_lzh12((unsigned long)128);
|
|
|
|
break;
|
|
|
|
#endif /* UNTESTED */
|
|
|
|
case lh5:
|
|
|
|
lzh_lzh13((unsigned long)128);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
mname = lzh_methname(method);
|
|
|
|
if(mname != NULL) {
|
|
|
|
do_indent(indent);
|
|
|
|
(void)fprintf(stderr,
|
|
|
|
"\tSorry, packing method not yet implemented.\n");
|
|
|
|
do_indent(indent);
|
|
|
|
(void)fprintf(stderr, "File = \"%s\"; ", text);
|
|
|
|
(void)fprintf(stderr, "method = %s, skipping file.\n", mname);
|
|
|
|
lzh_skip(filehdr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
(void)fprintf(stderr,
|
|
|
|
"There is something very wrong with this program!\n");
|
|
|
|
#ifdef SCAN
|
|
|
|
do_error("macunpack: program error");
|
|
|
|
#endif /* SCAN */
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
/* Checks whether everything is packed as MacBinary. */
|
|
|
|
if(*lzh_file != 0 /* More checks possible here. */) {
|
|
|
|
do_indent(indent);
|
|
|
|
(void)fprintf(stderr, "File = \"%s\" ", text);
|
|
|
|
(void)fprintf(stderr, "not packed in MacBinary, skipping file.\n");
|
|
|
|
#ifdef SCAN
|
|
|
|
do_error("macunpack: not MacBinary");
|
|
|
|
#endif /* SCAN */
|
|
|
|
lzh_skip(filehdr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
copy(info, lzh_file, 128);
|
|
|
|
rsrcLength = get4(info + I_RLENOFF);
|
|
|
|
dataLength = get4(info + I_DLENOFF);
|
|
|
|
transname(info + I_TYPEOFF, ftype, 4);
|
|
|
|
transname(info + I_AUTHOFF, fauth, 4);
|
|
|
|
if(list) {
|
|
|
|
do_indent(indent);
|
|
|
|
(void)fprintf(stderr,
|
|
|
|
"name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld",
|
|
|
|
text, ftype, fauth, (long)dataLength, (long)rsrcLength);
|
|
|
|
}
|
|
|
|
if(info_only) {
|
|
|
|
doit = 0;
|
|
|
|
} else {
|
|
|
|
doit = 1;
|
|
|
|
}
|
|
|
|
if(query) {
|
|
|
|
doit = do_query();
|
|
|
|
} else if(list) {
|
|
|
|
(void)fputc('\n', stderr);
|
|
|
|
}
|
|
|
|
if(doit) {
|
|
|
|
define_name(text);
|
|
|
|
start_info(info, (unsigned long)rsrcLength, (unsigned long)dataLength);
|
|
|
|
}
|
|
|
|
switch(method) {
|
|
|
|
case lz4:
|
|
|
|
if(verbose) {
|
|
|
|
(void)fprintf(stderr, "\tNo Compression (%.5s)", filehdr->method);
|
|
|
|
}
|
|
|
|
if(doit) {
|
|
|
|
lzh_nocomp(filehdr->upsize);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#ifdef UNTESTED
|
|
|
|
case lz5:
|
|
|
|
if(verbose) {
|
|
|
|
(void)fprintf(stderr, "\tLZSS (%.5s) compressed (%4.1f%%)",
|
|
|
|
filehdr->method, 100.0 * filehdr->psize / filehdr->upsize);
|
|
|
|
}
|
|
|
|
if(doit) {
|
|
|
|
lzh_lzss1(filehdr->upsize);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case lzs:
|
|
|
|
if(verbose) {
|
|
|
|
(void)fprintf(stderr, "\tLZSS (%.5s) compressed (%4.1f%%)",
|
|
|
|
filehdr->method, 100.0 * filehdr->psize / filehdr->upsize);
|
|
|
|
}
|
|
|
|
if(doit) {
|
|
|
|
lzh_lzss2(filehdr->upsize);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif /* UNTESTED */
|
|
|
|
case lh0:
|
|
|
|
if(verbose) {
|
|
|
|
(void)fprintf(stderr, "\tNo Compression (%.5s)", filehdr->method);
|
|
|
|
}
|
|
|
|
if(doit) {
|
|
|
|
lzh_nocomp(filehdr->upsize);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case lh1:
|
|
|
|
if(verbose) {
|
|
|
|
(void)fprintf(stderr, "\tLZAH (%.5s) compressed (%4.1f%%)",
|
|
|
|
filehdr->method, 100.0 * filehdr->psize / filehdr->upsize);
|
|
|
|
}
|
|
|
|
if(doit) {
|
|
|
|
lzh_lzah(filehdr->upsize);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#ifdef UNDEF
|
|
|
|
case lh2:
|
|
|
|
if(verbose) {
|
|
|
|
(void)fprintf(stderr, "\tLZAH (%.5s) compressed (%4.1f%%)",
|
|
|
|
filehdr->method, 100.0 * filehdr->psize / filehdr->upsize);
|
|
|
|
}
|
|
|
|
if(doit) {
|
|
|
|
lzh_lh2(filehdr->upsize);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case lh3:
|
|
|
|
if(verbose) {
|
|
|
|
(void)fprintf(stderr, "\tLZH (%.5s) compressed (%4.1f%%)",
|
|
|
|
filehdr->method, 100.0 * filehdr->psize / filehdr->upsize);
|
|
|
|
}
|
|
|
|
if(doit) {
|
|
|
|
lzh_lzh3(filehdr->upsize);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif /* UNDEF */
|
|
|
|
#ifdef UNTESTED
|
|
|
|
case lh4:
|
|
|
|
if(verbose) {
|
|
|
|
(void)fprintf(stderr, "\tLZH (%.5s) compressed (%4.1f%%)",
|
|
|
|
filehdr->method, 100.0 * filehdr->psize / filehdr->upsize);
|
|
|
|
}
|
|
|
|
if(doit) {
|
|
|
|
lzh_lzh12(filehdr->upsize);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif /* UNTESTED */
|
|
|
|
case lh5:
|
|
|
|
if(verbose) {
|
|
|
|
(void)fprintf(stderr, "\tLZH (%.5s) compressed (%4.1f%%)",
|
|
|
|
filehdr->method, 100.0 * filehdr->psize / filehdr->upsize);
|
|
|
|
}
|
|
|
|
if(doit) {
|
|
|
|
lzh_lzh13(filehdr->upsize);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(doit) {
|
|
|
|
crc = (*updcrc)(INIT_CRC, lzh_file, filehdr->upsize);
|
|
|
|
if(filehdr->crc != crc) {
|
|
|
|
(void)fprintf(stderr,
|
|
|
|
"CRC error on file: need 0x%04x, got 0x%04x\n",
|
|
|
|
filehdr->crc, (int)crc);
|
|
|
|
#ifdef SCAN
|
|
|
|
do_error("macunpack: CRC error on file");
|
|
|
|
#endif /* SCAN */
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
start_data();
|
|
|
|
copy(out_ptr, lzh_file + 128, (int)(filehdr->upsize - 128));
|
|
|
|
}
|
|
|
|
if(verbose) {
|
|
|
|
(void)fprintf(stderr, ".\n");
|
|
|
|
}
|
|
|
|
if(doit) {
|
|
|
|
end_file();
|
|
|
|
}
|
|
|
|
lzh_skip(filehdr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void lzh_skip(filehdr)
|
|
|
|
struct fileHdr *filehdr;
|
|
|
|
{
|
|
|
|
lzh_pointer += filehdr->psize;
|
|
|
|
in_data_size -= filehdr->psize;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/* -lz4- and -lh0: No compression */
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
static void lzh_nocomp(obytes)
|
|
|
|
unsigned long obytes;
|
|
|
|
{
|
|
|
|
copy(lzh_file, lzh_data, (int)obytes);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef UNTESTED
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/* -lz5-: LZSS compression, variant 1 */
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
static void lzh_lzss1(obytes)
|
|
|
|
unsigned long obytes;
|
|
|
|
{
|
|
|
|
int mask, ch, lzcnt, lzptr, ptr, count;
|
|
|
|
char *p = lzh_lzbuf;
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
for(i = 0; i < 256; i++) {
|
|
|
|
for(j = 0; j < 13; j++) {
|
|
|
|
*p++ = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for(i = 0; i < 256; i++) {
|
|
|
|
*p++ = i;
|
|
|
|
}
|
|
|
|
for(i = 0; i < 256; i++) {
|
|
|
|
*p++ = 255 - i;
|
|
|
|
}
|
|
|
|
for(i = 0; i < 128; i++) {
|
|
|
|
*p++ = 0;
|
|
|
|
}
|
|
|
|
for(i = 0; i < 128; i++) {
|
|
|
|
*p++ = ' ';
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp_out_ptr = out_ptr;
|
|
|
|
out_ptr = lzh_file;
|
|
|
|
ptr = LZ5BUFFSIZE - LZ5LOOKAHEAD;
|
|
|
|
count = 0;
|
|
|
|
lzh_current = lzh_data;
|
|
|
|
while(obytes != 0) {
|
|
|
|
if(count == 0) {
|
|
|
|
mask = *lzh_current++ & BYTEMASK;
|
|
|
|
count = 8;
|
|
|
|
}
|
|
|
|
count--;
|
|
|
|
ch = *lzh_current++ & BYTEMASK;
|
|
|
|
if ((mask & 1) != 0) {
|
|
|
|
*out_ptr++ = ch;
|
|
|
|
lzh_lzbuf[ptr++] = ch;
|
|
|
|
ptr &= LZ5MASK;
|
|
|
|
obytes--;
|
|
|
|
} else {
|
|
|
|
lzcnt = *lzh_current++;
|
|
|
|
lzptr = (ch & 0x00ff) | ((lzcnt << 4) & 0x0f00);
|
|
|
|
lzcnt = (lzcnt & 0x000f) + 3;
|
|
|
|
obytes -= lzcnt;
|
|
|
|
do {
|
|
|
|
ch = lzh_lzbuf[lzptr++];
|
|
|
|
lzh_lzbuf[ptr++] = ch;
|
|
|
|
*out_ptr++ = ch;
|
|
|
|
lzptr &= LZ5MASK;
|
|
|
|
ptr &= LZ5MASK;
|
|
|
|
} while (--lzcnt != 0) ;
|
|
|
|
}
|
|
|
|
mask >>= 1;
|
|
|
|
}
|
|
|
|
out_ptr = tmp_out_ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/* -lzs-: LZSS compression, variant 2 */
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
static void lzh_lzss2(obytes)
|
|
|
|
unsigned long obytes;
|
|
|
|
{
|
|
|
|
int ch, lzcnt, lzptr, ptr, i;
|
|
|
|
|
|
|
|
tmp_out_ptr = out_ptr;
|
|
|
|
out_ptr = lzh_file;
|
|
|
|
ptr = LZSBUFFSIZE - LZSLOOKAHEAD;
|
|
|
|
for(i = 0; i < ptr; i++) {
|
|
|
|
lzh_lzbuf[i] = ' ';
|
|
|
|
}
|
|
|
|
for(i = ptr; i < LZSBUFFSIZE; i++) {
|
|
|
|
lzh_lzbuf[i] = 0;
|
|
|
|
}
|
|
|
|
bit_be_init_getbits();
|
|
|
|
bit_be_filestart = lzh_data;
|
|
|
|
bit_be_inbytes = -1;
|
|
|
|
while(obytes != 0) {
|
|
|
|
if(bit_be_getbits(1) == 0) {
|
|
|
|
ch = bit_be_getbits(8);
|
|
|
|
*out_ptr++ = ch;
|
|
|
|
lzh_lzbuf[ptr++] = ch;
|
|
|
|
ptr &= LZSMASK;
|
|
|
|
obytes--;
|
|
|
|
} else {
|
|
|
|
lzptr = bit_be_getbits(11);
|
|
|
|
lzcnt = bit_be_getbits(4) + 3;
|
|
|
|
obytes -= lzcnt;
|
|
|
|
do {
|
|
|
|
ch = lzh_lzbuf[lzptr++];
|
|
|
|
lzh_lzbuf[ptr++] = ch;
|
|
|
|
*out_ptr++ = ch;
|
|
|
|
lzptr &= LZSMASK;
|
|
|
|
ptr &= LZSMASK;
|
|
|
|
} while (--lzcnt != 0) ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
out_ptr = tmp_out_ptr;
|
|
|
|
}
|
|
|
|
#endif /* UNTESTED */
|
|
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/* -lh1-: LZ compression plus adaptive Huffman encoding */
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
static void lzh_lzah(obytes)
|
|
|
|
unsigned long obytes;
|
|
|
|
{
|
|
|
|
lzh_current = lzh_data + 2; /* SKIPPING BLOCKSIZE! */
|
|
|
|
tmp_out_ptr = out_ptr;
|
|
|
|
out_ptr = lzh_file;
|
|
|
|
lzah_getbyte = lzh_getbyte;
|
|
|
|
de_lzah(obytes);
|
|
|
|
out_ptr = tmp_out_ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned char lzh_getbyte()
|
|
|
|
{
|
|
|
|
return *lzh_current++;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef UNDEF
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/* -lh2-: LZ** compression */
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
static void lzh_lh2(obytes)
|
|
|
|
unsigned long obytes;
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/* -lh3-: LZ** compression */
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
static void lzh_lh3(obytes)
|
|
|
|
unsigned long obytes;
|
|
|
|
{
|
|
|
|
}
|
|
|
|
#endif /* UNDEF */
|
|
|
|
|
|
|
|
#ifdef UNTESTED
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/* -lh4-: LZ(12) compression plus Huffman encoding */
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
static void lzh_lzh12(obytes)
|
|
|
|
unsigned long obytes;
|
|
|
|
{
|
|
|
|
lzh_current = lzh_data;
|
|
|
|
tmp_out_ptr = out_ptr;
|
|
|
|
out_ptr = lzh_file;
|
|
|
|
/* Controlled by obytes only */
|
|
|
|
de_lzh((long)(-1), (long)obytes, &lzh_current, 12);
|
|
|
|
out_ptr = tmp_out_ptr;
|
|
|
|
}
|
|
|
|
#endif /* UNTESTED */
|
|
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/* -lh5-: LZ(13) compression plus Huffman encoding */
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
static void lzh_lzh13(obytes)
|
|
|
|
unsigned long obytes;
|
|
|
|
{
|
|
|
|
lzh_current = lzh_data;
|
|
|
|
tmp_out_ptr = out_ptr;
|
|
|
|
out_ptr = lzh_file;
|
|
|
|
/* Controlled by obytes only */
|
|
|
|
de_lzh((long)(-1), (long)obytes, &lzh_current, 13);
|
|
|
|
out_ptr = tmp_out_ptr;
|
|
|
|
}
|