home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_progs / fileutil / scan.lha / src / lharc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-21  |  13.4 KB  |  532 lines

  1. /*              LHarc Dearchiver Main                                 */
  2.  
  3. /* Opens an archive and tests each internal file to see if it matches */
  4. /* a specified wildcard pattern. If it does, it dearchives 1 buffers  */
  5. /* worth on each call. It does this for every file in the archive.    */
  6. /* 0 <= x != buffer size -> end of file                               */
  7. /* 0 <= x <= buffer size -> x = # of bytes read into buf              */
  8. /*      x >  buffer size -> # of bytes read into buffer = buf size    */
  9. /* 0 >  x                -> end of archive                            */
  10. /* if no files match pattern, 0 is returned. Next call -1 is returned */
  11.  
  12. #include "lharc.h"
  13.  
  14. int     NotInterruptedCall = 1;
  15. int     ForceReturn;
  16. extern  long WinSiz, BCount, TotRd;
  17. char    expanded_archive_name[FILENAME_LENGTH];
  18. char    *writting_filename;
  19. char    *archive_name;
  20. extern  char *WildLZH;
  21. extern  long BufrCnt;
  22. long    TotSiz;
  23. long    cursize;
  24. long    HWinSiz;
  25. char    *BfrPtr;
  26. LzHeader hdr;
  27. long    pos;
  28. FILE    *afp=NULL;
  29.  
  30. long
  31. FillBufWithLZH( reading_filename, buffer )
  32.   char    *reading_filename;
  33.   char    *buffer;
  34. {
  35.   BfrPtr = buffer;
  36.   HWinSiz = WinSiz >> 1;
  37.   archive_name = reading_filename;
  38.   ForceReturn = 0;
  39.   if( NotInterruptedCall ) {
  40.      if( afp == NULL ) {
  41.         /* open archive file */
  42.         if ((afp = open_old_archive ()) == NULL) fatal_error (archive_name);
  43.      }
  44.      if( get_header (afp, &hdr)) {
  45.         pos = ftell( afp);
  46.         BCount = HWinSiz;           /* lh5 only */
  47.         TotRd = hdr.packed_size;    /* lh5 only */
  48.         cursize = hdr.original_size; /* lh5 only */
  49.         TotSiz = 0;
  50.         BufrCnt = 0;
  51.         extract_one( afp, &hdr);
  52.      }
  53.      else {
  54.         /* close archive file */
  55.         fclose( afp);
  56.         afp = NULL;
  57.         return(-1);
  58.      }
  59.   }
  60.   else {
  61.      extract_one (afp, &hdr);
  62.   }
  63.  
  64.   if( ForceReturn ) {
  65.      NotInterruptedCall = 0;
  66.   }
  67.   else {
  68.      fseek( afp, pos + hdr.packed_size, SEEK_SET);
  69.      if( TotSiz == WinSiz) TotSiz++; /* signify endof int file if nonobvious */
  70.   }
  71.  
  72.   return(TotSiz);
  73. }
  74.  
  75. static
  76. message_1 (title, subject, name)
  77.      char *title, *subject, *name;
  78. {
  79.   fprintf (stderr, "LHarc: %s%s ", title, subject);
  80.   fflush (stderr);
  81.  
  82.   if (errno == 0)
  83.     fprintf (stderr, "%s\n", name);
  84.   else
  85.     perror (name);
  86. }
  87.  
  88. void
  89. message (subject, name)
  90.      char *subject, *name;
  91. {
  92.   message_1 ("", subject, name);
  93. }
  94.  
  95. void
  96. warning (subject, name)
  97.      char *subject, *name;
  98. {
  99.   message_1 ("Warning: ", subject, name);
  100. }
  101.  
  102. void
  103. error (subject, msg)
  104.      char *subject, *msg;
  105. {
  106.   message_1 ("Error: ", subject, msg);
  107. }
  108.  
  109. void
  110. fatal_error (msg)
  111.      char *msg;
  112. {
  113.   message_1 ("Fatal error:", "", msg);
  114.   ErrP("terminating...");
  115. }
  116.  
  117. read_error ()
  118. {
  119.   fatal_error (archive_name);
  120. }
  121.  
  122. /*----------------------------------------------------------------------*/
  123. /*                                                                      */
  124. /*----------------------------------------------------------------------*/
  125.  
  126. static boolean
  127. expand_archive_name (dst, src)
  128.      char *dst, *src;
  129. {
  130.   register char *p, *dot;
  131.  
  132.   strcpy (dst, src);
  133.  
  134.   for (p = dst, dot = (char*)0; ; p ++, dot = (char*)0)
  135.     {
  136.       while (*p == '.')         /* skip leading dots of base name */
  137.         p ++;
  138.       for (; *p != '/'; p ++)
  139.         {
  140.           if (*p == '.')
  141.             dot = p;
  142.           else if (*p == '\0')
  143.             goto _Done;
  144.         }
  145.     }
  146.   _Done:
  147.  
  148.   if (dot)
  149.     p = dot;
  150.  
  151.   strcpy (p, ARCHIVENAME_EXTENTION); /* ".lzh" */
  152.   return (strcmp (dst, src) != 0);
  153. }
  154.  
  155. /*----------------------------------------------------------------------*/
  156. /*                                                                      */
  157. /*----------------------------------------------------------------------*/
  158.  
  159. static int
  160. calc_sum (p, len)
  161.      register char *p;
  162.      register int len;
  163. {
  164.   register int sum;
  165.  
  166.   for (sum = 0; len; len --)
  167.     sum += *p++;
  168.  
  169.   return sum & 0xff;
  170. }
  171.  
  172. static char *get_ptr;
  173. #define setup_get(PTR)          (get_ptr = (PTR))
  174. #define get_byte()              (*get_ptr++ & 0xff)
  175. #define put_ptr                 get_ptr
  176. #define setup_put(PTR)          (put_ptr = (PTR))
  177.  
  178. static unsigned short
  179. get_word ()
  180. {
  181.   int b0, b1;
  182.  
  183.   b0 = get_byte ();
  184.   b1 = get_byte ();
  185.   return (b1 << 8) + b0;
  186. }
  187.  
  188. static long
  189. get_longword ()
  190. {
  191.   long b0, b1, b2, b3;
  192.  
  193.   b0 = get_byte ();
  194.   b1 = get_byte ();
  195.   b2 = get_byte ();
  196.   b3 = get_byte ();
  197.   return (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
  198. }
  199.  
  200. static
  201. msdos_to_unix_filename (name, len)
  202.      register char *name;
  203.      register int len;
  204. {
  205.   register int i;
  206.  
  207. #ifdef MULTIBYTE_CHAR
  208.   for (i = 0; i < len; i ++)
  209.     {
  210.       if (MULTIBYTE_FIRST_P (name[i]) &&
  211.           MULTIBYTE_SECOND_P (name[i+1]))
  212.         i ++;
  213.       else if (name[i] == '\\')
  214.         name[i] = '/';
  215.       else if (isupper (name[i]))
  216.         name[i] = tolower (name[i]);
  217.     }
  218. #else
  219.   for (i = 0; i < len; i ++)
  220.     {
  221.       if (name[i] == '\\')
  222.         name[i] = '/';
  223.       else if (isupper (name[i]))
  224.         name[i] = tolower (name[i]);
  225.     }
  226. #endif
  227. }
  228.  
  229. static
  230. generic_to_unix_filename (name, len)
  231.      register char *name;
  232.      register int len;
  233. {
  234.   register int i;
  235.   boolean lower_case_used = FALSE;
  236.  
  237. #ifdef MULTIBYTE_CHAR
  238.   for (i = 0; i < len; i ++)
  239.     {
  240.       if (MULTIBYTE_FIRST_P (name[i]) &&
  241.           MULTIBYTE_SECOND_P (name[i+1]))
  242.         i ++;
  243.       else if (islower (name[i]))
  244.         {
  245.           lower_case_used = TRUE;
  246.           break;
  247.         }
  248.     }
  249.   for (i = 0; i < len; i ++)
  250.     {
  251.       if (MULTIBYTE_FIRST_P (name[i]) &&
  252.           MULTIBYTE_SECOND_P (name[i+1]))
  253.         i ++;
  254.       else if (name[i] == '\\')
  255.         name[i] = '/';
  256.       else if (!lower_case_used && isupper (name[i]))
  257.         name[i] = tolower (name[i]);
  258.     }
  259. #else
  260.   for (i = 0; i < len; i ++)
  261.     if (islower (name[i]))
  262.       {
  263.         lower_case_used = TRUE;
  264.         break;
  265.       }
  266.   for (i = 0; i < len; i ++)
  267.     {
  268.       if (name[i] == '\\')
  269.         name[i] = '/';
  270.       else if (!lower_case_used && isupper (name[i]))
  271.         name[i] = tolower (name[i]);
  272.     }
  273. #endif
  274. }
  275.  
  276. static
  277. macos_to_unix_filename (name, len)
  278.      register char *name;
  279.      register int len;
  280. {
  281.   register int i;
  282.  
  283.   for (i = 0; i < len; i ++)
  284.     {
  285.       if (name[i] == ':')
  286.         name[i] = '/';
  287.       else if (name[i] == '/')
  288.         name[i] = ':';
  289.     }
  290. }
  291.  
  292. /*----------------------------------------------------------------------*/
  293. /*                                                                      */
  294. /*      Generic stamp format:                                           */
  295. /*                                                                      */
  296. /*       31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16                */
  297. /*      |<-------- year ------->|<- month ->|<-- day -->|               */
  298. /*                                                                      */
  299. /*       15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0                */
  300. /*      |<--- hour --->|<---- minute --->|<- second*2 ->|               */
  301. /*                                                                      */
  302. /*----------------------------------------------------------------------*/
  303.  
  304.  
  305. static long
  306. gettz ()
  307. {
  308.    return(time((time_t *)NULL));
  309. }
  310.  
  311. static time_t
  312. generic_to_unix_stamp (t)
  313.      long t;
  314. {
  315.   int year, month, day, hour, min, sec;
  316.   long longtime;
  317.   static unsigned int dsboy[12] = { 0, 31, 59, 90, 120, 151,
  318.                                       181, 212, 243, 273, 304, 334};
  319.   unsigned int days;
  320.  
  321.   year  = ((int)(t >> 16+9) & 0x7f) + 1980;
  322.   month =  (int)(t >> 16+5) & 0x0f;     /* 1..12 means Jan..Dec */
  323.   day   =  (int)(t >> 16)   & 0x1f;     /* 1..31 means 1st,...31st */
  324.  
  325.   hour  =  ((int)t >> 11) & 0x1f;
  326.   min   =  ((int)t >> 5)  & 0x3f;
  327.   sec   = ((int)t         & 0x1f) * 2;
  328.  
  329.                                 /* Calculate days since 1970.01.01 */
  330.   days = (365 * (year - 1970) + /* days due to whole years */
  331.           (year - 1970 + 1) / 4 + /* days due to leap years */
  332.           dsboy[month-1] +      /* days since beginning of this year */
  333.           day-1);               /* days since beginning of month */
  334.  
  335.   if ((year % 4 == 0) &&
  336.       (year % 400 != 0) &&
  337.       (month >= 3))             /* if this is a leap year and month */
  338.     days ++;                    /* is March or later, add a day */
  339.  
  340.   /* Knowing the days, we can find seconds */
  341.   longtime = (((days * 24) + hour) * 60 + min) * 60 + sec;
  342.   longtime += gettz ();      /* adjust for timezone */
  343.  
  344.   /* special case:  if MSDOS format date and time were zero, then we set
  345.      time to be zero here too. */
  346.   if (t == 0)
  347.     longtime = 0;
  348.  
  349.   /* LONGTIME is now the time in seconds, since 1970/01/01 00:00:00.  */
  350.   return (time_t)longtime;
  351. }
  352.  
  353. /*----------------------------------------------------------------------*/
  354. /*                                                                      */
  355. /*----------------------------------------------------------------------*/
  356.  
  357. boolean
  358. get_header (fp, hdr)
  359.      FILE *fp;
  360.      register LzHeader *hdr;
  361. {
  362.   int header_size;
  363.   int name_length;
  364.   char data[LZHEADER_STRAGE];
  365.   int checksum;
  366.   int i;
  367.  
  368.   bzero (hdr, sizeof (LzHeader));
  369.  
  370.   if (((header_size = getc (fp)) == EOF) || (header_size == 0))
  371.     {
  372.       return FALSE;             /* finish */
  373.     }
  374.  
  375.   if (fread (data + I_HEADER_CHECKSUM,
  376.                   sizeof (char), header_size + 1, fp) < header_size + 1)
  377.     {
  378.       fatal_error ("Invalid header (LHarc file ?)");
  379.       return FALSE;             /* finish */
  380.     }
  381.  
  382.   setup_get (data + I_HEADER_CHECKSUM);
  383.   checksum = calc_sum (data + I_METHOD, header_size);
  384.   if (get_byte () != checksum)
  385.     warning ("Checksum error (LHarc file?)", "");
  386.  
  387.   hdr->header_size = header_size;
  388.   bcopy (data + I_METHOD, hdr->method, METHOD_TYPE_STRAGE);
  389. #ifdef OLD
  390.   if ((bcmp (hdr->method, LZHUFF1_METHOD, METHOD_TYPE_STRAGE) != 0) &&
  391.       (bcmp (hdr->method, LZHUFF0_METHOD, METHOD_TYPE_STRAGE) != 0) &&
  392.       (bcmp (hdr->method, LARC5_METHOD, METHOD_TYPE_STRAGE) != 0) &&
  393.       (bcmp (hdr->method, LARC4_METHOD, METHOD_TYPE_STRAGE) != 0))
  394.     {
  395.       warning ("Unknown method (LHarc file ?)", "");
  396.       return FALSE;             /* invalid method */
  397.     }
  398. #endif
  399.   setup_get (data + I_PACKED_SIZE);
  400.   hdr->packed_size      = get_longword ();
  401.   hdr->original_size    = get_longword ();
  402.   hdr->last_modified_stamp = get_longword ();
  403.   hdr->attribute        = get_word ();
  404.   name_length           = get_byte ();
  405.   for (i = 0; i < name_length; i ++)
  406.     hdr->name[i] =(char)get_byte ();
  407.   hdr->name[name_length] = '\0';
  408.  
  409.   /* defaults for other type */
  410.   hdr->unix_mode        = UNIX_FILE_REGULAR | UNIX_RW_RW_RW;
  411.   hdr->unix_gid         = 0;
  412.   hdr->unix_uid         = 0;
  413.  
  414.   if (header_size - name_length >= 24)
  415.     {                           /* EXTEND FORMAT */
  416.       hdr->crc                          = get_word ();
  417.       hdr->extend_type                  = get_byte ();
  418.       hdr->minor_version                = get_byte ();
  419.       hdr->has_crc = TRUE;
  420.     }
  421.   else if (header_size - name_length == 22)
  422.     {                           /* Generic with CRC */
  423.       hdr->crc                          = get_word ();
  424.       hdr->extend_type                  = EXTEND_GENERIC;
  425.       hdr->has_crc = TRUE;
  426.     }
  427.   else if (header_size - name_length == 20)
  428.     {                           /* Generic no CRC */
  429.       hdr->extend_type                  = EXTEND_GENERIC;
  430.       hdr->has_crc = FALSE;
  431.     }
  432.   else
  433.     {
  434.       warning ("Unknown header (LHarc file ?)", "");
  435.       return FALSE;
  436.     }
  437.  
  438.   switch (hdr->extend_type)
  439.     {
  440.     case EXTEND_MSDOS:
  441.       msdos_to_unix_filename (hdr->name, name_length);
  442.       hdr->unix_last_modified_stamp     =
  443.         generic_to_unix_stamp (hdr->last_modified_stamp);
  444.       break;
  445.  
  446.     case EXTEND_UNIX:
  447.       hdr->unix_last_modified_stamp     = (time_t)get_longword ();
  448.       hdr->unix_mode                    = get_word ();
  449.       hdr->unix_uid                     = get_word ();
  450.       hdr->unix_gid                     = get_word ();
  451.       break;
  452.  
  453.     case EXTEND_MACOS:
  454.       macos_to_unix_filename (hdr->name, name_length);
  455.       hdr->unix_last_modified_stamp     =
  456.         generic_to_unix_stamp (hdr->last_modified_stamp);
  457.       break;
  458.  
  459.     default:
  460.       generic_to_unix_filename (hdr->name, name_length);
  461.       hdr->unix_last_modified_stamp     =
  462.         generic_to_unix_stamp (hdr->last_modified_stamp);
  463.     }
  464.  
  465.   return TRUE;
  466. }
  467.  
  468. /*----------------------------------------------------------------------*/
  469. /*                                                                      */
  470. /*----------------------------------------------------------------------*/
  471.  
  472. static void
  473. modify_filename_extention (buffer, ext)
  474.      char *buffer;
  475.      char *ext;
  476. {
  477.   register char *p, *dot;
  478.  
  479.   for (p = buffer, dot = (char*)0; *p; p ++)
  480.     {
  481.       if (*p == '.')
  482.         dot = p;
  483.       else if (*p == '/')
  484.         dot = (char*)0;
  485.     }
  486.  
  487.   if (dot)
  488.     p = dot;
  489.  
  490.   strcpy (p, ext);
  491. }
  492.  
  493. /*----------------------------------------------------------------------*/
  494. /*                                                                      */
  495. /*----------------------------------------------------------------------*/
  496.  
  497. static boolean
  498. open_old_archive_1 (name, v_fp)
  499.      char *name;
  500.      FILE **v_fp;
  501. {
  502.   FILE *fp;
  503.   struct stat stbuf;
  504.  
  505.   if (stat (name, &stbuf) >= 0 &&
  506.       (fp = fopen (name, READ_BINARY)) != NULL)
  507.     {
  508.       *v_fp = fp;
  509.       return TRUE;
  510.     }
  511.  
  512.   *v_fp = NULL;
  513.   return FALSE;
  514. }
  515.  
  516. FILE *
  517. open_old_archive ()
  518. {
  519.   FILE *fp;
  520.  
  521.   if (!open_old_archive_1 (archive_name, &fp))
  522.     {
  523.       if (expand_archive_name (expanded_archive_name, archive_name))
  524.         {
  525.           archive_name = expanded_archive_name;
  526.           if (open_old_archive_1 (archive_name, &fp))
  527.             errno = 0;
  528.         }
  529.     }
  530.   return fp;
  531. }
  532.