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 / zma.c < prev    next >
C/C++ Source or Header  |  1995-09-18  |  10KB  |  390 lines

  1. #include "macunpack.h"
  2. #ifdef ZMA
  3. #include "globals.h"
  4. #include "zma.h"
  5. #include "crc.h"
  6. #include "../fileio/machdr.h"
  7. #include "../fileio/wrfile.h"
  8. #include "../fileio/kind.h"
  9. #include "../util/masks.h"
  10. #include "../util/util.h"
  11.  
  12. extern char *malloc();
  13. extern char *realloc();
  14. extern void de_lzh();
  15.  
  16. /* We do allow for possible backpointing, so we allocate the archive in core */
  17. static char *zma_archive;
  18. static char *zma_current;
  19. static char *zma_filestart;
  20. static unsigned long zma_length;
  21. static long zma_archlength;
  22.  
  23. static int zma_filehdr();
  24. static void zma_folder();
  25. static void zma_mooz();
  26. static void zma_wrfile();
  27. static void zma_nocomp();
  28. static void zma_lzh();
  29.  
  30. void zma(start, length)
  31.     char *start;
  32.     unsigned long length;
  33. {
  34.     struct fileHdr filehdr;
  35.     int i, toread;
  36.  
  37.     if(length != 0) {
  38.     if(zma_archlength < length) {
  39.         if(zma_archlength == 0) {
  40.         zma_archive = malloc((unsigned)length);
  41.         } else {
  42.         zma_archive = realloc(zma_archive, (unsigned)length);
  43.         }
  44.         zma_archlength = length;
  45.         if(zma_archive == NULL) {
  46.         (void)fprintf(stderr, "Insufficient memory, aborting\n");
  47.         exit(1);
  48.         }
  49.     }
  50.     if(fread(zma_archive, 1, (int)length, infp) != length) {
  51.         (void)fprintf(stderr, "Can't read archive.\n");
  52. #ifdef SCAN
  53.         do_error("macunpack: Can't read archive");
  54. #endif /* SCAN */
  55.         exit(1);
  56.     }
  57.     zma_length = get4(zma_archive + ZMAHDRS + 1);
  58.     if(zma_length != length) {
  59.         (void)fprintf(stderr, "Archive length mismatch.\n");
  60. #ifdef SCAN
  61.         do_error("macunpack: Archive length mismatch");
  62. #endif /* SCAN */
  63.         exit(1);
  64.     }
  65.     } else {
  66.     zma_length =  get4(start + ZMAHDRS + 1);
  67.     if(zma_archlength < zma_length) {
  68.         if(zma_archlength == 0) {
  69.         zma_archive = malloc((unsigned)zma_length);
  70.         } else {
  71.         zma_archive = realloc(zma_archive, (unsigned)zma_length);
  72.         }
  73.         zma_archlength = zma_length;
  74.         if(zma_archive == NULL) {
  75.         (void)fprintf(stderr, "Insufficient memory, aborting\n");
  76.         exit(1);
  77.         }
  78.     }
  79.     if(zma_archive == NULL) {
  80.         (void)fprintf(stderr, "Insufficient memory, aborting\n");
  81.         exit(1);
  82.     }
  83.     for(i = 0; i <= ZMAHDRS2; i++) {
  84.         zma_archive[i] = start[i];
  85.     }
  86.     toread = zma_length - ZMAHDRS2 - 1;
  87.     if(fread(zma_archive + ZMAHDRS2 + 1, 1, toread, infp) != toread) {
  88.         (void)fprintf(stderr, "Can't read archive.\n");
  89. #ifdef SCAN
  90.         do_error("macunpack: Can't read archive");
  91. #endif /* SCAN */
  92.         exit(1);
  93.     }
  94.     }
  95.     /* Consistency checks */
  96.     if(zma_archive[0] != 0) {
  97.     (void)fprintf(stderr, "Not a \"Zoom\" archive after all, aborting\n");
  98.     exit(1);
  99.     }
  100.     if(strncmp(zma_archive + 1, ZMAHDR, ZMAHDRS)) {
  101.     (void)fprintf(stderr, "Not a \"Zoom\" archive after all, aborting\n");
  102.     exit(1);
  103.     }
  104.     zma_current = zma_archive + 8;
  105.     updcrc = arc_updcrc;
  106.     crcinit = arc_crcinit;
  107.     while(zma_current != zma_archive) {
  108.     if(zma_filehdr(&filehdr, 0) == -1) {
  109.         (void)fprintf(stderr, "Can't find file header./n");
  110. #ifdef SCAN
  111.         do_error("macunpack: Can't find file header");
  112. #endif /* SCAN */
  113.         exit(1);
  114.     }
  115.     zma_filestart = zma_current + filehdr.hlen;
  116.     if(filehdr.what == z_dir) {
  117.         zma_folder(filehdr);
  118.     } else {
  119.         zma_mooz(filehdr);
  120.     }
  121.     zma_current = zma_archive + filehdr.next;
  122.     }
  123. }
  124.  
  125. static int zma_filehdr(f, skip)
  126. struct fileHdr *f;
  127. int skip;
  128. {
  129.     register int i;
  130.     int n;
  131.     char ftype[5], fauth[5];
  132.  
  133.     if(zma_current - zma_archive + Z_HDRSIZE > zma_length) {
  134.     return -1;
  135.     }
  136.     for(i = 0; i < INFOBYTES; i++) {
  137.     info[i] = '\0';
  138.     }
  139.  
  140.     n = zma_current[Z_FNAME] & BYTEMASK;
  141.     if(n > F_NAMELEN) {
  142.     n = F_NAMELEN;
  143.     }
  144.     info[I_NAMEOFF] = n;
  145.     copy(info + I_NAMEOFF + 1, zma_current + Z_FNAME + 1, n);
  146.     transname(zma_current + Z_FNAME + 1, text, n);
  147.  
  148.     f->what = zma_current[Z_WHAT];
  149.     f->rsrcLength = get4(zma_current + Z_URLEN);
  150.     f->dataLength = get4(zma_current + Z_UDLEN);
  151.     f->compRLength = get4(zma_current + Z_CRLEN);
  152.     f->compDLength = get4(zma_current + Z_CDLEN);
  153.     f->rsrcCRC = get2(zma_current + Z_RCRC);
  154.     f->dataCRC = get2(zma_current + Z_DCRC);
  155.     f->hlen = zma_current[Z_HLEN];
  156.     f->next = get4(zma_current + Z_NEXT);
  157.     if(f->what == z_dir) { /* A hack */
  158.     f->conts = get4(zma_current + Z_AUTH);
  159.     }
  160.     /* Set rsrc fork sizes correctly */
  161.     f->rsrcLength -= f->dataLength;
  162.     f->compRLength -= f->compDLength;
  163.  
  164.     write_it = !skip;
  165.     if(f->what & 0x80) {
  166.     write_it = 0;
  167.     f->what = -f->what;
  168.     f->deleted = 1;
  169.     return 0;
  170.     }
  171.     f->deleted = 0;
  172.     if(list && !skip) {
  173.     do_indent(indent);
  174.     if(f->what == z_dir) {
  175.         (void)fprintf(stderr, "folder=\"%s\"", text);
  176.     } else {
  177.         transname(zma_current + Z_TYPE, ftype, 4);
  178.         transname(zma_current + Z_AUTH, fauth, 4);
  179.         (void)fprintf(stderr,
  180.             "name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld",
  181.             text, ftype, fauth,
  182.             (long)f->dataLength, (long)f->rsrcLength);
  183.     }
  184.     switch(f->what) {
  185.     case z_plug:
  186.         (void)fputc('\n', stderr);
  187.         (void)fprintf(stderr,
  188.             "\tFile uses custom processing, cannot handle.\n");
  189.         write_it = 0;
  190.         return 0;
  191.     case z_dir:
  192.     case z_file:
  193.     case z_plain:
  194.         break;
  195.     default:
  196.         (void)fputc('\n', stderr);
  197.         (void)fprintf(stderr,
  198.             "\tEh, do not understand this (%d); skipped.\n", f->what);
  199.         write_it = 0;
  200.         return 0;
  201.     }
  202.  
  203.     if(info_only) {
  204.         write_it = 0;
  205.     }
  206.     if(query) {
  207.         write_it = do_query();
  208.     } else {
  209.         (void)fputc('\n', stderr);
  210.     }
  211.     }
  212.  
  213.  
  214.     if(write_it) {
  215.     define_name(text);
  216.  
  217.     if(f->what != z_dir) {
  218.         copy(info + I_TYPEOFF, zma_current + Z_TYPE, 4);
  219.         copy(info + I_AUTHOFF, zma_current + Z_AUTH, 4);
  220.         copy(info + I_FLAGOFF, zma_current + Z_FLAGS, 2);
  221.         copy(info + I_DLENOFF, zma_current + Z_UDLEN, 4);
  222.         put4(zma_current + Z_URLEN, f->rsrcLength);
  223.         copy(info + I_RLENOFF, zma_current + Z_URLEN, 4);
  224.         copy(info + I_CTIMOFF, zma_current + Z_MDATE, 4);
  225.         copy(info + I_MTIMOFF, zma_current + Z_MDATE, 4);
  226.     }
  227.     }
  228.     return 1;
  229. }
  230.  
  231. static void zma_folder(fhdr)
  232. struct fileHdr fhdr;
  233. {
  234.     int i;
  235.     char loc_name[64];
  236.     struct fileHdr filehdr;
  237.  
  238.     for(i = 0; i < 64; i++) {
  239.     loc_name[i] = text[i];
  240.     }
  241.     zma_current = zma_archive + fhdr.conts;
  242.     if(write_it || info_only) {
  243.     if(write_it) {
  244.         do_mkdir(text, info);
  245.     }
  246.     indent++;
  247.     while(zma_current != zma_archive) {
  248.         if(zma_filehdr(&filehdr, 0) == -1) {
  249.         (void)fprintf(stderr, "Can't find file header.\n");
  250. #ifdef SCAN
  251.         do_error("macunpack: Can't find file header");
  252. #endif /* SCAN */
  253.         exit(1);
  254.         }
  255.         zma_filestart = zma_current + filehdr.hlen;
  256.         if(filehdr.what == z_dir) {
  257.         zma_folder(filehdr);
  258.         } else {
  259.         zma_mooz(filehdr);
  260.         }
  261.         zma_current = zma_archive + filehdr.next;
  262.     }
  263.     if(write_it) {
  264.         enddir();
  265.     }
  266.     indent--;
  267.     if(list) {
  268.         do_indent(indent);
  269.         (void)fprintf(stderr, "leaving folder \"%s\"\n", loc_name);
  270.     }
  271.     }
  272. }
  273.  
  274. static void zma_mooz(filehdr)
  275. struct fileHdr filehdr;
  276. {
  277.     unsigned long crc;
  278.  
  279.     if(write_it) {
  280.     start_info(info, filehdr.rsrcLength, filehdr.dataLength);
  281.     }
  282.     if(verbose) {
  283.     (void)fprintf(stderr, "\tData: ");
  284.     }
  285.     if(write_it) {
  286.     start_data();
  287.     }
  288.     zma_wrfile(filehdr.compDLength, filehdr.dataLength, filehdr.what);
  289.     if(write_it) {
  290.     crc = (*updcrc)(INIT_CRC, out_buffer, filehdr.dataLength);
  291.     if(filehdr.dataCRC != crc) {
  292.         (void)fprintf(stderr,
  293.         "CRC error on data fork: need 0x%04x, got 0x%04x\n",
  294.         (int)filehdr.dataCRC, (int)crc);
  295. #ifdef SCAN
  296.         do_error("macunpack: CRC error on data fork");
  297. #endif /* SCAN */
  298.         exit(1);
  299.     }
  300.     }
  301.     if(verbose) {
  302.     (void)fprintf(stderr, ", Rsrc: ");
  303.     }
  304.     if(write_it) {
  305.     start_rsrc();
  306.     }
  307.     zma_wrfile(filehdr.compRLength, filehdr.rsrcLength, filehdr.what);
  308.     if(write_it) {
  309.     crc = (*updcrc)(INIT_CRC, out_buffer, filehdr.rsrcLength);
  310.     if(filehdr.rsrcCRC != crc) {
  311.         (void)fprintf(stderr,
  312.         "CRC error on resource fork: need 0x%04x, got 0x%04x\n",
  313.         (int)filehdr.rsrcCRC, (int)crc);
  314. #ifdef SCAN
  315.         do_error("macunpack: CRC error on resource fork");
  316. #endif /* SCAN */
  317.         exit(1);
  318.     }
  319.     end_file();
  320.     }
  321.     if(verbose) {
  322.     (void)fprintf(stderr, ".\n");
  323.     }
  324. }
  325.  
  326. static void zma_wrfile(ibytes, obytes, type)
  327. unsigned long ibytes, obytes;
  328. char type;
  329. {
  330.     if(ibytes == 0) {
  331.     if(verbose) {
  332.         (void)fprintf(stderr, "empty");
  333.     }
  334.     return;
  335.     }
  336.     switch(type) {
  337.     case z_plain:        /* no compression */
  338.     if(verbose) {
  339.         (void)fprintf(stderr, "No compression");
  340.     }
  341.     if(write_it) {
  342.         zma_nocomp(ibytes);
  343.     }
  344.     break;
  345.     case z_file:        /* lzh compression */
  346.     if(verbose) {
  347.         (void)fprintf(stderr,
  348.             "LZH compressed (%4.1f%%)", 100.0 * ibytes / obytes);
  349.     }
  350.     if(write_it) {
  351.         zma_lzh(ibytes);
  352.     }
  353.     break;
  354.     default:
  355.     (void)fprintf(stderr, "Unknown compression method %2x\n", type);
  356. #ifdef SCAN
  357.     do_idf("", UNKNOWN);
  358. #endif /* SCAN */
  359.     exit(1);
  360.     }
  361. }
  362.  
  363. /*---------------------------------------------------------------------------*/
  364. /*    No compression                                 */
  365. /*---------------------------------------------------------------------------*/
  366. static void zma_nocomp(ibytes)
  367. unsigned long ibytes;
  368. {
  369.     int n = ibytes;
  370.     char *ptr = out_buffer;
  371.  
  372.     while(n-- > 0) {
  373.     *ptr++ = *zma_filestart++;
  374.     }
  375. }
  376.  
  377. /*---------------------------------------------------------------------------*/
  378. /*    LZ compression plus Huffman encoding                     */
  379. /*---------------------------------------------------------------------------*/
  380. static void zma_lzh(ibytes)
  381. unsigned long ibytes;
  382. {
  383.     /* Controlled by ibutes only */
  384.     de_lzh((long)ibytes, (long)(-1), &zma_filestart, 13);
  385. }
  386. #else /* ZMA */
  387. int zma; /* keep lint and some compilers happy */
  388. #endif /* ZMA */
  389.  
  390.