home *** CD-ROM | disk | FTP | other *** search
- /*----------------------------------------------------------------------*/
- /* header.c (from lharc.c) -- header manipulate functions */
- /* Original by Y.Tagawa */
- /* modified Dec 16 1991 by M.Oki */
- /*----------------------------------------------------------------------*/
-
- #include "lharc.h"
- extern int header_level;
-
- 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))
- #define put_byte(c) (*put_ptr++ = (char)(c))
-
- static unsigned short
- get_word ()
- {
- int b0, b1;
-
- b0 = get_byte ();
- b1 = get_byte ();
- return (b1 << 8) + b0;
- }
-
- static void
- put_word (v)
- unsigned int v;
- {
- put_byte (v);
- put_byte (v >> 8);
- }
-
- 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 void
- put_longword (v)
- long v;
- {
- put_byte (v);
- put_byte (v >> 8);
- put_byte (v >> 16);
- put_byte (v >> 24);
- }
-
-
- static void
- 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 void
- 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 void
- 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] = ':';
- }
- }
-
- static void
- unix_to_generic_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 (islower (name[i]))
- name[i] = toupper (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 ->| */
- /* */
- /*----------------------------------------------------------------------*/
-
- /* NOTE : If you don't have `gettimeofday(2)', or your gettimeofday(2)
- returns bogus timezone information, try FTIME, MKTIME, TIMELOCAL or
- TZSET. */
-
- /* choose one */
- #if defined(MKTIME)
- #ifdef TIMELOCAL
- #undef TIMELOCAL
- #endif
- #endif /* defined(MKTIME) */
-
- #if defined(MKTIME) || defined(TIMELOCAL)
- #ifdef TZSET
- #undef TZSET
- #endif
- #endif /* defined(MKTIME) || defined(TIMELOCAL) */
-
- #if defined(MKTIME) || defined(TIMELOCAL) || defined(TZSET)
- #ifdef FTIME
- #undef FTIME
- #endif
- #endif
-
- #if defined(MKTIME) || defined(TIMELOCAL) || defined(TZSET) || defined(FTIME)
- #ifdef GETTIMEOFDAY
- #undef GETTIMEOFDAY
- #endif
- #else
- #ifndef GETTIMEOFDAY
- #define GETTIMEOFDAY /* use gettimeofday() */
- #endif
- #endif
-
- #ifdef FTIME
- #include <sys/timeb.h>
- #endif
-
- /* You may define as :
- #define TIMEZONE_HOOK \
- extern long timezone ; \
- extern void tzset();
- */
- #ifdef TIMEZONE_HOOK
- TIMEZONE_HOOK
- /* Which do you like better, `TIMEZONE_HOOK' or `TIMEZONE_HOOK;' ? */
- #endif
-
- #if defined(TZSET) && defined(_MINIX)
- extern long timezone; /* not defined in time.h */
- #endif
-
- #if defined(FTIME) || defined(GETTIMEOFDAY) || defined(TZSET)
- static long
- gettz ()
- #ifdef TZSET
- {
- tzset();
- return timezone;
- }
- #endif
- #if !defined(TZSET) && defined(FTIME)
- {
- struct timeb buf;
-
- ftime(&buf);
- return buf.timezone * 60L;
- }
- #endif
- #if !defined(TZSET) && !defined(FTIME) /* maybe defined(GETTIMEOFDAY) */
- {
- struct timeval tp;
- struct timezone tzp;
- gettimeofday (&tp, &tzp); /* specific to 4.3BSD */
- /* return (tzp.tz_minuteswest * 60L + (tzp.tz_dsttime != 0 ? 60L * 60L : 0));*/
- return (tzp.tz_minuteswest * 60L);
- }
- #endif
- #endif /* defined(FTIME) || defined(GETTIMEOFDAY) || defined(TZSET) */
-
- #ifdef NOT_USED
- static struct tm *
- msdos_to_unix_stamp_tm (a)
- long a;
- {
- static struct tm t;
-
- t.tm_sec = ( a & 0x1f) * 2;
- t.tm_min = (a >> 5) & 0x3f;
- t.tm_hour = (a >> 11) & 0x1f;
- t.tm_mday = (a >> 16) & 0x1f;
- t.tm_mon = ((a >> 16+5) & 0x0f) - 1;
- t.tm_year = ((a >> 16+9) & 0x7f) + 80;
- return &t;
- }
- #endif
-
- static time_t
- generic_to_unix_stamp (t)
- long t;
- #if defined(MKTIME) || defined(TIMELOCAL)
- {
- struct tm dostm;
-
- /* special case: if MSDOS format date and time were zero, then we set
- time to be zero here too. */
- if (t == 0)
- return (time_t)0;
-
- dostm.tm_sec = (t & 0x1f) * 2;
- dostm.tm_min = t >> 5 & 0x3f;
- dostm.tm_hour = t >> 11 & 0x1f;
- dostm.tm_mday = t >> 16 & 0x1f;
- dostm.tm_mon = (t >> 16+5 & 0x0f) - 1; /* 0..11 */
- dostm.tm_year = (t >> 16+9 & 0x7f) + 80;
- dostm.tm_isdst = 0; /* correct? */
- #ifdef MKTIME
- return (time_t)mktime(&dostm);
- #else /* maybe defined(TIMELOCAL) */
- return (time_t)timelocal(&dostm);
- #endif
- }
- #else /* defined(MKTIME) || defined(TIMELOCAL) */
- {
- 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;
-
- /* special case: if MSDOS format date and time were zero, then we set
- time to be zero here too. */
- if (t == 0)
- return (time_t)0;
-
- 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 */
-
- /* LONGTIME is now the time in seconds, since 1970/01/01 00:00:00. */
- return (time_t)longtime;
- }
- #endif /* defined(MKTIME) || defined(TIMELOCAL) */
-
- static long
- unix_to_generic_stamp (t)
- time_t t;
- {
- struct tm *tm = localtime (&t);
-
- return ((((long)(tm->tm_year - 80)) << 25) +
- (((long)(tm->tm_mon + 1)) << 21) +
- (((long)tm->tm_mday) << 16) +
- (long)((tm->tm_hour << 11) +
- (tm->tm_min << 5) +
- (tm->tm_sec / 2)));
- }
-
- /*----------------------------------------------------------------------*/
- /* build header functions */
- /*----------------------------------------------------------------------*/
-
- boolean
- get_header (fp, hdr)
- FILE *fp;
- register LzHeader *hdr;
- {
- int header_size;
- int name_length;
- char data[LZHEADER_STRAGE];
- char dirname[FILENAME_LENGTH];
- int dir_length = 0;
- int checksum;
- int i;
- char *ptr;
-
- 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_LEVEL);
- hdr->header_level = get_byte();
- if (hdr->header_level != 2 &&
- fread (data + header_size, sizeof (char), 2, fp) < 2)
- {
- fatal_error ("Invalid header (LHarc file ?)");
- return FALSE; /* finish */
- }
-
- setup_get (data + I_HEADER_CHECKSUM);
- checksum = get_byte();
-
- 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_byte ();
-
- if ((hdr->header_level = get_byte ()) != 2) {
- if (calc_sum (data + I_METHOD, header_size) != checksum)
- warning ("Checksum error (LHarc file?)", "");
- name_length = get_byte ();
- for (i = 0; i < name_length; i ++)
- hdr->name[i] =(char)get_byte ();
- hdr->name[name_length] = '\0';
- } else {
- hdr->unix_last_modified_stamp = hdr->last_modified_stamp;
- 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->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;
- }
-
- if (hdr->extend_type == EXTEND_UNIX && hdr->header_level == 0)
- {
- hdr->minor_version = get_byte ();
- hdr->unix_last_modified_stamp = (time_t)get_longword ();
- hdr->unix_mode = get_word ();
- hdr->unix_uid = get_word ();
- hdr->unix_gid = get_word ();
- return TRUE;
- }
-
- if (hdr->header_level > 0) {
- /* Extend Header */
- if (hdr->header_level != 2) setup_get(data + hdr->header_size);
- ptr = get_ptr;
- while((header_size = get_word()) != 0)
- {
- if (hdr->header_level != 2 &&
- ((data + LZHEADER_STRAGE - get_ptr < header_size) ||
- fread(get_ptr, sizeof(char), header_size, fp) < header_size))
- {
- fatal_error ("Invalid header (LHa file ?)");
- return FALSE;
- }
- switch (get_byte()) {
- case 0:
- /*
- * header crc
- */
- setup_get(get_ptr + header_size - 3);
- break;
- case 1:
- /*
- * filename
- */
- for (i = 0; i < header_size - 3; i++)
- hdr->name[i] =(char)get_byte ();
- hdr->name[header_size - 3] = '\0';
- break;
- case 2:
- /*
- * directory
- */
- for (i = 0; i < header_size - 3; i++)
- dirname[i] = (char)get_byte ();
- dirname[header_size - 3] = '\0';
- convdelim(dirname, DELIM);
- dir_length = header_size-3;
- break;
- case 0x40:
- /*
- * MS-DOS attribute
- */
- if (hdr->extend_type == EXTEND_MSDOS ||
- hdr->extend_type == EXTEND_HUMAN ||
- hdr->extend_type == EXTEND_GENERIC)
- hdr->attribute = get_word();
- break;
- case 0x50:
- /*
- * UNIX permission
- */
- if (hdr->extend_type == EXTEND_UNIX)
- hdr->unix_mode = get_word();
- break;
- case 0x51:
- /*
- * UNIX gid and uid
- */
- if (hdr->extend_type == EXTEND_UNIX)
- {
- hdr->unix_gid = get_word();
- hdr->unix_uid = get_word();
- }
- break;
- case 0x52:
- /*
- * UNIX group name
- */
- setup_get(get_ptr + header_size - 3);
- break;
- case 0x53:
- /*
- * UNIX user name
- */
- setup_get(get_ptr + header_size - 3);
- break;
- case 0x54:
- /*
- * UNIX last modified time
- */
- if (hdr->extend_type == EXTEND_UNIX)
- hdr->unix_last_modified_stamp = (time_t)get_longword();
- break;
- default:
- /*
- * other headers
- */
- setup_get(get_ptr + header_size - 3);
- break;
- }
- }
- if (hdr->header_level != 2 && get_ptr - ptr != 2) {
- hdr->packed_size -= get_ptr - ptr - 2;
- hdr->header_size += get_ptr - ptr - 2;
- }
- }
- if (dir_length)
- {
- strcat(dirname, hdr->name);
- strcpy(hdr->name, dirname);
- name_length += dir_length;
- }
-
- switch (hdr->extend_type)
- {
- case EXTEND_MSDOS:
- msdos_to_unix_filename (hdr->name, name_length);
- case EXTEND_HUMAN:
- if (hdr->header_level == 2)
- hdr->unix_last_modified_stamp = hdr->last_modified_stamp;
- else
- hdr->unix_last_modified_stamp =
- generic_to_unix_stamp (hdr->last_modified_stamp);
- break;
-
- #ifdef OSK
- case EXTEND_OS68K:
- case EXTEND_XOSK:
- #endif
- case EXTEND_UNIX:
- 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);
- if (hdr->header_level == 2)
- hdr->unix_last_modified_stamp = hdr->last_modified_stamp;
- else
- hdr->unix_last_modified_stamp =
- generic_to_unix_stamp (hdr->last_modified_stamp);
- }
-
- return TRUE;
- }
-
- void
- init_header (name, v_stat, hdr)
- char *name;
- struct stat *v_stat;
- LzHeader *hdr;
- {
- int len;
-
- if ( compress_method == 5 )
- bcopy (LZHUFF5_METHOD, hdr->method, METHOD_TYPE_STRAGE);
- else if ( compress_method )
- bcopy (LZHUFF1_METHOD, hdr->method, METHOD_TYPE_STRAGE);
- else
- bcopy (LZHUFF0_METHOD, hdr->method, METHOD_TYPE_STRAGE);
-
- hdr->packed_size = 0;
- hdr->original_size = v_stat->st_size;
- hdr->last_modified_stamp = unix_to_generic_stamp (v_stat->st_mtime);
- hdr->attribute = GENERIC_ATTRIBUTE;
- hdr->header_level = header_level;
- strcpy (hdr->name, name);
- len = strlen (name);
- hdr->crc = 0x0000;
- hdr->extend_type = EXTEND_UNIX;
- hdr->unix_last_modified_stamp = v_stat->st_mtime;
- /* since 00:00:00 JAN.1.1970 */
- #ifdef NOT_COMPATIBLE_MODE
- /* Please need your modification in this space. */
- #else
- hdr->unix_mode = v_stat->st_mode;
- #endif
-
- hdr->unix_uid = v_stat->st_uid;
- hdr->unix_gid = v_stat->st_gid;
-
- if (is_directory (v_stat))
- {
- bcopy (LZHDIRS_METHOD, hdr->method, METHOD_TYPE_STRAGE);
- hdr->attribute = GENERIC_DIRECTORY_ATTRIBUTE;
- hdr->original_size = 0;
- if (len > 0 && hdr->name[len-1] != '/')
- strcpy (&hdr->name[len++], "/");
- }
- if (generic_format)
- unix_to_generic_filename (hdr->name, len);
- }
-
- /* Write unix extended header or generic header. */
- void
- write_header (nafp, hdr)
- FILE *nafp;
- LzHeader *hdr;
- {
- int header_size;
- int name_length;
- char data[LZHEADER_STRAGE];
- char *p;
-
- bzero (data, LZHEADER_STRAGE);
- bcopy (hdr->method, data + I_METHOD, METHOD_TYPE_STRAGE);
- setup_put (data + I_PACKED_SIZE);
- put_longword (hdr->packed_size);
- put_longword (hdr->original_size);
-
- if (hdr->header_level == HEADER_LEVEL2)
- put_longword ((long)hdr->unix_last_modified_stamp);
- else
- put_longword (hdr->last_modified_stamp);
-
- switch (hdr->header_level)
- {
- case HEADER_LEVEL0:
- put_byte (hdr->attribute);
- break;
- case HEADER_LEVEL1:
- case HEADER_LEVEL2:
- put_byte (0x20);
- break;
- }
-
- put_byte (hdr->header_level);
-
- convdelim(hdr->name, DELIM2);
- if (hdr->header_level != HEADER_LEVEL2)
- {
- if (p = (char *)rindex(hdr->name, DELIM2))
- name_length = strlen(++p);
- else
- name_length = strlen(hdr->name);
- put_byte (name_length);
- bcopy (p ? p : hdr->name, data + I_NAME, name_length);
- setup_put (data + I_NAME + name_length);
- }
-
- put_word (hdr->crc);
- if (generic_format)
- {
- header_size = I_GENERIC_HEADER_BOTTOM - 2 + name_length;
- data[I_HEADER_SIZE] = header_size;
- data[I_HEADER_CHECKSUM] = calc_sum (data + I_METHOD, header_size);
- }
- else if (header_level == HEADER_LEVEL0)
- {
- /* write old-style extend header */
- put_byte (EXTEND_UNIX);
- put_byte (CURRENT_UNIX_MINOR_VERSION);
- put_longword ((long)hdr->unix_last_modified_stamp);
- put_word (hdr->unix_mode);
- put_word (hdr->unix_uid);
- put_word (hdr->unix_gid);
- header_size = I_UNIX_EXTEND_BOTTOM - 2 + name_length;
- data[I_HEADER_SIZE] = header_size;
- data[I_HEADER_CHECKSUM] = calc_sum (data + I_METHOD, header_size);
- }
- else
- {
- /* write extend header. */
- char *ptr;
- put_byte (EXTEND_UNIX);
- ptr = put_ptr;
- put_word(5);
- if (hdr->header_level == HEADER_LEVEL1)
- header_size = put_ptr - data - 2;
- put_byte(0x50); /* permission */
- put_word(hdr->unix_mode);
- put_word(7);
- put_byte(0x51); /* gid and uid */
- put_word(hdr->unix_gid);
- put_word(hdr->unix_uid);
- if (p = (char *)rindex(hdr->name, DELIM2))
- {
- int i;
- name_length = p - hdr->name + 1;
- put_word(name_length + 3);
- put_byte(2); /* dirname */
- for (i = 0; i < name_length; i++)
- put_byte(hdr->name[i]);
- }
- if (header_level != HEADER_LEVEL2)
- {
- put_word(7);
- put_byte(0x54); /* time stamp */
- put_longword(hdr->unix_last_modified_stamp);
- hdr->packed_size += put_ptr - ptr;
- ptr = put_ptr;
- setup_put (data + I_PACKED_SIZE);
- put_longword (hdr->packed_size);
- put_ptr = ptr;
- data[I_HEADER_SIZE] = header_size;
- data[I_HEADER_CHECKSUM] = calc_sum (data + I_METHOD, header_size);
- }
- else
- {
- int i;
- if (p = (char *)rindex(hdr->name, DELIM2))
- name_length = strlen(++p);
- else
- {
- p = hdr->name;
- name_length = strlen(hdr->name);
- }
- put_word(name_length + 3);
- put_byte(1); /* filename */
- for (i = 0; i < name_length; i++)
- put_byte(*p++);
- }
- header_size = put_ptr - data;
- }
- if (header_level == HEADER_LEVEL2)
- {
- setup_put(data + I_HEADER_SIZE);
- put_word(header_size + 2);
- }
- if (fwrite (data, sizeof (char), header_size + 2, nafp) == 0)
- fatal_error ("Cannot write to temporary file");
- convdelim(hdr->name, DELIM);
- }
-