home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / APPS / macutils.lzh / MACUTILS / MACUNPACK / dd.c < prev    next >
C/C++ Source or Header  |  1995-09-18  |  25KB  |  1,043 lines

  1. #include "macunpack.h"
  2. #ifdef DD
  3. #include "globals.h"
  4. #include "dd.h"
  5. #include "crc.h"
  6. #include "../fileio/machdr.h"
  7. #include "../fileio/wrfile.h"
  8. #include "../fileio/fileglob.h"
  9. #include "../util/masks.h"
  10. #include "../util/util.h"
  11.  
  12. extern char *malloc();
  13. extern char *realloc();
  14. extern char *strcpy();
  15. extern char *strncpy();
  16. extern void cpt_wrfile1();
  17. extern void core_compress();
  18. extern void de_compress();
  19.  
  20. static void dd_name();
  21. static int dd_filehdr();
  22. static void dd_cfilehdr();
  23. static int dd_valid();
  24. static int dd_valid1();
  25. static char *dd_methname();
  26. static unsigned long dd_checksum();
  27. static void dd_chksum();
  28. static unsigned long dd_checkor();
  29. static void dd_do_delta();
  30. static void dd_delta();
  31. static void dd_delta3();
  32. static void dd_copy();
  33. static void dd_copyfile();
  34. static void dd_expand();
  35. static void dd_expandfile();
  36. static void dd_nocomp();
  37. static void dd_lzc();
  38. #ifdef UNTESTED
  39. static void dd_rle();
  40. #ifdef NOTIMPLEMENTED
  41. static void dd_huffman();
  42. #endif /* NOTIMPLEMENTED */
  43. static void dd_lzss();
  44. static int dd_getbits();
  45. #endif /* UNTESTED */
  46. static void dd_cpt_compat();
  47.  
  48. typedef struct methodinfo {
  49.     char *name;
  50.     int number;
  51. };
  52.  
  53. static struct methodinfo methods[] = {
  54.     {"NoComp",  nocomp},
  55.     {"LZC",     lzc},
  56.     {"???",    method2},
  57.     {"RLE",     rle},
  58.     {"Huffman", huffman},
  59.     {"???",    method5},
  60.     {"???",    method6},
  61.     {"LZSS",    lzss},
  62.     {"RLE/LZH",    cpt_compat},
  63.     {"???",    method9},
  64. };
  65. static unsigned char *dd_archive;
  66. static unsigned char *dd_data_ptr;
  67. static int dd_archive_size;
  68. static int dd_max_archive_size;
  69. static unsigned char *dd_dirst;
  70. static int dd_dirstptr;
  71. static int dd_dirstmax;
  72. static int dd_xor;
  73. static long dd_bitbuf;
  74. static int dd_bitcount;
  75. static unsigned char *dd_bitptr;
  76. static char dd_LZbuff[2048];
  77.  
  78. void dd_file(bin_hdr)
  79. unsigned char *bin_hdr;
  80. {
  81.     unsigned long data_size;
  82.     int i;
  83.     struct fileCHdr cf;
  84.     char ftype[5], fauth[5];
  85.  
  86.     updcrc = binhex_updcrc;
  87.     crcinit = binhex_crcinit;
  88.     dd_name(bin_hdr);
  89.     for(i = 0; i < INFOBYTES; i++) {
  90.     info[i] = bin_hdr[i];
  91.     }
  92.     transname(info + I_NAMEOFF + 1, text, (int)info[I_NAMEOFF] & BYTEMASK);
  93.     data_size = get4(info + I_DLENOFF);
  94.     if(data_size > dd_max_archive_size) {
  95.     if(dd_max_archive_size == 0) {
  96.         dd_archive = (unsigned char *)malloc((unsigned)data_size);
  97.     } else {
  98.         dd_archive = (unsigned char *)realloc((char *)dd_archive,
  99.                         (unsigned)data_size);
  100.     }
  101.     dd_max_archive_size = data_size;
  102.     if(dd_archive == NULL) {
  103.         (void)fprintf(stderr, "Insufficient memory.\n");
  104.         exit(1);
  105.     }
  106.     }
  107.     dd_archive_size = data_size;
  108.     if(fread((char *)dd_archive, 1, (int)data_size, infp) != data_size) {
  109.     (void)fprintf(stderr, "Premature EOF\n");
  110. #ifdef SCAN
  111.     do_error("Premature EOF");
  112. #endif /* SCAN */
  113.     exit(1);
  114.     }
  115.     dd_data_ptr = dd_archive;
  116.     dd_cfilehdr(&cf);
  117.     write_it = 1;
  118.     if(list) {
  119.     do_indent(indent);
  120.     transname(info + I_TYPEOFF, ftype, 4);
  121.     transname(info + I_AUTHOFF, fauth, 4);
  122.     (void)fprintf(stderr,
  123.         "name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld",
  124.         text, ftype, fauth,
  125.         (long)get4(info + I_DLENOFF), (long)get4(info + I_RLENOFF));
  126.     if(info_only) {
  127.         write_it = 0;
  128.     }
  129.     if(query) {
  130.         write_it = do_query();
  131.     } else {
  132.         (void)fputc('\n', stderr);
  133.     }
  134.     }
  135.     if(!dd_valid((int)cf.datamethod, (int)cf.rsrcmethod)) {
  136.     (void)fprintf(stderr, "\tUnimplemented method found: %d %d\n",
  137.         cf.datamethod, cf.rsrcmethod);
  138. #ifdef SCAN
  139.     do_error("macunpack: Unimplemented method found");
  140. #endif /* SCAN */
  141.     return;
  142.     }
  143.  
  144.     if(write_it) {
  145.     define_name(text);
  146.     }
  147.     if(write_it || list) {
  148.     dd_expand(cf, dd_data_ptr);
  149.     }
  150. }
  151.  
  152. void dd_arch(bin_hdr)
  153. unsigned char *bin_hdr;
  154. {
  155.     unsigned long data_size;
  156.     unsigned long crc, filecrc;
  157.     struct fileHdr f;
  158.     struct fileCHdr cf;
  159.     char locname[64];
  160.     int i, nlength;
  161.  
  162.     updcrc = binhex_updcrc;
  163.     crcinit = binhex_crcinit;
  164.     data_size = get4((char *)bin_hdr + I_DLENOFF);
  165.     if(data_size > dd_max_archive_size) {
  166.     if(dd_max_archive_size == 0) {
  167.         dd_archive = (unsigned char *)malloc((unsigned)data_size);
  168.     } else {
  169.         dd_archive = (unsigned char *)realloc((char *)dd_archive,
  170.                         (unsigned)data_size);
  171.     }
  172.     dd_max_archive_size = data_size;
  173.     }
  174.     dd_archive_size = data_size;
  175.     if(fread((char *)dd_archive, 1, (int)data_size, infp) != data_size) {
  176.     (void)fprintf(stderr, "Insufficient memory.\n");
  177.     exit(1);
  178.     }
  179.     dd_name(bin_hdr);
  180.     nlength = bin_hdr[I_NAMEOFF];
  181.     for(i = 0; i < INFOBYTES; i++) {
  182.     info[i] = 0;
  183.     }
  184.     info[I_NAMEOFF] = nlength;
  185.     for(i = 1; i <= nlength; i++) {
  186.     info[I_NAMEOFF + i] = bin_hdr[I_NAMEOFF + i];
  187.     }
  188.     transname(info + I_NAMEOFF + 1, text, nlength);
  189.     (void)strcpy(locname, text);
  190.     if(list) {
  191.     do_indent(indent);
  192.     (void)fprintf(stderr, "folder=\"%s\"", text);
  193.     if(query) {
  194.         if(!do_query()) {
  195.         return;
  196.         }
  197.     } else {
  198.         (void)fputc('\n', stderr);
  199.     }
  200.     indent++;
  201.     }
  202.     if(!info_only) {
  203.     do_mkdir(text, info);
  204.     }
  205.  
  206.     if(strncmp((char *)dd_archive, "DDAR", 4)) {
  207.     (void)fprintf(stderr, "Magic archive header error\n");
  208. #ifdef SCAN
  209.     do_error("macunpack: Magic archive header error");
  210. #endif /* SCAN */
  211.     exit(1);
  212.     }
  213.     crc = (*updcrc)(crcinit, dd_archive, ARCHHDRSIZE - 2);
  214.     filecrc = get2((char *)dd_archive + ARCHHDRCRC);
  215.     if(crc != filecrc) {
  216.     (void)fprintf(stderr, "Header CRC mismatch: got 0x%02x, need 0x%02x\n",
  217.         (int)crc, (int)filecrc);
  218. #ifdef SCAN
  219.     do_error("macunpack: Header CRC mismatch");
  220. #endif /* SCAN */
  221.     exit(1);
  222.     }
  223.     dd_data_ptr = dd_archive + ARCHHDRSIZE;
  224.     while(dd_data_ptr < dd_archive + data_size) {
  225.     switch(dd_filehdr(&f, &cf, dir_skip)) {
  226.     case DD_FILE:
  227.         dd_chksum(f, dd_data_ptr);
  228.         dd_expand(cf, dd_data_ptr);
  229.     case DD_IVAL:
  230.         dd_data_ptr += f.dataLength - CFILEHDRSIZE;
  231.         break;
  232.     case DD_COPY:
  233.         dd_copy(f, dd_data_ptr);
  234.         dd_data_ptr += f.dataLength + f.rsrcLength;
  235.         break;
  236.     case DD_SDIR:
  237.         if(write_it || info_only) {
  238.         if(write_it) {
  239.             do_mkdir(text, info);
  240.         }
  241.         if(dd_dirstptr == dd_dirstmax) {
  242.             if(dd_dirstmax == 0) {
  243.             dd_dirst = (unsigned char *)malloc(64);
  244.             } else {
  245.             dd_dirst = (unsigned char *)realloc((char *)dd_dirst,
  246.                         (unsigned)dd_dirstmax + 64);
  247.             }
  248.             dd_dirstmax += 64;
  249.         }
  250.         for(i = 0; i < 64; i++) {
  251.             dd_dirst[dd_dirstptr + i] = text[i];
  252.         }
  253.         dd_dirst += 64;
  254.         indent++;
  255.         } else {
  256.         dir_skip++;
  257.         }
  258.         break;
  259.     case DD_EDIR:
  260.         if(dir_skip) {
  261.         dir_skip--;
  262.         } else {
  263.         dd_dirst -= 64;
  264.         indent--;
  265.         if(list) {
  266.             do_indent(indent);
  267.             (void)fprintf(stderr, "leaving folder \"%s\"\n",
  268.                 dd_dirst + dd_dirstptr);
  269.         }
  270.         if(!info_only) {
  271.             enddir();
  272.         }
  273.         }
  274.     }
  275.     }
  276.     if(!info_only) {
  277.     enddir();
  278.     }
  279.     if(list) {
  280.     indent--;
  281.     do_indent(indent);
  282.     (void)fprintf(stderr, "leaving folder \"%s\"\n", locname);
  283.     }
  284. }
  285.  
  286. static void dd_name(bin_hdr)
  287. unsigned char *bin_hdr;
  288. {
  289.     int nlength;
  290.     unsigned char *extptr;
  291.  
  292.     nlength = bin_hdr[I_NAMEOFF] & BYTEMASK;
  293.     extptr = bin_hdr + I_NAMEOFF + nlength - 3;
  294.     if(!strncmp((char *)extptr, ".sea", 4) ||
  295.        !strncmp((char *)extptr, ".Sea", 4) ||
  296.        !strncmp((char *)extptr, ".SEA", 4)) {
  297.     nlength -= 4;
  298.     extptr[0] = 0;
  299.     extptr[1] = 0;
  300.     extptr[2] = 0;
  301.     extptr[3] = 0;
  302.     bin_hdr[I_NAMEOFF] = nlength;
  303.     return;
  304.     }
  305.     extptr++;
  306.     if(!strncmp((char *)extptr, ".dd", 3)) {
  307.     nlength -=3;
  308.     extptr[0] = 0;
  309.     extptr[1] = 0;
  310.     extptr[2] = 0;
  311.     bin_hdr[I_NAMEOFF] = nlength;
  312.     return;
  313.     }
  314.     if(nlength < 31) {
  315.     nlength++;
  316.     }
  317.     bin_hdr[I_NAMEOFF + nlength] = 0xA5;
  318.     bin_hdr[I_NAMEOFF] = nlength;
  319. }
  320.  
  321. static int dd_filehdr(f, cf, skip)
  322. struct fileHdr *f;
  323. struct fileCHdr *cf;
  324. int skip;
  325. {
  326.     register int i;
  327.     unsigned long crc;
  328.     int n, to_uncompress;
  329.     unsigned char *hdr;
  330.     char ftype[5], fauth[5];
  331.     unsigned long datalength, rsrclength;
  332.  
  333.     to_uncompress = DD_COPY;
  334.     hdr = dd_data_ptr;
  335.     dd_data_ptr += FILEHDRSIZE;
  336.     for(i = 0; i < INFOBYTES; i++) {
  337.     info[i] = '\0';
  338.     }
  339.     crc = INIT_CRC;
  340.     crc = (*updcrc)(crc, hdr, FILEHDRSIZE - 2);
  341.  
  342.     f->hdrcrc = get2((char *)hdr + D_HDRCRC);
  343.     if(f->hdrcrc != crc) {
  344.     (void)fprintf(stderr, "Header CRC mismatch: got 0x%04x, need 0x%04x\n",
  345.         f->hdrcrc & WORDMASK, (int)crc);
  346. #ifdef SCAN
  347.     do_error("macunpack: Header CRC mismatch");
  348. #endif /* SCAN */
  349.     exit(1);
  350.     }
  351.  
  352.     n = hdr[D_FNAME] & BYTEMASK;
  353.     if(n > F_NAMELEN) {
  354.     n = F_NAMELEN;
  355.     }
  356.     info[I_NAMEOFF] = n;
  357.     copy(info + I_NAMEOFF + 1, (char *)hdr + D_FNAME + 1, n);
  358.     transname((char *)hdr + D_FNAME + 1, text, n);
  359.  
  360.     if(!hdr[D_ISDIR]) {
  361.     f->datacrc = get2((char *)hdr + D_DATACRC);
  362.     f->rsrccrc = get2((char *)hdr + D_RSRCCRC);
  363.     f->dataLength = get4((char *)hdr + D_DATALENGTH);
  364.     f->rsrcLength = get4((char *)hdr + D_RSRCLENGTH);
  365.     copy(info + I_DLENOFF, (char *)hdr + D_DATALENGTH, 4);
  366.     copy(info + I_RLENOFF, (char *)hdr + D_RSRCLENGTH, 4);
  367.     copy(info + I_CTIMOFF, (char *)hdr + D_CTIME, 4);
  368.     copy(info + I_MTIMOFF, (char *)hdr + D_MTIME, 4);
  369.     copy(info + I_TYPEOFF, (char *)hdr + D_FTYPE, 4);
  370.     copy(info + I_AUTHOFF, (char *)hdr + D_CREATOR, 4);
  371.     copy(info + I_FLAGOFF, (char *)hdr + D_FNDRFLAGS, 2);
  372.     }
  373.  
  374.     if(hdr[D_ISDIR]) {
  375.     to_uncompress = DD_SDIR;
  376.     } else if(hdr[D_ENDDIR]) {
  377.     to_uncompress = DD_EDIR;
  378.     } else if(!no_dd && ((hdr[D_FNDRFLAGS] & 0x80) == 0)) {
  379.     dd_cfilehdr(cf);
  380.     to_uncompress = DD_FILE;
  381.     datalength = cf->dataLength;
  382.     rsrclength = cf->rsrcLength;
  383.     } else {
  384.     datalength = f->dataLength;
  385.     rsrclength = f->rsrcLength;
  386.     }
  387.     hdr[D_FNDRFLAGS] &= 0x7f;
  388.     write_it = !skip;
  389.     if(list && !skip) {
  390.     if(to_uncompress != DD_EDIR) {
  391.         do_indent(indent);
  392.     }
  393.     if(to_uncompress == DD_SDIR) {
  394.         (void)fprintf(stderr, "folder=\"%s\"", text);
  395.     } else if(to_uncompress != DD_EDIR) {
  396.         transname(info + I_TYPEOFF, ftype, 4);
  397.         transname(info + I_AUTHOFF, fauth, 4);
  398.         (void)fprintf(stderr,
  399.             "name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld",
  400.             text, ftype, fauth, (long)datalength, (long)rsrclength);
  401.     }
  402.     if(info_only) {
  403.         write_it = 0;
  404.     }
  405.     if(to_uncompress != DD_EDIR) {
  406.         if(query) {
  407.         write_it = do_query();
  408.         } else {
  409.         (void)fputc('\n', stderr);
  410.         }
  411.     }
  412.     if(to_uncompress == DD_FILE) {
  413.         if(!dd_valid((int)cf->datamethod, (int)cf->rsrcmethod)) {
  414.         (void)fprintf(stderr, "\tUnimplemented method found: %d %d\n",
  415.             cf->datamethod, cf->rsrcmethod);
  416. #ifdef SCAN
  417.         do_error("macunpack: Unimplemented method found");
  418. #endif /* SCAN */
  419.         return DD_IVAL;
  420.         }
  421.     }
  422.     }
  423.  
  424.     if(write_it) {
  425.     define_name(text);
  426.     }
  427.     return to_uncompress;
  428. }
  429.  
  430. static void dd_cfilehdr(f)
  431. struct fileCHdr *f;
  432. {
  433.     unsigned long crc;
  434.     unsigned char *hdr;
  435.  
  436.     hdr = dd_data_ptr;
  437.     dd_data_ptr += CFILEHDRSIZE;
  438.     crc = INIT_CRC;
  439.     crc = (*updcrc)(crc, hdr, CFILEHDRSIZE - 2);
  440.  
  441.     f->hdrcrc = get2((char *)hdr + C_HDRCRC);
  442.     if(f->hdrcrc != crc) {
  443.     (void)fprintf(stderr, "Header CRC mismatch: got 0x%04x, need 0x%04x\n",
  444.         f->hdrcrc & WORDMASK, (int)crc);
  445. #ifdef SCAN
  446.     do_error("macunpack: Header CRC mismatch");
  447. #endif /* SCAN */
  448.     exit(1);
  449.     }
  450.  
  451.     f->dataLength = get4((char *)hdr + C_DATALENGTH);
  452.     f->dataCLength = get4((char *)hdr + C_DATACLENGTH);
  453.     f->rsrcLength = get4((char *)hdr + C_RSRCLENGTH);
  454.     f->rsrcCLength = get4((char *)hdr + C_RSRCCLENGTH);
  455.     f->datamethod = hdr[C_DATAMETHOD];
  456.     f->rsrcmethod = hdr[C_RSRCMETHOD];
  457.     f->datacrc = get2((char *)hdr + C_DATACRC);
  458.     f->rsrccrc = get2((char *)hdr + C_RSRCCRC);
  459.     f->datainfo = get2((char *)hdr + C_DATAINFO);
  460.     f->rsrcinfo = get2((char *)hdr + C_RSRCINFO);
  461.     f->datacrc2 = get2((char *)hdr + C_DATACRC2);
  462.     f->rsrccrc2 = get2((char *)hdr + C_RSRCCRC2);
  463.     f->info1 = hdr[C_INFO1];
  464.     f->info2 = hdr[C_INFO2];
  465.     copy(info + I_DLENOFF, (char *)hdr + C_DATALENGTH, 4);
  466.     copy(info + I_RLENOFF, (char *)hdr + C_RSRCLENGTH, 4);
  467.     copy(info + I_CTIMOFF, (char *)hdr + C_CTIME, 4);
  468.     copy(info + I_MTIMOFF, (char *)hdr + C_MTIME, 4);
  469.     copy(info + I_TYPEOFF, (char *)hdr + C_FTYPE, 4);
  470.     copy(info + I_AUTHOFF, (char *)hdr + C_CREATOR, 4);
  471.     copy(info + I_FLAGOFF, (char *)hdr + C_FNDRFLAGS, 2);
  472.     if(f->info1 >= 0x2a && (f->info2 & 0x80) == 0) {
  473.     dd_xor = 0x5a;
  474.     } else {
  475.     dd_xor = 0;
  476.     }
  477. }
  478.  
  479. static int dd_valid(dmethod, rmethod)
  480. int dmethod, rmethod;
  481. {
  482.     return dd_valid1(dmethod) | dd_valid1(rmethod);
  483. }
  484.  
  485. static int dd_valid1(method)
  486. int method;
  487. {
  488.     switch(method) {
  489.     case nocomp:
  490.     case lzc:
  491. #ifdef UNTESTED
  492.     case rle:
  493. #ifdef NOTIMPLEMENTED
  494.     case huffman:
  495. #endif /* NOTIMPLEMENTED */
  496.     case lzss:
  497. #endif /* UNTESTED */
  498.     case cpt_compat:
  499.     return 1;
  500.     }
  501.     return 0;
  502. }
  503.  
  504. static char *dd_methname(n)
  505. int n;
  506. {
  507. int i, nmeths;
  508.     nmeths = sizeof(methods) / sizeof(struct methodinfo);
  509.     for(i = 0; i < nmeths; i++) {
  510.     if(methods[i].number == n) {
  511.         return methods[i].name;
  512.     }
  513.     }
  514.     return NULL;
  515. }
  516.  
  517. static unsigned long dd_checksum(init, buffer, length)
  518. unsigned long init;
  519. char *buffer;
  520. unsigned long length;
  521. {
  522.     int i;
  523.     unsigned long cks;
  524.  
  525.     cks = init;
  526.     for(i = 0; i < length; i++) {
  527.     cks += *buffer++ & BYTEMASK;
  528.     }
  529.     return cks & WORDMASK;
  530. }
  531.  
  532. static void dd_chksum(hdr, data)
  533. struct fileHdr hdr;
  534. unsigned char *data;
  535. {
  536.     unsigned long cks;
  537.  
  538.     if(write_it) {
  539.     cks = dd_checksum(INIT_CRC, (char *)data - CFILEHDRSIZE,
  540.               hdr.dataLength);
  541.     if(hdr.datacrc != cks) {
  542.         (void)fprintf(stderr,
  543.         "Checksum error on compressed file: need 0x%04x, got 0x%04x\n",
  544.         hdr.datacrc, (int)cks);
  545. #ifdef SCAN
  546.         do_error("macunpack: Checksum error on compressed file");
  547. #endif /* SCAN */
  548.         exit(1);
  549.     }
  550.     }
  551. }
  552.  
  553. static unsigned long dd_checkor(init, buffer, length)
  554. unsigned long init;
  555. char *buffer;
  556. unsigned long length;
  557. {
  558.     int i;
  559.     unsigned long cks;
  560.  
  561.     cks = init;
  562.     for(i = 0; i < length; i++) {
  563.     cks ^= *buffer++ & BYTEMASK;
  564.     }
  565.     return cks & WORDMASK;
  566. }
  567.  
  568. static void dd_do_delta(out_ptr, nbytes, kind)
  569. char *out_ptr;
  570. unsigned long nbytes;
  571. int kind;
  572. {
  573.     switch(kind) {
  574.     case 0:
  575.     break;
  576.     case 1:
  577.     dd_delta(out_ptr, nbytes);
  578.     break;
  579.     case 2:
  580.     dd_delta3(out_ptr, nbytes);
  581.     break;
  582.     default:
  583.     (void)fprintf(stderr, "Illegal kind value found: %d\n", kind);
  584. #ifdef SCAN
  585.     do_error("Illegal kind value found");
  586. #endif /* SCAN */
  587.     exit(1);
  588.     }
  589. }
  590.  
  591. static void dd_delta(out_ptr, nbytes)
  592. char *out_ptr;
  593. unsigned long nbytes;
  594. {
  595.     int i, sum = 0;
  596.  
  597.     for(i = 0; i < nbytes; i++) {
  598.     sum = (sum + *out_ptr) & BYTEMASK;
  599.     *out_ptr++ = sum;
  600.     }
  601. }
  602.  
  603. static void dd_delta3(out_ptr, nbytes)
  604. char *out_ptr;
  605. unsigned long nbytes;
  606. {
  607.     int i, sum1 = 0, sum2 = 0, sum3 = 0;
  608.  
  609.     for(i = 0; i < nbytes; i += 3) {
  610.     sum1 = (sum1 + *out_ptr) & BYTEMASK;
  611.     *out_ptr++ = sum1;
  612.     if(i < nbytes - 1) {
  613.         sum2 = (sum2 + *out_ptr) & BYTEMASK;
  614.         *out_ptr++ = sum2;
  615.         if(i < nbytes) {
  616.         sum3 = (sum3 + *out_ptr) & BYTEMASK;
  617.         *out_ptr++ = sum3;
  618.         }
  619.     }
  620.     }
  621. }
  622.  
  623. /*---------------------------------------------------------------------------*/
  624. /*    Archive only, no compression                         */
  625. /*---------------------------------------------------------------------------*/
  626. static void dd_copy(hdr, data)
  627. struct fileHdr hdr;
  628. unsigned char *data;
  629. {
  630.     unsigned long cks;
  631.  
  632.     if(write_it) {
  633.     start_info(info, hdr.rsrcLength, hdr.dataLength);
  634.     }
  635.     if(verbose) {
  636.     (void)fprintf(stderr, "\tNo compression");
  637.     }
  638.     if(write_it) {
  639.     start_data();
  640.     }
  641.     dd_copyfile(hdr.dataLength, data);
  642.     data += hdr.dataLength;
  643.     if(write_it) {
  644.     cks = dd_checksum(INIT_CRC, out_buffer, hdr.dataLength);
  645.     if(hdr.datacrc != cks) {
  646.         (void)fprintf(stderr,
  647.         "Checksum error on data fork: need 0x%04x, got 0x%04x\n",
  648.         hdr.datacrc, (int)cks);
  649. #ifdef SCAN
  650.         do_error("macunpack: Checksum error on data fork");
  651. #endif /* SCAN */
  652.         exit(1);
  653.     }
  654.     }
  655.     if(write_it) {
  656.     start_rsrc();
  657.     }
  658.     dd_copyfile(hdr.rsrcLength, data);
  659.     data += hdr.rsrcLength;
  660.     if(write_it) {
  661.     cks = dd_checksum(INIT_CRC, out_buffer, hdr.rsrcLength);
  662.     if(hdr.rsrccrc != cks) {
  663.         (void)fprintf(stderr,
  664.         "Checksum error on resource fork: need 0x%04x, got 0x%04x\n",
  665.         hdr.rsrccrc, (int)cks);
  666. #ifdef SCAN
  667.         do_error("macunpack: Checksum error on resource fork");
  668. #endif /* SCAN */
  669.         exit(1);
  670.     }
  671.     end_file();
  672.     }
  673.     if(verbose) {
  674.     (void)fprintf(stderr, ".\n");
  675.     }
  676. }
  677.  
  678. static void dd_copyfile(obytes, data)
  679. unsigned long obytes;
  680. unsigned char *data;
  681. {
  682.     if(obytes == 0) {
  683.     return;
  684.     }
  685.     if(write_it) {
  686.     copy(out_ptr, (char *)data, (int)obytes);
  687.     }
  688. }
  689.  
  690. /*---------------------------------------------------------------------------*/
  691. /*    Possible compression, and perhaps in an archive                 */
  692. /*---------------------------------------------------------------------------*/
  693. static void dd_expand(hdr, data)
  694. struct fileCHdr hdr;
  695. unsigned char *data;
  696. {
  697.     unsigned long cks;
  698.     char *out_buf;
  699.  
  700.     if(write_it) {
  701.     start_info(info, hdr.rsrcLength, hdr.dataLength);
  702.     }
  703.     if(verbose) {
  704.     (void)fprintf(stderr, "\tData: ");
  705.     }
  706.     if(write_it) {
  707.     start_data();
  708.     }
  709.     out_buf = out_buffer;
  710.     dd_expandfile(hdr.dataLength, hdr.dataCLength, (int)hdr.datamethod, 
  711.     (int)hdr.datainfo, data, (unsigned long)hdr.datacrc);
  712.     data += hdr.dataCLength;
  713.     if(write_it) {
  714.     if((hdr.info2 & 0x40) && (hdr.dataLength != 0)) {
  715.         cks = arc_updcrc(INIT_CRC, (unsigned char *)out_buf,
  716.                  (int)hdr.dataLength);
  717.         if(cks != hdr.datacrc2) {
  718.         (void)fprintf(stderr,
  719.             "Checksum error on data fork: need 0x%04x, got 0x%04x\n",
  720.             (int)hdr.datacrc2, (int)cks);
  721. #ifdef SCAN
  722.         do_error("macunpack: Checksum error on data fork");
  723. #endif /* SCAN */
  724.         exit(1);
  725.         }
  726.     }
  727.     }
  728.     if(verbose) {
  729.     (void)fprintf(stderr, ", Rsrc: ");
  730.     }
  731.     if(write_it) {
  732.     start_rsrc();
  733.     }
  734.     out_buf = out_buffer;
  735.     dd_expandfile(hdr.rsrcLength, hdr.rsrcCLength, (int)hdr.rsrcmethod,
  736.     (int)hdr.rsrcinfo, data, (unsigned long)hdr.rsrccrc);
  737.     data += hdr.rsrcCLength;
  738.     if(write_it) {
  739.     if((hdr.info2 & 0x40) && (hdr.rsrcLength != 0)) {
  740.         cks = arc_updcrc(INIT_CRC, (unsigned char *)out_buf,
  741.                  (int)hdr.rsrcLength);
  742.         if(cks != hdr.rsrccrc2) {
  743.         (void)fprintf(stderr,
  744.            "Checksum error on resource fork: need 0x%04x, got 0x%04x\n",
  745.             (int)hdr.rsrccrc2, (int)cks);
  746. #ifdef SCAN
  747.         do_error("macunpack: Checksum error on resource fork");
  748. #endif /* SCAN */
  749.         exit(1);
  750.         }
  751.     }
  752.     end_file();
  753.     }
  754.     if(verbose) {
  755.     (void)fprintf(stderr, ".\n");
  756.     }
  757. }
  758.  
  759. static void dd_expandfile(obytes, ibytes, method, kind, data, chksum)
  760. unsigned long obytes, ibytes, chksum;
  761. int method, kind;
  762. unsigned char *data;
  763. {
  764.     int sub_method, m1, m2;
  765.     char *optr = out_ptr;
  766.     unsigned long cksinit;
  767.  
  768.     if(obytes == 0) {
  769.     if(verbose) {
  770.         (void)fprintf(stderr, "empty");
  771.     }
  772.     return;
  773.     }
  774.     switch(method & 0x7f) {
  775.     case nocomp:
  776.     if(verbose) {
  777.         (void)fprintf(stderr, "No compression");
  778.     }
  779.     if(write_it) {
  780.         dd_nocomp(obytes, data);
  781.     }
  782.     break;
  783.     case lzc:
  784.     m1 = (*data++ & BYTEMASK) ^ dd_xor;
  785.     m2 = (*data++ & BYTEMASK) ^ dd_xor;
  786.     sub_method = (*data++ & BYTEMASK) ^ dd_xor;
  787.     cksinit = m1 + m2 + sub_method;
  788.     sub_method = sub_method & 0x1f;
  789.     if(verbose) {
  790.         (void)fprintf(stderr, "LZC(%d) compressed (%4.1f%%)",
  791.             sub_method, 100.0 * ibytes / obytes);
  792.     }
  793.     if(write_it) {
  794.         dd_lzc(ibytes - 3, obytes, data, sub_method, chksum, cksinit);
  795.     }
  796.     break;
  797. #ifdef UNTESTED
  798.     case rle:
  799.     if(verbose) {
  800.         (void)fprintf(stderr, "RLE compressed (%4.1f%%)",
  801.             100.0 * ibytes / obytes);
  802.     }
  803.     if(write_it) {
  804.         dd_rle(ibytes, data);
  805.     }
  806.     break;
  807. #ifdef NOTIMPLEMENTED
  808.     case huffman:
  809.     if(verbose) {
  810.         (void)fprintf(stderr, "Huffman compressed (%4.1f%%)",
  811.             100.0 * ibytes / obytes);
  812.     }
  813.     if(write_it) {
  814.         dd_huffman(ibytes, data);
  815.     }
  816.     break;
  817. #endif /* NOTIMPLEMENTED */
  818.     case lzss:
  819.     if(verbose) {
  820.         (void)fprintf(stderr, "LZSS compressed (%4.1f%%)",
  821.             100.0 * ibytes / obytes);
  822.     }
  823.     if(write_it) {
  824.         dd_lzss(data, chksum);
  825.     }
  826.     break;
  827. #endif /* UNTESTED */
  828.     case cpt_compat:
  829.     sub_method = get2((char *)data);
  830.     data += 16;
  831.     if(sub_method != 0) {
  832.         sub_method = 0;
  833.     } else {
  834.         sub_method = 1;
  835.     }
  836.     if(verbose) {
  837.         if(!sub_method) {
  838.         (void)fprintf(stderr, "RLE compressed (%4.1f%%)",
  839.             100.0 * ibytes / obytes);
  840.         } else {
  841.         (void)fprintf(stderr, "RLE/LZH compressed (%4.1f%%)",
  842.             100.0 * ibytes / obytes);
  843.         }
  844.     }
  845.     if(write_it) {
  846.         dd_cpt_compat(ibytes, obytes, data, sub_method, chksum);
  847.     }
  848.     break;
  849.     default:
  850.     break;
  851.     }
  852.     if(write_it) {
  853.     dd_do_delta(optr, obytes, kind);
  854.     }
  855. }
  856.  
  857. /*---------------------------------------------------------------------------*/
  858. /*    Method 0: no compression                         */
  859. /*---------------------------------------------------------------------------*/
  860. static void dd_nocomp(obytes, data)
  861. unsigned char *data;
  862. unsigned long obytes;
  863. {
  864.     copy(out_ptr, (char *)data, (int)obytes);
  865. }
  866.  
  867. /*---------------------------------------------------------------------------*/
  868. /*    Method 1: LZC compressed                         */
  869. /*---------------------------------------------------------------------------*/
  870. static void dd_lzc(ibytes, obytes, data, mb, chksum, ckinit)
  871. unsigned char *data;
  872. unsigned long ibytes, obytes, chksum, ckinit;
  873. int mb;
  874. {
  875.     int i;
  876.     char *out_buf;
  877.     unsigned long cks;
  878.  
  879.     out_buf = out_buffer;
  880.     core_compress((char *)data);
  881.     de_compress(ibytes, mb);
  882.     out_buffer = out_buf;
  883.     if(dd_xor != 0) {
  884.     for(i = 0; i < obytes; i++) {
  885.         *out_buf++ ^= dd_xor;
  886.     }
  887.     }
  888.     cks = dd_checksum(ckinit, out_buffer, obytes);
  889.     if(chksum != cks) {
  890.     (void)fprintf(stderr,
  891.         "Checksum error on fork: need 0x%04x, got 0x%04x\n",
  892.         (int)chksum, (int)cks);
  893. #ifdef SCAN
  894.     do_error("macunpack: Checksum error on fork");
  895. #endif /* SCAN */
  896.     exit(1);
  897.     }
  898. }
  899.  
  900. #ifdef UNTESTED
  901. /*---------------------------------------------------------------------------*/
  902. /*    Method 3: Run length encoding                         */
  903. /*---------------------------------------------------------------------------*/
  904. static void dd_rle(ibytes, data)
  905. unsigned char *data;
  906. unsigned long ibytes;
  907. {
  908.     int ch, lastch, n, i;
  909.  
  910.     while(ibytes != 0) {
  911.     ch = *data++;
  912.     ibytes--;
  913.     if(ch == ESC) {
  914.         n = *data++ - 1;
  915.         ibytes--;
  916.         if(n < 0) {
  917.         *out_ptr++ = ESC;
  918.         lastch = ESC;
  919.         } else {
  920.         for(i = 0; i < n; i++) {
  921.             *out_ptr++ = lastch;
  922.         }
  923.         }
  924.     } else {
  925.         *out_ptr++ = ch;
  926.         lastch = ch;
  927.     }
  928.     }
  929. }
  930.  
  931. #ifdef NOTIMPLEMENTED
  932. /*---------------------------------------------------------------------------*/
  933. /*    Method 4: Huffman encoding                         */
  934. /*---------------------------------------------------------------------------*/
  935. static void dd_huffman(ibytes, data)
  936. unsigned char *data;
  937. unsigned long ibytes;
  938. {
  939. }
  940. #endif /* NOTIMPLEMENTED */
  941.  
  942. /*---------------------------------------------------------------------------*/
  943. /*    Method 7: Slightly improved LZSS                     */
  944. /*---------------------------------------------------------------------------*/
  945. static void dd_lzss(data, chksum)
  946. unsigned char *data;
  947. unsigned long chksum;
  948. {
  949.     int i, LZptr, LZbptr, LZlength;
  950.     char *optr = out_ptr;
  951.     unsigned char cks;
  952.  
  953.     data += get4((char *)data + 6);
  954.     LZptr = 0;
  955.     while(1) {
  956.     if(dd_getbits(1) == 0) {
  957.         *out_ptr++ = dd_LZbuff[LZptr++] = dd_getbits(8);
  958.         LZptr &= 0x7ff;
  959.     } else {
  960.         if(dd_getbits(1) == 0) {
  961.         LZbptr = dd_getbits(11);
  962.         } else {
  963.         LZbptr = dd_getbits(7);
  964.         }
  965.         if(LZbptr == 0) {
  966.         break;
  967.         }
  968.         LZbptr = (LZptr - LZbptr) & 0x7ff;
  969.         LZlength = dd_getbits(2);
  970.         if(LZlength == 3) {
  971.         LZlength += dd_getbits(2);
  972.         if(LZlength == 6) {
  973.             do {
  974.             i = dd_getbits(4);
  975.             LZlength += i;
  976.             } while(i == 15);
  977.         }
  978.         }
  979.         LZlength += 2;
  980.         for(i = 0; i < LZlength; i++) {
  981.         *out_ptr++ = dd_LZbuff[LZptr++] = dd_LZbuff[LZbptr++];
  982.         LZptr &= 0x7ff;
  983.         LZbptr &= 0x7ff;
  984.         }
  985.     }
  986.     }
  987.     cks = dd_checkor(INIT_CRC, optr, (unsigned long)(out_ptr - optr));
  988.     if(chksum != cks) {
  989.     (void)fprintf(stderr,
  990.         "Checksum error on fork: need 0x%04x, got 0x%04x\n",
  991.         (int)chksum, (int)cks);
  992. #ifdef SCAN
  993.     do_error("macunpack: Checksum error on fork");
  994. #endif /* SCAN */
  995.     exit(1);
  996.     }
  997. }
  998.  
  999. static int dd_getbits(n)
  1000. int n;
  1001. {
  1002.     int r;
  1003.  
  1004.     while(dd_bitcount < n) {
  1005.     dd_bitbuf = (dd_bitbuf << 8) | (~(*dd_bitptr++) & BYTEMASK);
  1006.     dd_bitcount += 8;
  1007.     }
  1008.     dd_bitcount -= n;
  1009.     r = (dd_bitbuf >> dd_bitcount);
  1010.     dd_bitbuf ^= (r << dd_bitcount);
  1011.     return r;
  1012. }
  1013.  
  1014. #endif /* UNTESTED */
  1015.  
  1016. /*---------------------------------------------------------------------------*/
  1017. /*    Method 8: Compactor compatible compression                 */
  1018. /*---------------------------------------------------------------------------*/
  1019. static void dd_cpt_compat(ibytes, obytes, data, sub_method, chksum)
  1020. unsigned char *data;
  1021. unsigned long ibytes, obytes, chksum;
  1022. int sub_method;
  1023. {
  1024.     unsigned long cks;
  1025.     char *optr = out_buffer;
  1026.  
  1027.     cpt_wrfile1(data, ibytes, obytes, sub_method, (unsigned long)0x0fff0);
  1028.     cks = arc_updcrc(INIT_CRC, (unsigned char *)optr, (int)obytes);
  1029.     if(chksum != cks) {
  1030.     (void)fprintf(stderr,
  1031.         "Checksum error on fork: need 0x%04x, got 0x%04x\n",
  1032.         (int)chksum, (int)cks);
  1033. #ifdef SCAN
  1034.     do_error("macunpack: Checksum error on fork");
  1035. #endif /* SCAN */
  1036.     exit(1);
  1037.     }
  1038. }
  1039. #else /* DD */
  1040. int dd; /* keep lint and some compilers happy */
  1041. #endif /* DD */
  1042.  
  1043.