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 / dia.c < prev    next >
C/C++ Source or Header  |  1995-09-18  |  13KB  |  559 lines

  1. #include "macunpack.h"
  2. #ifdef DIA
  3. #include "globals.h"
  4. #include "dia.h"
  5. #include "../util/curtime.h"
  6. #include "../util/masks.h"
  7. #include "../fileio/machdr.h"
  8. #include "../fileio/wrfile.h"
  9. #include "../fileio/kind.h"
  10. #include "../util/util.h"
  11.  
  12. extern char *malloc();
  13. extern char *realloc();
  14.  
  15. static unsigned char *dia_archive;
  16. static int dia_archive_size;
  17. static int dia_max_archive_size;
  18. static int dia_finfo;
  19. static int dia_method;
  20. static unsigned char *dia_archive_ptr;
  21. static unsigned char *dia_header_ptr;
  22. static unsigned char *dia_header_last;
  23. static int dia_forklength;
  24. static int dia_cforklength;
  25. static unsigned char dia_bitbuf[BCHUNKSIZE];
  26. static int dia_LZtab[BCHUNKSIZE];
  27. static unsigned char *dia_bit_base;
  28. static int dia_imask;
  29.  
  30. static void dia_folder();
  31. static void dia_file();
  32. static void dia_getlength();
  33. static void dia_skipfork();
  34. static void dia_getfork();
  35. static void dia_getblock();
  36. static int dia_decode();
  37. static int dia_prevbit();
  38.  
  39. void dia(bin_hdr)
  40. unsigned char *bin_hdr;
  41. {
  42.     int i, folder, nlength;
  43.     unsigned char hdr;
  44.     unsigned char *header;
  45.  
  46.     dir_skip = 0;
  47.     for(i = 0; i < INFOBYTES; i++) {
  48.     info[i] = 0;
  49.     }
  50.     if(in_data_size > dia_max_archive_size) {
  51.     if(dia_archive == NULL) {
  52.         dia_archive = (unsigned char *)malloc((unsigned)in_data_size);
  53.     } else {
  54.         dia_archive = (unsigned char *)realloc((char *)dia_archive,
  55.                            (unsigned)in_data_size);
  56.     }
  57.     if(dia_archive == 0) {
  58.         (void)fprintf(stderr, "Insufficient memory.\n");
  59.         exit(1);
  60.     }
  61.     dia_max_archive_size = in_data_size;
  62.     }
  63.     dia_archive_size = in_data_size;
  64.     if(fread((char *)dia_archive, 1, in_data_size, infp) != in_data_size) {
  65.     (void)fprintf(stderr, "Can't read archive.\n");
  66. #ifdef SCAN
  67.     do_error("macunpack: Can't read archive");
  68. #endif /* SCAN */
  69.     exit(1);
  70.     }
  71.     nlength = bin_hdr[I_NAMEOFF] & BYTEMASK;
  72.     if(!strncmp((char *)bin_hdr + I_NAMEOFF + nlength - 1, " \272", 2)) {
  73.     nlength -= 2;
  74.     }
  75.     info[I_NAMEOFF] = nlength;
  76.     for(i = 1; i <= nlength; i++) {
  77.     info[I_NAMEOFF + i] = bin_hdr[I_NAMEOFF + i];
  78.     }
  79.     hdr = *dia_archive;
  80.     folder = hdr & IS_FOLDER;
  81.     dia_finfo = hdr & F_INFO;
  82.     if(hdr & VOLUME) {
  83.     (void)fprintf(stderr, "Multi-segment archives not implemented.\n");
  84. #ifdef SCAN
  85.     do_error("macunpack: Multi-segment archive");
  86. #endif /* SCAN */
  87.     exit(1);
  88.     }
  89.     if(hdr & CRYPTED) {
  90.     (void)fprintf(stderr, "Encrypted archives not implemented.\n");
  91. #ifdef SCAN
  92.     do_idf("", PROTECTED);
  93. #endif /* SCAN */
  94.     exit(1);
  95.     }
  96.     i = (hdr & N_BLOCKS) + 1;
  97.     header = (unsigned char *)malloc((unsigned)(i * CHUNKSIZE));
  98.     dia_archive_ptr = dia_archive + 1;
  99.     dia_header_last = header;
  100.     dia_method = 0;
  101.     while(i-- > 0) {
  102.     dia_getblock(&dia_archive_ptr, &dia_header_last);
  103.     }
  104.     dia_header_ptr = header;
  105.     if(folder) {
  106.     dia_folder((unsigned char *)NULL);
  107.     } else {
  108.     dia_file(*dia_header_ptr++, (unsigned char *)NULL);
  109.     }
  110.     free((char *)header);
  111. }
  112.  
  113. static void dia_folder(name)
  114. unsigned char *name;
  115. {
  116.     unsigned char lname[32];
  117.     int i, length, doit;
  118.     unsigned char indicator, *old_ptr;
  119.  
  120.     if(name != NULL) {
  121.     for(i = 0; i < INFOBYTES; i++) {
  122.         info[i] = 0;
  123.     }
  124.     length = *name++ & REMAINS;
  125.     info[I_NAMEOFF] = length;
  126.     for(i = 1; i <= length; i++) {
  127.         info[I_NAMEOFF + i] = *name++;
  128.     }
  129.     } else {
  130.     length = info[I_NAMEOFF];
  131.     }
  132.     if(dia_finfo) {
  133.     dia_header_ptr += 20;
  134.     }
  135.     if(!dir_skip) {
  136.     doit = 1;
  137.     if(list) {
  138.         transname(info + I_NAMEOFF + 1, (char *)lname, length);
  139.         do_indent(indent);
  140.         (void)fprintf(stderr, "folder=\"%s\"", lname);
  141.         if(query) {
  142.         doit = do_query();
  143.         } else {
  144.         (void)fputc('\n', stderr);
  145.         }
  146.         if(doit) {
  147.         indent++;
  148.         } else {
  149.         dir_skip = 1;
  150.         }
  151.     }
  152.     if(doit && !info_only) {
  153.         do_mkdir((char *)lname, info);
  154.     }
  155.     } else {
  156.     dir_skip++;
  157.     }
  158.     while(dia_header_ptr < dia_header_last) {
  159.     indicator = *dia_header_ptr;
  160.     if(indicator & LEAVE_FOLDER) {
  161.         *dia_header_ptr = indicator & ~LEAVE_FOLDER;
  162.         break;
  163.     } else if(indicator & ONLY_FOLDER) {
  164.         if(indicator == ONLY_FOLDER) {
  165.         dia_header_ptr++;
  166.         } else {
  167.         *dia_header_ptr -= 1;
  168.         }
  169.         break;
  170.     } else if(indicator & FOLDER) {
  171.         old_ptr = dia_header_ptr;
  172.         dia_header_ptr += (indicator & REMAINS) + 1;
  173.         dia_folder(old_ptr);
  174.     } else {
  175.         dia_header_ptr++;
  176.         old_ptr = dia_header_ptr;
  177.         dia_header_ptr += (*old_ptr & REMAINS) + 1;
  178.         dia_file(indicator, old_ptr);
  179.     }
  180.     }
  181.     if(!dir_skip) {
  182.     if(doit) {
  183.         indent--;
  184.         if(!info_only) {
  185.         enddir();
  186.         }
  187.         do_indent(indent);
  188.         (void)fprintf(stderr, "leaving folder \"%s\"\n", lname);
  189.     }
  190.     } else {
  191.     dir_skip--;
  192.     }
  193. }
  194.  
  195. static void dia_file(indicator, name)
  196. unsigned char indicator, *name;
  197. {
  198.     unsigned char lname[32];
  199.     int i, length, doit;
  200.     int n_data, n_rsrc;
  201.     unsigned char *old_archive_ptr;
  202.     char ftype[5], fauth[5];
  203.     int dataLength, rsrcLength;
  204.     int cdataLength, crsrcLength;
  205.     int dataMethod, rsrcMethod;
  206.     unsigned long curtime;
  207.  
  208.     if(name != NULL) {
  209.     for(i = 0; i < INFOBYTES; i++) {
  210.         info[i] = 0;
  211.     }
  212.     length = *name++ & REMAINS;
  213.     info[I_NAMEOFF] = length;
  214.     for(i = 1; i <= length; i++) {
  215.         info[I_NAMEOFF + i] = *name++;
  216.     }
  217.     } else {
  218.     length = info[I_NAMEOFF];
  219.     }
  220.     for(i = 0; i < 4; i++) {
  221.     info[I_TYPEOFF + i] = *dia_header_ptr++;
  222.     }
  223.     for(i = 0; i < 4; i++) {
  224.     info[I_AUTHOFF + i] = *dia_header_ptr++;
  225.     }
  226.     if(indicator & DATE_PRESENT) {
  227.     for(i = 0; i < 4; i++) {
  228.         info[I_CTIMOFF + i] = *dia_header_ptr++;
  229.     }
  230.     for(i = 0; i < 4; i++) {
  231.         info[I_MTIMOFF + i] = *dia_header_ptr++;
  232.     }
  233.     } else {
  234.     curtime = (unsigned long)time((time_t *)0) + TIMEDIFF;
  235.     put4(info + I_CTIMOFF, curtime);
  236.     put4(info + I_MTIMOFF, curtime);
  237.     }
  238.     if(dia_finfo) {
  239.     for(i = 0; i < 6; i++) {
  240.         info[I_FLAGOFF + i] = *dia_header_ptr++;
  241.     }
  242.     }
  243.     n_data = 0;
  244.     if(indicator & HAS_DATA) {
  245.     if(indicator & SHORT_DATA) {
  246.         n_data = 1;
  247.     } else {
  248.         n_data = *dia_header_ptr++ + 1;
  249.     }
  250.     }
  251.     n_rsrc = 0;
  252.     if(indicator & HAS_RSRC) {
  253.     if(indicator & SHORT_RSRC) {
  254.         n_rsrc = 1;
  255.     } else {
  256.         n_rsrc = *dia_header_ptr++ + 1;
  257.     }
  258.     }
  259.     if(!dir_skip) {
  260.     old_archive_ptr = dia_archive_ptr;
  261.     dia_getlength(n_data);
  262.     dataLength = dia_forklength;
  263.     cdataLength = dia_cforklength;
  264.     dataMethod = dia_method;
  265.     dia_getlength(n_rsrc);
  266.     rsrcLength = dia_forklength;
  267.     crsrcLength = dia_cforklength;
  268.     rsrcMethod = dia_method;
  269.     dia_archive_ptr = old_archive_ptr;
  270.     put4(info + I_DLENOFF, (unsigned long)dataLength);
  271.     put4(info + I_RLENOFF, (unsigned long)rsrcLength);
  272.     if(list) {
  273.         transname(info + I_NAMEOFF + 1, (char *)lname, length);
  274.         do_indent(indent);
  275.         transname(info + I_TYPEOFF, ftype, 4);
  276.         transname(info + I_AUTHOFF, fauth, 4);
  277.         (void)fprintf(stderr,
  278.             "name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld",
  279.             lname, ftype, fauth, (long)dataLength, (long)rsrcLength);
  280.         if(info_only) {
  281.         doit = 0;
  282.         } else {
  283.         doit = 1;
  284.         }
  285.         if(query) {
  286.         doit = do_query();
  287.         } else {
  288.         (void)fputc('\n', stderr);
  289.         }
  290.     } else {
  291.         doit = 1;
  292.     }
  293.     } else {
  294.     dia_skipfork(n_data);
  295.     dia_skipfork(n_rsrc);
  296.     return;
  297.     }
  298.     if(doit) {
  299.     define_name((char *)lname);
  300.     start_info(info, (unsigned long)rsrcLength, (unsigned long)dataLength);
  301.     }
  302.     if(verbose) {
  303.     (void)fprintf(stderr, "\tData: ");
  304.     if(dataLength == 0) {
  305.         (void)fprintf(stderr, "empty");
  306.     } else if(dataMethod == NOCOMP) {
  307.         (void)fprintf(stderr, "No compression");
  308.     } else {
  309.         if(dataMethod != COMP) {
  310.         (void)fprintf(stderr, "Partial ");
  311.         }
  312.         (void)fprintf(stderr, "LZFK compressed (%4.1f%%)",
  313.         100.0 * cdataLength / dataLength);
  314.     }
  315.     }
  316.     if(doit) {
  317.     start_data();
  318.     dia_getfork(n_data);
  319.     } else {
  320.     dia_skipfork(n_data);
  321.     }
  322.     if(verbose) {
  323.     (void)fprintf(stderr, ", Rsrc: ");
  324.     if(rsrcLength == 0) {
  325.         (void)fprintf(stderr, "empty");
  326.     } else if(rsrcMethod == NOCOMP) {
  327.         (void)fprintf(stderr, "No compression");
  328.     } else {
  329.         if(rsrcMethod != COMP) {
  330.         (void)fprintf(stderr, "Partial ");
  331.         }
  332.         (void)fprintf(stderr, "LZFK compressed (%4.1f%%)",
  333.         100.0 * crsrcLength / rsrcLength);
  334.     }
  335.     }
  336.     if(doit) {
  337.     start_rsrc();
  338.     dia_getfork(n_rsrc);
  339.     } else {
  340.     dia_skipfork(n_rsrc);
  341.     }
  342.     if(verbose) {
  343.     (void)fprintf(stderr, ".\n");
  344.     }
  345.     if(doit) {
  346.     end_file();
  347.     }
  348. }
  349.  
  350. static void dia_getlength(nblocks)
  351. int nblocks;
  352. {
  353.     int length;
  354.     unsigned char *arch_ptr, *block_ptr;
  355.     unsigned char block[CHUNKSIZE];
  356.  
  357.     dia_method = 0;
  358.     dia_forklength = 0;
  359.     dia_cforklength = 0;
  360.     while(nblocks > 1) {
  361.     nblocks--;
  362.     length = get2((char *)dia_archive_ptr);
  363.     if(length >= 0x8000) {
  364.         length = 0x10000 - length;
  365.         dia_method |= NOCOMP;
  366.     } else {
  367.         dia_method |= COMP;
  368.     }
  369.     dia_forklength += CHUNKSIZE;
  370.     dia_cforklength += length + 2;
  371.     dia_archive_ptr += length + 2;
  372.     }
  373.     if(nblocks == 1) {
  374.     arch_ptr = dia_archive_ptr;
  375.     block_ptr = block;
  376.     dia_getblock(&arch_ptr, &block_ptr);
  377.     dia_forklength += block_ptr - block;
  378.     dia_cforklength += arch_ptr - dia_archive_ptr;
  379.     dia_archive_ptr = arch_ptr;
  380.     }
  381. }
  382.  
  383. static void dia_skipfork(nblocks)
  384. int nblocks;
  385. {
  386.     int length;
  387.  
  388.     while(nblocks-- > 0) {
  389.     length = get2((char *)dia_archive_ptr);
  390.     if(length >= 0x8000) {
  391.         length = 0x10000 - length;
  392.     }
  393.     dia_archive_ptr += length + 2;
  394.     }
  395. }
  396.  
  397. static void dia_getfork(nblocks)
  398. int nblocks;
  399. {
  400.     while(nblocks-- > 0) {
  401.     dia_getblock(&dia_archive_ptr, (unsigned char **)&out_ptr);
  402.     }
  403. }
  404.  
  405. static void dia_getblock(archive_ptr, block_ptr)
  406. unsigned char **archive_ptr, **block_ptr;
  407. {
  408.     int length, i;
  409.     unsigned char *arch_ptr, *bl_ptr;
  410.  
  411.     arch_ptr = *archive_ptr;
  412.     bl_ptr = *block_ptr;
  413.     length = get2((char *)arch_ptr);
  414.     arch_ptr += 2;
  415.     if(length >= 0x8000) {
  416.     length = 0x10000 - length;
  417.     for(i = 0; i < length; i++) {
  418.         *bl_ptr++ = *arch_ptr++;
  419.     }
  420.     *block_ptr += length;
  421.     dia_method |= NOCOMP;
  422.     } else {
  423.     *block_ptr += dia_decode(arch_ptr, bl_ptr, length);
  424.     dia_method |= COMP;
  425.     }
  426.     *archive_ptr += length + 2;
  427. }
  428.  
  429. static int dia_decode(ibuff, obuff, in_length)
  430. unsigned char *ibuff, *obuff; int in_length;
  431. {
  432.     int nbits, set_zero, i, j;
  433.     unsigned char *bitbuf_ptr;
  434.     int count[4];
  435.     int *LZtab_ptr;
  436.     unsigned char *out_ptr, *buf_ptr, *in_ptr;
  437.     int omask;
  438.     int LZcount;
  439.     int *length_ptr, *nchars_ptr;
  440.     int *offsn_ptr, length, nchars, offset;
  441.     int *offs_ptr[4];
  442.     int nwords;
  443.  
  444.     in_ptr = ibuff + in_length;
  445.     nbits = *--in_ptr;
  446.     nbits |= (*--in_ptr << 8);
  447.     if(nbits == WORDMASK) {
  448.     nbits = *--in_ptr;
  449.     nbits |= (*--in_ptr << 8);
  450.     nbits = nbits + WORDMASK;
  451.     }
  452.     bitbuf_ptr = dia_bitbuf + BCHUNKSIZE;
  453.     *--bitbuf_ptr = *--in_ptr;
  454.     set_zero = 0;
  455.     dia_bit_base = bitbuf_ptr;
  456.     dia_imask = 1 << (7 - (nbits & 7));
  457.     if(dia_prevbit()) {
  458.     set_zero = 1;
  459.     }
  460.     for(i = 0; i < nbits; i++) {
  461.     if(set_zero) {
  462.         *--bitbuf_ptr = 0;
  463.     } else {
  464.         *--bitbuf_ptr = *--in_ptr;
  465.     }
  466.     if(dia_prevbit()) {
  467.         set_zero = !set_zero;
  468.     }
  469.     }
  470.     /* Now we have the bits in longitudal order; reorder them */
  471.     nwords = ((dia_bit_base - bitbuf_ptr) >> 1);
  472.     for(i = 0; i < nwords; i++) {
  473.     dia_LZtab[i] = 0;
  474.     }
  475.     omask = 1;
  476.     for(i = 0; i < 16; i++) {
  477.     j = nwords;
  478.     LZtab_ptr = dia_LZtab + nwords;
  479.     while(j-- > 0) {
  480.         LZtab_ptr--;
  481.         if(dia_prevbit()) {
  482.         *LZtab_ptr |= omask;
  483.         }
  484.     }
  485.     omask <<= 1;
  486.     }
  487.     LZcount = nwords / 3;
  488.     /*  At this point we have in LZtab LZcount triples.  Each triple consists
  489.     of the following parts:
  490.         nchars:    the number of characters to take from input
  491.         length:    the number of characters - 1 to copy from output
  492.         offset:    the offset in the output buffer
  493.     The ordering is as follows:
  494.     1.    lengths
  495.     2.    nchars
  496.     3.    offsets for length 0
  497.     4.    offsets for length 1
  498.     5.    offsets for length 2
  499.     6.    offsets for length 3
  500.     7.    offsets for other lengths
  501.     */
  502.     /*    Now first count the occurences of lengths 0 to 3 */
  503.     count[0] = 0;
  504.     count[1] = 0;
  505.     count[2] = 0;
  506.     count[3] = 0;
  507.     for(i = 0; i < LZcount; i++) {
  508.     if((j = dia_LZtab[i]) < 4) {
  509.         count[j]++;
  510.     }
  511.     }
  512.     length_ptr = dia_LZtab;
  513.     nchars_ptr = dia_LZtab + LZcount;
  514.     offs_ptr[0] = nchars_ptr + LZcount;
  515.     offs_ptr[1] = offs_ptr[0] + count[0];
  516.     offs_ptr[2] = offs_ptr[1] + count[1];
  517.     offs_ptr[3] = offs_ptr[2] + count[2];
  518.     offsn_ptr = offs_ptr[3] + count[3];
  519.     out_ptr = obuff;
  520.     for(i = 0; i < LZcount; i++) {
  521.     length = *length_ptr++;
  522.     nchars = *nchars_ptr++;
  523.     if(length < 4) {
  524.         offset = *offs_ptr[length]++;
  525.     } else {
  526.         offset = *offsn_ptr++;
  527.     }
  528.     while(nchars-- > 0) {
  529.         *out_ptr++ = *ibuff++;
  530.     }
  531.     buf_ptr = out_ptr - length - offset - 1;
  532.     while(length-- >= 0) {
  533.         *out_ptr++ = *buf_ptr++;
  534.     }
  535.     }
  536.     i = in_ptr - ibuff;
  537.     while(i-- > 0) {
  538.     *out_ptr++ = *ibuff++;
  539.     }
  540.     return out_ptr - obuff;
  541. }
  542.  
  543. static int dia_prevbit()
  544. {
  545.     int c;
  546.  
  547.     if(dia_imask == 0x100) {
  548.     dia_bit_base--;
  549.     dia_imask = 1;
  550.     }
  551.     c = *dia_bit_base & dia_imask;
  552.     dia_imask <<= 1;
  553.     return c;
  554. }
  555. #else /* DIA */
  556. int dia; /* keep lint and some compilers happy */
  557. #endif /* DIA */
  558.  
  559.