#include "macunpack.h" #ifdef PIT #define PIT_INTERNAL #include "pit.h" #include #include #include "../fileio/fileglob.h" #include "../fileio/kind.h" #include "../fileio/machdr.h" #include "../fileio/wrfile.h" #include "../util/masks.h" #include "../util/transname.h" #include "../util/util.h" #include "crc.h" #include "de_huffman.h" #include "globals.h" #include "huffman.h" static int pit_filehdr(struct pit_header *f, int compr); static void pit_wrfile(uint32_t bytes, int type); static void pit_nocomp(uint32_t ibytes); static void pit_huffman(uint32_t obytes); void pit (void) { struct pit_header filehdr; char pithdr[4]; int decode, synced, ch; uint32_t data_crc, crc; updcrc = binhex_updcrc; crcinit = binhex_crcinit; set_huffman(HUFF_BE); synced = 0; while(1) { if(!synced) { if(fread(pithdr, 1, 4, infp) != 4) { (void)fprintf(stderr, "Premature EOF\n"); #ifdef SCAN do_error("macunpack: Premature EOF"); #endif /* SCAN */ exit(1); } } synced = 0; if(strncmp(pithdr, "PEnd", 4) == 0) { break; } if(strncmp(pithdr, "PMa", 3) != 0) { (void)fprintf(stderr, "File contains non PackIt info %.4s\n", pithdr); #ifdef SCAN do_error("macunpack: File contains non PackIt info"); #endif /* SCAN */ exit(1); } switch(pithdr[3]) { case 'g': case '4': break; case '5': case '6': if(pithdr[3] == '6') { (void)fprintf(stderr, "DES-"); } (void)fprintf(stderr, "Encrypted file found, trying to sync"); while(!synced) { ch = getb(infp); if(ch == 'P') { pithdr[0] = ch; pithdr[1] = ch = getb(infp); if(ch == 'M') { pithdr[2] = ch = getb(infp); if(ch == 'a') { pithdr[3] = ch = getb(infp); if((ch >= '4' && ch <= '6') || ch == 'g') { synced = 1; } } } else if(ch == 'E') { pithdr[2] = ch = getb(infp); if(ch == 'n') { pithdr[3] = ch = getb(infp); if(ch == 'd') { synced = 1; } } } if(!synced) { (void)ungetc(ch, infp); } } } (void)fprintf(stderr, ", done.\n"); #ifdef SCAN do_idf("", PROTECTED); #endif /* SCAN */ continue; default: (void)fprintf(stderr, "File contains non PackIt info %.4s\n", pithdr); #ifdef SCAN do_error("macunpack: File contains non PackIt info"); #endif /* SCAN */ exit(1); } bytes_read = 0; if(pithdr[3] == '4') { read_tree(); decode = huffman; } else { decode = nocomp; } if(pit_filehdr(&filehdr, decode) == -1) { (void)fprintf(stderr, "Can't read file header\n"); #ifdef SCAN do_error("macunpack: Can't read file header"); #endif /* SCAN */ exit(1); } bytes_written = filehdr.rlen + filehdr.dlen; start_info(info, filehdr.rlen, filehdr.dlen); start_data(); pit_wrfile(filehdr.dlen, decode); data_crc = (*updcrc)(INIT_CRC, (unsigned char*)out_buffer, filehdr.dlen); start_rsrc(); pit_wrfile(filehdr.rlen, decode); data_crc = (*updcrc)(data_crc, (unsigned char*)out_buffer, filehdr.rlen); if(decode == nocomp) { crc = getb(infp); crc = (crc << 8) | getb(infp); } else { crc = (getihuffbyte() & BYTEMASK) | ((getihuffbyte() & BYTEMASK) << 8); } if(crc != data_crc) { (void)fprintf(stderr, "CRC error in file: need 0x%04x, got 0x%04x\n", (int)crc, (int)data_crc); #ifdef SCAN do_error("macunpack: CRC error in file"); #endif /* SCAN */ exit(1); } if(verbose) { if(decode == nocomp) { (void)fprintf(stderr, "\tNo compression"); } else { (void)fprintf(stderr, "\tHuffman compressed (%4.1f%%)", 100.0 * bytes_read / bytes_written); } } if(write_it) { end_file(); } if(verbose) { (void)fprintf(stderr, ".\n"); } } } static int pit_filehdr (struct pit_header *f, int compr) { register int i; uint32_t crc; int n; char hdr[HDRBYTES]; char ftype[5], fauth[5]; for(i = 0; i < INFOBYTES; i++) info[i] = '\0'; if(compr == huffman) { for(i = 0; i < HDRBYTES; i++) { hdr[i] = getihuffbyte(); } } else { if(fread(hdr, 1, HDRBYTES, infp) != HDRBYTES) { return -1; } } crc = INIT_CRC; crc = (*updcrc)(crc, (unsigned char*)hdr, HDRBYTES - 2); f->hdrCRC = get2(hdr + H_HDRCRC); if(f->hdrCRC != crc) { (void)fprintf(stderr, "\tHeader CRC mismatch: got 0x%04x, need 0x%04x\n", f->hdrCRC & WORDMASK, (int)crc); return -1; } n = hdr[H_NLENOFF] & BYTEMASK; if(n > H_NAMELEN) { n = H_NAMELEN; } info[I_NAMEOFF] = n; copy(info + I_NAMEOFF + 1, hdr + H_NAMEOFF, n); transname(hdr + H_NAMEOFF, text, n); text[n] = '\0'; f->rlen = get4(hdr + H_RLENOFF); f->dlen = get4(hdr + H_DLENOFF); write_it = 1; if(list) { transname(hdr + H_TYPEOFF, ftype, 4); transname(hdr + H_AUTHOFF, fauth, 4); do_indent(indent); (void)fprintf(stderr, "name=\"%s\", type=%4.4s, author=%4.4s, data=%d, rsrc=%d", text, ftype, fauth, (int32_t)f->dlen, (int32_t)f->rlen); if(info_only) { write_it = 0; } if(query) { write_it = do_query(); } else { (void)fputc('\n', stderr); } } if(write_it) { define_name(text); copy(info + I_TYPEOFF, hdr + H_TYPEOFF, 4); copy(info + I_AUTHOFF, hdr + H_AUTHOFF, 4); copy(info + I_FLAGOFF, hdr + H_FLAGOFF, 2); copy(info + I_LOCKOFF, hdr + H_LOCKOFF, 2); copy(info + I_DLENOFF, hdr + H_DLENOFF, 4); copy(info + I_RLENOFF, hdr + H_RLENOFF, 4); copy(info + I_CTIMOFF, hdr + H_CTIMOFF, 4); copy(info + I_MTIMOFF, hdr + H_MTIMOFF, 4); } return 1; } static void pit_wrfile (uint32_t bytes, int type) { if(bytes == 0) { return; } switch(type) { case nocomp: pit_nocomp(bytes); break; case huffman: pit_huffman(bytes); } } /*---------------------------------------------------------------------------*/ /* No compression */ /*---------------------------------------------------------------------------*/ static void pit_nocomp (uint32_t ibytes) { int n; n = fread(out_buffer, 1, (int)ibytes, infp); if(n != ibytes) { (void)fprintf(stderr, "Premature EOF\n"); #ifdef SCAN do_error("macunpack: Premature EOF"); #endif /* SCAN */ exit(1); } } /*---------------------------------------------------------------------------*/ /* Huffman compression */ /*---------------------------------------------------------------------------*/ static void pit_huffman (uint32_t obytes) { de_huffman(obytes); } #else /* PIT */ int pit; /* keep lint and some compilers happy */ #endif /* PIT */