home *** CD-ROM | disk | FTP | other *** search
- /* LHarc Dearchiver Main */
-
- /* Opens an archive and tests each internal file to see if it matches */
- /* a specified wildcard pattern. If it does, it dearchives 1 buffers */
- /* worth on each call. It does this for every file in the archive. */
- /* 0 <= x != buffer size -> end of file */
- /* 0 <= x <= buffer size -> x = # of bytes read into buf */
- /* x > buffer size -> # of bytes read into buffer = buf size */
- /* 0 > x -> end of archive */
- /* if no files match pattern, 0 is returned. Next call -1 is returned */
-
- #include "lharc.h"
-
- int NotInterruptedCall = 1;
- int ForceReturn;
- extern long WinSiz, BCount, TotRd;
- char expanded_archive_name[FILENAME_LENGTH];
- char *writting_filename;
- char *archive_name;
- extern char *WildLZH;
- extern long BufrCnt;
- long TotSiz;
- long cursize;
- long HWinSiz;
- char *BfrPtr;
- LzHeader hdr;
- long pos;
- FILE *afp=NULL;
-
- long
- FillBufWithLZH( reading_filename, buffer )
- char *reading_filename;
- char *buffer;
- {
- BfrPtr = buffer;
- HWinSiz = WinSiz >> 1;
- archive_name = reading_filename;
- ForceReturn = 0;
- if( NotInterruptedCall ) {
- if( afp == NULL ) {
- /* open archive file */
- if ((afp = open_old_archive ()) == NULL) fatal_error (archive_name);
- }
- if( get_header (afp, &hdr)) {
- pos = ftell( afp);
- BCount = HWinSiz; /* lh5 only */
- TotRd = hdr.packed_size; /* lh5 only */
- cursize = hdr.original_size; /* lh5 only */
- TotSiz = 0;
- BufrCnt = 0;
- extract_one( afp, &hdr);
- }
- else {
- /* close archive file */
- fclose( afp);
- afp = NULL;
- return(-1);
- }
- }
- else {
- extract_one (afp, &hdr);
- }
-
- if( ForceReturn ) {
- NotInterruptedCall = 0;
- }
- else {
- fseek( afp, pos + hdr.packed_size, SEEK_SET);
- if( TotSiz == WinSiz) TotSiz++; /* signify endof int file if nonobvious */
- }
-
- return(TotSiz);
- }
-
- static
- message_1 (title, subject, name)
- char *title, *subject, *name;
- {
- fprintf (stderr, "LHarc: %s%s ", title, subject);
- fflush (stderr);
-
- if (errno == 0)
- fprintf (stderr, "%s\n", name);
- else
- perror (name);
- }
-
- void
- message (subject, name)
- char *subject, *name;
- {
- message_1 ("", subject, name);
- }
-
- void
- warning (subject, name)
- char *subject, *name;
- {
- message_1 ("Warning: ", subject, name);
- }
-
- void
- error (subject, msg)
- char *subject, *msg;
- {
- message_1 ("Error: ", subject, msg);
- }
-
- void
- fatal_error (msg)
- char *msg;
- {
- message_1 ("Fatal error:", "", msg);
- ErrP("terminating...");
- }
-
- read_error ()
- {
- fatal_error (archive_name);
- }
-
- /*----------------------------------------------------------------------*/
- /* */
- /*----------------------------------------------------------------------*/
-
- static boolean
- expand_archive_name (dst, src)
- char *dst, *src;
- {
- register char *p, *dot;
-
- strcpy (dst, src);
-
- for (p = dst, dot = (char*)0; ; p ++, dot = (char*)0)
- {
- while (*p == '.') /* skip leading dots of base name */
- p ++;
- for (; *p != '/'; p ++)
- {
- if (*p == '.')
- dot = p;
- else if (*p == '\0')
- goto _Done;
- }
- }
- _Done:
-
- if (dot)
- p = dot;
-
- strcpy (p, ARCHIVENAME_EXTENTION); /* ".lzh" */
- return (strcmp (dst, src) != 0);
- }
-
- /*----------------------------------------------------------------------*/
- /* */
- /*----------------------------------------------------------------------*/
-
- static int
- calc_sum (p, len)
- register char *p;
- register int len;
- {
- register int sum;
-
- for (sum = 0; len; len --)
- sum += *p++;
-
- return sum & 0xff;
- }
-
- static char *get_ptr;
- #define setup_get(PTR) (get_ptr = (PTR))
- #define get_byte() (*get_ptr++ & 0xff)
- #define put_ptr get_ptr
- #define setup_put(PTR) (put_ptr = (PTR))
-
- static unsigned short
- get_word ()
- {
- int b0, b1;
-
- b0 = get_byte ();
- b1 = get_byte ();
- return (b1 << 8) + b0;
- }
-
- static long
- get_longword ()
- {
- long b0, b1, b2, b3;
-
- b0 = get_byte ();
- b1 = get_byte ();
- b2 = get_byte ();
- b3 = get_byte ();
- return (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
- }
-
- static
- msdos_to_unix_filename (name, len)
- register char *name;
- register int len;
- {
- register int i;
-
- #ifdef MULTIBYTE_CHAR
- for (i = 0; i < len; i ++)
- {
- if (MULTIBYTE_FIRST_P (name[i]) &&
- MULTIBYTE_SECOND_P (name[i+1]))
- i ++;
- else if (name[i] == '\\')
- name[i] = '/';
- else if (isupper (name[i]))
- name[i] = tolower (name[i]);
- }
- #else
- for (i = 0; i < len; i ++)
- {
- if (name[i] == '\\')
- name[i] = '/';
- else if (isupper (name[i]))
- name[i] = tolower (name[i]);
- }
- #endif
- }
-
- static
- generic_to_unix_filename (name, len)
- register char *name;
- register int len;
- {
- register int i;
- boolean lower_case_used = FALSE;
-
- #ifdef MULTIBYTE_CHAR
- for (i = 0; i < len; i ++)
- {
- if (MULTIBYTE_FIRST_P (name[i]) &&
- MULTIBYTE_SECOND_P (name[i+1]))
- i ++;
- else if (islower (name[i]))
- {
- lower_case_used = TRUE;
- break;
- }
- }
- for (i = 0; i < len; i ++)
- {
- if (MULTIBYTE_FIRST_P (name[i]) &&
- MULTIBYTE_SECOND_P (name[i+1]))
- i ++;
- else if (name[i] == '\\')
- name[i] = '/';
- else if (!lower_case_used && isupper (name[i]))
- name[i] = tolower (name[i]);
- }
- #else
- for (i = 0; i < len; i ++)
- if (islower (name[i]))
- {
- lower_case_used = TRUE;
- break;
- }
- for (i = 0; i < len; i ++)
- {
- if (name[i] == '\\')
- name[i] = '/';
- else if (!lower_case_used && isupper (name[i]))
- name[i] = tolower (name[i]);
- }
- #endif
- }
-
- static
- macos_to_unix_filename (name, len)
- register char *name;
- register int len;
- {
- register int i;
-
- for (i = 0; i < len; i ++)
- {
- if (name[i] == ':')
- name[i] = '/';
- else if (name[i] == '/')
- name[i] = ':';
- }
- }
-
- /*----------------------------------------------------------------------*/
- /* */
- /* Generic stamp format: */
- /* */
- /* 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 */
- /* |<-------- year ------->|<- month ->|<-- day -->| */
- /* */
- /* 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 */
- /* |<--- hour --->|<---- minute --->|<- second*2 ->| */
- /* */
- /*----------------------------------------------------------------------*/
-
-
- static long
- gettz ()
- {
- return(time((time_t *)NULL));
- }
-
- static time_t
- generic_to_unix_stamp (t)
- long t;
- {
- int year, month, day, hour, min, sec;
- long longtime;
- static unsigned int dsboy[12] = { 0, 31, 59, 90, 120, 151,
- 181, 212, 243, 273, 304, 334};
- unsigned int days;
-
- year = ((int)(t >> 16+9) & 0x7f) + 1980;
- month = (int)(t >> 16+5) & 0x0f; /* 1..12 means Jan..Dec */
- day = (int)(t >> 16) & 0x1f; /* 1..31 means 1st,...31st */
-
- hour = ((int)t >> 11) & 0x1f;
- min = ((int)t >> 5) & 0x3f;
- sec = ((int)t & 0x1f) * 2;
-
- /* Calculate days since 1970.01.01 */
- days = (365 * (year - 1970) + /* days due to whole years */
- (year - 1970 + 1) / 4 + /* days due to leap years */
- dsboy[month-1] + /* days since beginning of this year */
- day-1); /* days since beginning of month */
-
- if ((year % 4 == 0) &&
- (year % 400 != 0) &&
- (month >= 3)) /* if this is a leap year and month */
- days ++; /* is March or later, add a day */
-
- /* Knowing the days, we can find seconds */
- longtime = (((days * 24) + hour) * 60 + min) * 60 + sec;
- longtime += gettz (); /* adjust for timezone */
-
- /* special case: if MSDOS format date and time were zero, then we set
- time to be zero here too. */
- if (t == 0)
- longtime = 0;
-
- /* LONGTIME is now the time in seconds, since 1970/01/01 00:00:00. */
- return (time_t)longtime;
- }
-
- /*----------------------------------------------------------------------*/
- /* */
- /*----------------------------------------------------------------------*/
-
- boolean
- get_header (fp, hdr)
- FILE *fp;
- register LzHeader *hdr;
- {
- int header_size;
- int name_length;
- char data[LZHEADER_STRAGE];
- int checksum;
- int i;
-
- bzero (hdr, sizeof (LzHeader));
-
- if (((header_size = getc (fp)) == EOF) || (header_size == 0))
- {
- return FALSE; /* finish */
- }
-
- if (fread (data + I_HEADER_CHECKSUM,
- sizeof (char), header_size + 1, fp) < header_size + 1)
- {
- fatal_error ("Invalid header (LHarc file ?)");
- return FALSE; /* finish */
- }
-
- setup_get (data + I_HEADER_CHECKSUM);
- checksum = calc_sum (data + I_METHOD, header_size);
- if (get_byte () != checksum)
- warning ("Checksum error (LHarc file?)", "");
-
- hdr->header_size = header_size;
- bcopy (data + I_METHOD, hdr->method, METHOD_TYPE_STRAGE);
- #ifdef OLD
- if ((bcmp (hdr->method, LZHUFF1_METHOD, METHOD_TYPE_STRAGE) != 0) &&
- (bcmp (hdr->method, LZHUFF0_METHOD, METHOD_TYPE_STRAGE) != 0) &&
- (bcmp (hdr->method, LARC5_METHOD, METHOD_TYPE_STRAGE) != 0) &&
- (bcmp (hdr->method, LARC4_METHOD, METHOD_TYPE_STRAGE) != 0))
- {
- warning ("Unknown method (LHarc file ?)", "");
- return FALSE; /* invalid method */
- }
- #endif
- setup_get (data + I_PACKED_SIZE);
- hdr->packed_size = get_longword ();
- hdr->original_size = get_longword ();
- hdr->last_modified_stamp = get_longword ();
- hdr->attribute = get_word ();
- name_length = get_byte ();
- for (i = 0; i < name_length; i ++)
- hdr->name[i] =(char)get_byte ();
- hdr->name[name_length] = '\0';
-
- /* defaults for other type */
- hdr->unix_mode = UNIX_FILE_REGULAR | UNIX_RW_RW_RW;
- hdr->unix_gid = 0;
- hdr->unix_uid = 0;
-
- if (header_size - name_length >= 24)
- { /* EXTEND FORMAT */
- hdr->crc = get_word ();
- hdr->extend_type = get_byte ();
- hdr->minor_version = get_byte ();
- hdr->has_crc = TRUE;
- }
- else if (header_size - name_length == 22)
- { /* Generic with CRC */
- hdr->crc = get_word ();
- hdr->extend_type = EXTEND_GENERIC;
- hdr->has_crc = TRUE;
- }
- else if (header_size - name_length == 20)
- { /* Generic no CRC */
- hdr->extend_type = EXTEND_GENERIC;
- hdr->has_crc = FALSE;
- }
- else
- {
- warning ("Unknown header (LHarc file ?)", "");
- return FALSE;
- }
-
- switch (hdr->extend_type)
- {
- case EXTEND_MSDOS:
- msdos_to_unix_filename (hdr->name, name_length);
- hdr->unix_last_modified_stamp =
- generic_to_unix_stamp (hdr->last_modified_stamp);
- break;
-
- case EXTEND_UNIX:
- hdr->unix_last_modified_stamp = (time_t)get_longword ();
- hdr->unix_mode = get_word ();
- hdr->unix_uid = get_word ();
- hdr->unix_gid = get_word ();
- break;
-
- case EXTEND_MACOS:
- macos_to_unix_filename (hdr->name, name_length);
- hdr->unix_last_modified_stamp =
- generic_to_unix_stamp (hdr->last_modified_stamp);
- break;
-
- default:
- generic_to_unix_filename (hdr->name, name_length);
- hdr->unix_last_modified_stamp =
- generic_to_unix_stamp (hdr->last_modified_stamp);
- }
-
- return TRUE;
- }
-
- /*----------------------------------------------------------------------*/
- /* */
- /*----------------------------------------------------------------------*/
-
- static void
- modify_filename_extention (buffer, ext)
- char *buffer;
- char *ext;
- {
- register char *p, *dot;
-
- for (p = buffer, dot = (char*)0; *p; p ++)
- {
- if (*p == '.')
- dot = p;
- else if (*p == '/')
- dot = (char*)0;
- }
-
- if (dot)
- p = dot;
-
- strcpy (p, ext);
- }
-
- /*----------------------------------------------------------------------*/
- /* */
- /*----------------------------------------------------------------------*/
-
- static boolean
- open_old_archive_1 (name, v_fp)
- char *name;
- FILE **v_fp;
- {
- FILE *fp;
- struct stat stbuf;
-
- if (stat (name, &stbuf) >= 0 &&
- (fp = fopen (name, READ_BINARY)) != NULL)
- {
- *v_fp = fp;
- return TRUE;
- }
-
- *v_fp = NULL;
- return FALSE;
- }
-
- FILE *
- open_old_archive ()
- {
- FILE *fp;
-
- if (!open_old_archive_1 (archive_name, &fp))
- {
- if (expand_archive_name (expanded_archive_name, archive_name))
- {
- archive_name = expanded_archive_name;
- if (open_old_archive_1 (archive_name, &fp))
- errno = 0;
- }
- }
- return fp;
- }
-