/* ------------------------------------------------------------------------ */
-/* LHa for UNIX */
-/* header.c -- header manipulate functions */
-/* */
-/* Modified Nobutaka Watazaki */
-/* */
-/* Original Y.Tagawa */
-/* modified 1991.12.16 M.Oki */
-/* Ver. 1.10 Symbolic Link added 1993.10.01 N.Watazaki */
-/* Ver. 1.13b Symbolic Link Bug Fix 1994.08.22 N.Watazaki */
-/* Ver. 1.14 Source All chagned 1995.01.14 N.Watazaki */
-/* Ver. 1.14i bug fixed 2000.10.06 t.okamoto */
+/* LHa for UNIX */
+/* header.c -- header manipulate functions */
+/* */
+/* Modified Nobutaka Watazaki */
+/* */
+/* Original Y.Tagawa */
+/* modified 1991.12.16 M.Oki */
+/* Ver. 1.10 Symbolic Link added 1993.10.01 N.Watazaki */
+/* Ver. 1.13b Symbolic Link Bug Fix 1994.08.22 N.Watazaki */
+/* Ver. 1.14 Source All chagned 1995.01.14 N.Watazaki */
+/* Ver. 1.14i bug fixed 2000.10.06 t.okamoto */
+/* Ver. 1.14i Contributed UTF-8 convertion for Mac OS X */
+/* 2002.06.29 Hiroto Sakai */
+/* Ver. 1.14i autoconfiscated & rewritten 2003.02.23 Koji Arai */
/* ------------------------------------------------------------------------ */
#include "lha.h"
#define strrchr xstrrchr
#endif
-/* ------------------------------------------------------------------------ */
static char *get_ptr;
-#define GET_BYTE() (*get_ptr++ & 0xff)
+#define GET_BYTE() (*get_ptr++ & 0xff)
#if DUMP_HEADER
static char *start_ptr;
#define get_byte() dump_get_byte()
#define skip_bytes(len) dump_skip_bytes(len)
#else
-#define setup_get(PTR) (get_ptr = (PTR))
-#define get_byte() GET_BYTE()
+#define setup_get(PTR) (get_ptr = (PTR))
+#define get_byte() GET_BYTE()
#define skip_bytes(len) (get_ptr += (len))
#endif
-#define put_ptr get_ptr
-#define setup_put(PTR) (put_ptr = (PTR))
-#define put_byte(c) (*put_ptr++ = (char)(c))
+#define put_ptr get_ptr
+#define setup_put(PTR) (put_ptr = (PTR))
+#define put_byte(c) (*put_ptr++ = (char)(c))
int optional_archive_kanji_code = NONE;
int optional_system_kanji_code = NONE;
int default_system_kanji_code = NONE;
#endif
-/* ------------------------------------------------------------------------ */
int
calc_sum(p, len)
- register char *p;
- register int len;
+ void *p;
+ int len;
{
- register int sum;
+ int sum = 0;
- for (sum = 0; len; len--)
- sum += *p++;
+ while (len--) sum += *(unsigned char*)p++;
- return sum & 0xff;
+ return sum & 0xff;
}
#if DUMP_HEADER
{
if (len == 0) return;
if (verbose_listing && verbose > 1) {
- printf("%02d %2d:", get_ptr - start_ptr, len);
+ printf("%02d %2d: ", get_ptr - start_ptr, len);
while (len--)
- printf(" 0x%02x", GET_BYTE());
- printf("\n");
+ printf("0x%02x ", GET_BYTE());
+ printf("... ignored\n");
}
else
get_ptr += len;
}
#endif
-/* ------------------------------------------------------------------------ */
static int
get_word()
{
- int b0, b1;
+ int b0, b1;
int w;
#if DUMP_HEADER
if (verbose_listing && verbose > 1)
printf("%02d %2d: ", get_ptr - start_ptr, 2);
#endif
- b0 = GET_BYTE();
- b1 = GET_BYTE();
+ b0 = GET_BYTE();
+ b1 = GET_BYTE();
w = (b1 << 8) + b0;
#if DUMP_HEADER
if (verbose_listing && verbose > 1)
printf("%d(0x%04x)\n", w, w);
#endif
- return w;
+ return w;
}
-/* ------------------------------------------------------------------------ */
static void
put_word(v)
- unsigned int v;
+ unsigned int v;
{
- put_byte(v);
- put_byte(v >> 8);
+ put_byte(v);
+ put_byte(v >> 8);
}
-/* ------------------------------------------------------------------------ */
static long
get_longword()
{
- long b0, b1, b2, b3;
+ long b0, b1, b2, b3;
long l;
#if DUMP_HEADER
if (verbose_listing && verbose > 1)
printf("%02d %2d: ", get_ptr - start_ptr, 4);
#endif
- b0 = GET_BYTE();
- b1 = GET_BYTE();
- b2 = GET_BYTE();
- b3 = GET_BYTE();
+ b0 = GET_BYTE();
+ b1 = GET_BYTE();
+ b2 = GET_BYTE();
+ b3 = GET_BYTE();
l = (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
#if DUMP_HEADER
if (verbose_listing && verbose > 1)
printf("%ld(0x%08lx)\n", l, l);
#endif
- return l;
+ return l;
}
-/* ------------------------------------------------------------------------ */
static void
put_longword(v)
- long v;
+ long v;
{
- put_byte(v);
- put_byte(v >> 8);
- put_byte(v >> 16);
- put_byte(v >> 24);
+ put_byte(v);
+ put_byte(v >> 8);
+ put_byte(v >> 16);
+ put_byte(v >> 24);
}
static int
from_delim, to_delim,
case_to)
char *name;
- int len;
- int size;
+ int len; /* length of name */
+ int size; /* size of name buffer */
int from_code, to_code, case_to;
char *from_delim, *to_delim;
int i;
#ifdef MULTIBYTE_FILENAME
char tmp[FILENAME_LENGTH];
+ int to_code_save = NONE;
+
+ if (from_code == CODE_CAP) {
+ len = cap_to_sjis(tmp, name, sizeof(tmp));
+ strncpy(name, tmp, size);
+ name[size-1] = 0;
+ len = strlen(name);
+ from_code = CODE_SJIS;
+ }
+
+ if (to_code == CODE_CAP) {
+ to_code_save = CODE_CAP;
+ to_code = CODE_SJIS;
+ }
if (from_code == CODE_SJIS && to_code == CODE_UTF8) {
for (i = 0; i < len; i++)
if (from_code == CODE_SJIS && case_to == TO_LOWER) {
for (i = 0; i < len; i++) {
#ifdef MULTIBYTE_FILENAME
- if (SJIS_FIRST_P(name[i]))
+ if (SJIS_FIRST_P(name[i]) && SJIS_SECOND_P(name[i+1]))
i++;
else
#endif
continue;
}
}
-}
-/* ------------------------------------------------------------------------ */
-/* */
-/* 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 ->| */
-/* */
-/* ------------------------------------------------------------------------ */
+#ifdef MULTIBYTE_FILENAME
+ if (to_code_save == CODE_CAP) {
+ len = sjis_to_cap(tmp, name, sizeof(tmp));
+ strncpy(name, tmp, size);
+ name[size-1] = 0;
+ len = strlen(name);
+ }
+#endif /* MULTIBYTE_FILENAME */
+}
/*
- * NOTE : If you don't have `gettimeofday(2)', or your gettimeofday(2)
- * returns bogus timezone information, try FTIME, MKTIME, TIMELOCAL or TZSET.
+ * Generic (MS-DOS style) time stamp format (localtime):
+ *
+ * 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
+ * |<---- year-1980 --->|<- month ->|<--- day ---->|
+ *
+ * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+ * |<--- hour --->|<---- minute --->|<- second/2 ->|
+ *
*/
-/* choose one */
-#if defined(HAVE_MKTIME)
-#ifdef HAVE_TIMELOCAL
-#undef HAVE_TIMELOCAL
-#endif
-#endif /* defined(HAVE_MKTIME) */
+static time_t
+generic_to_unix_stamp(t)
+ long t;
+{
+ struct tm tm;
-#if defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL)
-#ifdef HAVE_TZSET
-#undef HAVE_TZSET
-#endif
-#endif /* defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL) */
+#define subbits(n, off, len) (((n) >> (off)) & ((1 << (len))-1))
-#if defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL) || defined(HAVE_TZSET)
-#ifdef HAVE_FTIME
-#undef HAVE_FTIME
-#endif
-#endif
+ tm.tm_sec = subbits(t, 0, 5) * 2;
+ tm.tm_min = subbits(t, 5, 6);
+ tm.tm_hour = subbits(t, 11, 5);
+ tm.tm_mday = subbits(t, 16, 5);
+ tm.tm_mon = subbits(t, 21, 4) - 1;
+ tm.tm_year = subbits(t, 25, 7) + 80;
+ tm.tm_isdst = -1;
-#if defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL) || defined(HAVE_TZSET) || defined(HAVE_FTIME)
-#ifdef HAVE_GETTIMEOFDAY
-#undef HAVE_GETTIMEOFDAY
-#endif
+#if HAVE_MKTIME
+ return mktime(&tm);
#else
-#ifndef HAVE_GETTIMEOFDAY
-#define HAVE_GETTIMEOFDAY /* use gettimeofday() */
-#endif
-#endif
-
-#ifdef HAVE_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(HAVE_TZSET) && defined(_MINIX)
-extern long timezone; /* not defined in time.h */
+ return timelocal(&tm);
#endif
+}
-/* ------------------------------------------------------------------------ */
-#if defined(HAVE_FTIME) || defined(HAVE_GETTIMEOFDAY) || defined(HAVE_TZSET)
static long
-gettz()
-#ifdef HAVE_TZSET
+unix_to_generic_stamp(t)
+ time_t t;
{
- tzset();
- return timezone;
-}
-#endif
+ struct tm *tm = localtime(&t);
-/* ------------------------------------------------------------------------ */
-#if !defined(HAVE_TZSET) && defined(HAVE_FTIME)
-{
- struct timeb buf;
+ tm->tm_year -= 80;
+ tm->tm_mon += 1;
- ftime(&buf);
- return buf.timezone * 60L;
+ return ((long)(tm->tm_year << 25) +
+ (tm->tm_mon << 21) +
+ (tm->tm_mday << 16) +
+ (tm->tm_hour << 11) +
+ (tm->tm_min << 5) +
+ (tm->tm_sec / 2));
}
-#endif
-/* ------------------------------------------------------------------------ */
-#if !defined(HAVE_TZSET) && !defined(HAVE_FTIME) /* maybe defined(HAVE_GETTIMEOFDAY) */
+static unsigned long
+wintime_to_unix_stamp()
{
-#ifdef HAVE_STRUCT_TM_TM_GMTOFF
- time_t tt;
-
- time(&tt);
- return -localtime(&tt)->tm_gmtoff;
-#else /* HAVE_STRUCT_TM_TM_GMTOFF */
- 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 /* HAVE_STRUCT_TM_TM_GMTOFF */
-}
-#endif
-#endif /* defined(HAVE_FTIME) || defined(HAVE_GETTIMEOFDAY) ||
- * defined(HAVE_TZSET) */
+#if HAVE_UINT64_T
+ uint64_t t;
+ uint64_t epoch = ((uint64_t)0x019db1de << 32) + 0xd53e8000;
+ /* 0x019db1ded53e8000ULL: 1970-01-01 00:00:00 (UTC) */
+
+ t = (unsigned long)get_longword();
+ t |= (uint64_t)(unsigned long)get_longword() << 32;
+ t = (t - epoch) / 10000000;
+ return t;
+#else
+ int i, borrow;
+ unsigned long t, q, x;
+ unsigned long wintime[8];
+ unsigned long epoch[8] = {0x01,0x9d,0xb1,0xde, 0xd5,0x3e,0x80,0x00};
+ /* 1970-01-01 00:00:00 (UTC) */
+ /* wintime -= epoch */
+ borrow = 0;
+ for (i = 7; i >= 0; i--) {
+ wintime[i] = (unsigned)get_byte() - epoch[i] - borrow;
+ borrow = (wintime[i] > 0xff) ? 1 : 0;
+ wintime[i] &= 0xff;
+ }
-/* ------------------------------------------------------------------------ */
-static time_t
-generic_to_unix_stamp(t)
- long t;
-#if defined(HAVE_MKTIME) || defined(HAVE_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;
-#if 0
- dostm.tm_isdst = 0; /* correct? */
-#endif
- dostm.tm_isdst = -1; /* correct? */
-#ifdef HAVE_MKTIME
- return (time_t) mktime(&dostm);
-#else /* maybe defined(HAVE_TIMELOCAL) */
- return (time_t) timelocal(&dostm);
+ /* q = wintime / 10000000 */
+ t = q = 0;
+ x = 10000000; /* x: 24bit */
+ for (i = 0; i < 8; i++) {
+ t = (t << 8) + wintime[i]; /* 24bit + 8bit. t must be 32bit variable */
+ q <<= 8; /* q must be 32bit (time_t) */
+ q += t / x;
+ t %= x; /* 24bit */
+ }
+ return q;
#endif
}
-#else /* defined(HAVE_MKTIME) || defined(HAVE_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 % 100 != 0 || year % 400 == 0) && /* 1999.5.24 t.oka */
- (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(HAVE_MKTIME) || defined(HAVE_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 */
-/* ------------------------------------------------------------------------ */
-
/*
* extended header
*
* on level 3 header:
* size field is 4 bytes
*/
-static long
+
+static ssize_t
get_extended_header(fp, hdr, header_size, hcrc)
FILE *fp;
LzHeader *hdr;
- long header_size;
+ size_t header_size;
unsigned int *hcrc;
{
char data[LZHEADER_STORAGE];
char dirname[FILENAME_LENGTH];
int dir_length = 0;
int i;
- long whole_size = header_size;
+ ssize_t whole_size = header_size;
int ext_type;
int n = 1 + hdr->size_field_length; /* `ext-type' + `next-header size' */
break;
case 0x41:
/* Windows time stamp (FILETIME structure) */
- skip_bytes(header_size - n); /* ignored */
+ /* it is time in 100 nano seconds since 1601-01-01 00:00:00 */
+
+ skip_bytes(8); /* create time is ignored */
+
+ /* set last modified time */
+ if (hdr->header_level >= 2)
+ skip_bytes(8); /* time_t has been already set */
+ else
+ hdr->unix_last_modified_stamp = wintime_to_unix_stamp();
+
+ skip_bytes(8); /* last access time is ignored */
+
break;
case 0x50:
/* UNIX permission */
name_length = sizeof(hdr->name) - dir_length - 1;
hdr->name[name_length] = 0;
}
- strcat(dirname, hdr->name);
- strcpy(hdr->name, dirname);
+ strcat(dirname, hdr->name); /* ok */
+ strcpy(hdr->name, dirname); /* ok */
name_length += dir_length;
}
return whole_size;
}
+#define I_HEADER_SIZE 0 /* level 0,1,2 */
+#define I_HEADER_CHECKSUM 1 /* level 0,1 */
+#define I_METHOD 2 /* level 0,1,2,3 */
+#define I_PACKED_SIZE 7 /* level 0,1,2,3 */
+#define I_ATTRIBUTE 19 /* level 0,1,2,3 */
+#define I_HEADER_LEVEL 20 /* level 0,1,2,3 */
+
+#define COMMON_HEADER_SIZE 21 /* size of common part */
+
+#define I_GENERIC_HEADER_SIZE 24 /* + name_length */
+#define I_LEVEL0_HEADER_SIZE 36 /* + name_length (unix extended) */
+#define I_LEVEL1_HEADER_SIZE 27 /* + name_length */
+#define I_LEVEL2_HEADER_SIZE 26 /* + padding */
+#define I_LEVEL3_HEADER_SIZE 32
+
/*
* level 0 header
*
LzHeader *hdr;
char *data;
{
- int header_size;
+ size_t header_size;
+ ssize_t extend_size;
int checksum;
int name_length;
int i;
- int extend_size;
hdr->size_field_length = 2; /* in bytes */
hdr->header_size = header_size = get_byte();
checksum = get_byte();
- if (fread(data+I_NAME_LENGTH, header_size+2-I_NAME_LENGTH, 1, fp) == 0) {
+ if (fread(data + COMMON_HEADER_SIZE,
+ header_size + 2 - COMMON_HEADER_SIZE, 1, fp) == 0) {
error("Invalid header (LHarc file ?)");
return FALSE; /* finish */
}
LzHeader *hdr;
char *data;
{
- int header_size, extend_size;
+ size_t header_size;
+ ssize_t extend_size;
int checksum;
int name_length;
int i, dummy;
hdr->header_size = header_size = get_byte();
checksum = get_byte();
- if (fread(data+I_NAME_LENGTH, header_size+2-I_NAME_LENGTH, 1, fp) == 0) {
+ if (fread(data + COMMON_HEADER_SIZE,
+ header_size + 2 - COMMON_HEADER_SIZE, 1, fp) == 0) {
error("Invalid header (LHarc file ?)");
return FALSE; /* finish */
}
hdr->crc = get_word();
hdr->extend_type = get_byte();
- dummy = header_size+2 - name_length - 27;
+ dummy = header_size+2 - name_length - I_LEVEL1_HEADER_SIZE;
if (dummy > 0)
skip_bytes(dummy); /* skip old style extend header */
LzHeader *hdr;
char *data;
{
- int header_size, extend_size;
+ size_t header_size;
+ ssize_t extend_size;
int padding;
unsigned int hcrc;
hdr->size_field_length = 2; /* in bytes */
hdr->header_size = header_size = get_word();
- if (fread(data + I_NAME_LENGTH, 26 - I_NAME_LENGTH, 1, fp) == 0) {
+ if (fread(data + COMMON_HEADER_SIZE,
+ I_LEVEL2_HEADER_SIZE - COMMON_HEADER_SIZE, 1, fp) == 0) {
error("Invalid header (LHarc file ?)");
return FALSE; /* finish */
}
if (extend_size == -1)
return FALSE;
- padding = header_size - 26 - extend_size;
+ padding = header_size - I_LEVEL2_HEADER_SIZE - extend_size;
while (padding--) /* padding should be 0 or 1 */
hcrc = UPDATE_CRC(hcrc, fgetc(fp));
LzHeader *hdr;
char *data;
{
- long header_size, extend_size;
+ size_t header_size;
+ ssize_t extend_size;
int padding;
unsigned int hcrc;
hdr->size_field_length = get_word();
- if (fread(data + I_NAME_LENGTH, 32 - I_NAME_LENGTH, 1, fp) == 0) {
+ if (fread(data + COMMON_HEADER_SIZE,
+ I_LEVEL3_HEADER_SIZE - COMMON_HEADER_SIZE, 1, fp) == 0) {
error("Invalid header (LHarc file ?)");
return FALSE; /* finish */
}
if (extend_size == -1)
return FALSE;
- padding = header_size - 32 - extend_size;
+ padding = header_size - I_LEVEL3_HEADER_SIZE - extend_size;
while (padding--) /* padding should be 0 */
hcrc = UPDATE_CRC(hcrc, fgetc(fp));
}
data[0] = end_mark;
- if (fread(data + 1, I_NAME_LENGTH - 1, 1, fp) == 0) {
+ if (fread(data + 1, COMMON_HEADER_SIZE - 1, 1, fp) == 0) {
error("Invalid header (LHarc file ?)");
return FALSE; /* finish */
}
system_kanji_code,
archive_delim, system_delim, filename_case);
+ if ((hdr->unix_mode & UNIX_FILE_SYMLINK) == UNIX_FILE_SYMLINK) {
+ char *p;
+ /* split symbolic link */
+ p = strchr(hdr->name, '|');
+ if (p) {
+ /* hdr->name is symbolic link name */
+ /* hdr->realname is real name */
+ *p = 0;
+ strcpy(hdr->realname, p+1); /* ok */
+ }
+ else
+ error("unknown symlink name \"%s\"", hdr->name);
+ }
+
return TRUE;
}
-/* ------------------------------------------------------------------------ */
+/* skip SFX header */
+int
+seek_lha_header(fp)
+ FILE *fp;
+{
+ unsigned char buffer[64 * 1024]; /* max seek size */
+ unsigned char *p;
+ int n;
+
+ n = fread(buffer, 1, sizeof(buffer), fp);
+
+ for (p = buffer; p < buffer + n; p++) {
+ if (! (p[I_METHOD]=='-' && p[I_METHOD+1]=='l' && p[I_METHOD+4]=='-'))
+ continue;
+ /* found "-l??-" keyword (as METHOD type string) */
+
+ /* level 0 or 1 header */
+ if ((p[I_HEADER_LEVEL] == 0 || p[I_HEADER_LEVEL] == 1)
+ && p[I_HEADER_SIZE] > 20
+ && p[I_HEADER_CHECKSUM] == calc_sum(p+2, p[I_HEADER_SIZE])) {
+ if (fseeko(fp, (p - buffer) - n, SEEK_CUR) == -1)
+ fatal_error("cannot seek header");
+ return 0;
+ }
+
+ /* level 2 header */
+ if (p[I_HEADER_LEVEL] == 2
+ && p[I_HEADER_SIZE] >= 24
+ && p[I_ATTRIBUTE] == 0x20) {
+ if (fseeko(fp, (p - buffer) - n, SEEK_CUR) == -1)
+ fatal_error("cannot seek header");
+ return 0;
+ }
+ }
+
+ if (fseeko(fp, -n, SEEK_CUR) == -1)
+ fatal_error("cannot seek header");
+ return -1;
+}
+
+
+/* remove leading `xxxx/..' */
+static char *
+remove_leading_dots(char *path)
+{
+ char *first = path;
+ char *ptr = 0;
+
+ if (strcmp(first, "..") == 0) {
+ warning("Removing leading `..' from member name.");
+ return first+1; /* change to "." */
+ }
+
+ if (strstr(first, "..") == 0)
+ return first;
+
+ while (path && *path) {
+
+ if (strcmp(path, "..") == 0)
+ ptr = path = path+2;
+ else if (strncmp(path, "../", 3) == 0)
+ ptr = path = path+3;
+ else
+ path = strchr(path, '/');
+
+ if (path && *path == '/') {
+ path++;
+ }
+ }
+
+ if (ptr) {
+ warning("Removing leading `%.*s' from member name.", ptr-first, first);
+ return ptr;
+ }
+
+ return first;
+}
+
void
init_header(name, v_stat, hdr)
- char *name;
- struct stat *v_stat;
- LzHeader *hdr;
+ char *name;
+ struct stat *v_stat;
+ LzHeader *hdr;
{
- int len;
+ int len;
memset(hdr, 0, sizeof(LzHeader));
but need set for empty files */
memcpy(hdr->method, LZHUFF0_METHOD, METHOD_TYPE_STORAGE);
- hdr->packed_size = 0;
- hdr->original_size = v_stat->st_size;
- 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 */
+ hdr->packed_size = 0;
+ hdr->original_size = v_stat->st_size;
+ hdr->attribute = GENERIC_ATTRIBUTE;
+ hdr->header_level = header_level;
+ len = str_safe_copy(hdr->name,
+ remove_leading_dots(name),
+ sizeof(hdr->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. */
+ /* Please need your modification in this space. */
#else
- hdr->unix_mode = v_stat->st_mode;
+ hdr->unix_mode = v_stat->st_mode;
#endif
- hdr->unix_uid = v_stat->st_uid;
- hdr->unix_gid = v_stat->st_gid;
+ hdr->unix_uid = v_stat->st_uid;
+ hdr->unix_gid = v_stat->st_gid;
#if INCLUDE_OWNER_NAME_IN_HEADER
#if HAVE_GETPWUID
}
#endif
#endif /* INCLUDE_OWNER_NAME_IN_HEADER */
- if (is_directory(v_stat)) {
- memcpy(hdr->method, LZHDIRS_METHOD, METHOD_TYPE_STORAGE);
- hdr->attribute = GENERIC_DIRECTORY_ATTRIBUTE;
- hdr->original_size = 0;
- if (len > 0 && hdr->name[len - 1] != '/')
- strcpy(&hdr->name[len++], "/");
- }
+ if (is_directory(v_stat)) {
+ memcpy(hdr->method, LZHDIRS_METHOD, METHOD_TYPE_STORAGE);
+ hdr->attribute = GENERIC_DIRECTORY_ATTRIBUTE;
+ hdr->original_size = 0;
+ if (len > 0 && hdr->name[len - 1] != '/') {
+ if (len < sizeof(hdr->name)-1)
+ strcpy(&hdr->name[len++], "/"); /* ok */
+ else
+ warning("the length of dirname \"%s\" is too long.",
+ hdr->name);
+ }
+ }
#ifdef S_IFLNK
- if (is_symlink(v_stat)) {
- char lkname[FILENAME_LENGTH];
- int len;
- memcpy(hdr->method, LZHDIRS_METHOD, METHOD_TYPE_STORAGE);
- hdr->attribute = GENERIC_DIRECTORY_ATTRIBUTE;
- hdr->original_size = 0;
- len = readlink(name, lkname, sizeof(lkname));
- if (xsnprintf(hdr->name, sizeof(hdr->name),
- "%s|%.*s", hdr->name, len, lkname) == -1)
- error("file name is too long (%s -> %.*s)", hdr->name, len, lkname);
- }
+ if (is_symlink(v_stat)) {
+ memcpy(hdr->method, LZHDIRS_METHOD, METHOD_TYPE_STORAGE);
+ hdr->attribute = GENERIC_DIRECTORY_ATTRIBUTE;
+ hdr->original_size = 0;
+ readlink(name, hdr->realname, sizeof(hdr->realname));
+ }
#endif
}
}
}
-/* ------------------------------------------------------------------------ */
-/* Write unix extended header or generic header. */
-
-static int
+static size_t
write_header_level0(data, hdr, pathname)
LzHeader *hdr;
char *data, *pathname;
{
int limit;
int name_length;
- int header_size;
+ size_t header_size;
setup_put(data);
memset(data, 0, LZHEADER_STORAGE);
/* write pathname (level 0 header contains the directory part) */
name_length = strlen(pathname);
if (generic_format)
- limit = 255 - I_GENERIC_HEADER_BOTTOM + 2;
+ limit = 255 - I_GENERIC_HEADER_SIZE + 2;
else
- limit = 255 - I_UNIX_EXTEND_BOTTOM + 2;
+ limit = 255 - I_LEVEL0_HEADER_SIZE + 2;
if (name_length > limit) {
warning("the length of pathname \"%s\" is too long.", pathname);
put_word(hdr->crc);
if (generic_format) {
- header_size = I_GENERIC_HEADER_BOTTOM + name_length - 2;
+ header_size = I_GENERIC_HEADER_SIZE + name_length - 2;
data[I_HEADER_SIZE] = header_size;
data[I_HEADER_CHECKSUM] = calc_sum(data + I_METHOD, header_size);
} else {
put_word(hdr->unix_gid);
/* size of extended header is 12 */
- header_size = I_UNIX_EXTEND_BOTTOM + name_length - 2;
+ header_size = I_LEVEL0_HEADER_SIZE + name_length - 2;
data[I_HEADER_SIZE] = header_size;
data[I_HEADER_CHECKSUM] = calc_sum(data + I_METHOD, header_size);
}
return header_size + 2;
}
-static int
+static size_t
write_header_level1(data, hdr, pathname)
LzHeader *hdr;
char *data, *pathname;
{
int name_length, dir_length, limit;
char *basename, *dirname;
- int header_size;
+ size_t header_size;
char *extend_header_top;
- int extend_header_size;
+ size_t extend_header_size;
basename = strrchr(pathname, LHA_PATHSEP);
if (basename) {
put_byte(hdr->header_level); /* level 1 */
/* level 1 header: write filename (basename only) */
- limit = 255 - 27 + 2;
+ limit = 255 - I_LEVEL1_HEADER_SIZE + 2;
if (name_length > limit) {
put_byte(0); /* name length */
}
return header_size + extend_header_size + 2;
}
-static int
+static size_t
write_header_level2(data, hdr, pathname)
LzHeader *hdr;
char *data, *pathname;
{
int name_length, dir_length;
char *basename, *dirname;
- int header_size;
+ size_t header_size;
char *extend_header_top;
char *headercrc_ptr;
unsigned int hcrc;
header_size++;
}
- /* put hader size */
+ /* put header size */
setup_put(data + I_HEADER_SIZE);
put_word(header_size);
- /* put hader CRC in extended header */
+ /* put header CRC in extended header */
INITIALIZE_CRC(hcrc);
hcrc = calccrc(hcrc, data, (unsigned int) header_size);
setup_put(headercrc_ptr);
FILE *fp;
LzHeader *hdr;
{
- int header_size;
+ size_t header_size;
char data[LZHEADER_STORAGE];
int archive_kanji_code = CODE_SJIS;
if (generic_format)
filename_case = TO_UPPER;
- if (hdr->header_level == HEADER_LEVEL0) {
+ if (hdr->header_level == 0) {
archive_delim = "\\";
}
- strncpy(pathname, hdr->name, sizeof(pathname));
- pathname[sizeof(pathname)-1] = 0;
+ if ((hdr->unix_mode & UNIX_FILE_SYMLINK) == UNIX_FILE_SYMLINK) {
+ char *p;
+ p = strchr(hdr->name, '|');
+ if (p) {
+ error("symlink name \"%s\" contains '|' char. change it into '_'",
+ hdr->name);
+ *p = '_';
+ }
+ if (xsnprintf(pathname, sizeof(pathname),
+ "%s|%s", hdr->name, hdr->realname) == -1)
+ error("file name is too long (%s -> %s)", hdr->name, hdr->realname);
+ }
+ else {
+ strncpy(pathname, hdr->name, sizeof(pathname));
+ pathname[sizeof(pathname)-1] = 0;
+ }
+
convert_filename(pathname, strlen(pathname), sizeof(pathname),
system_kanji_code,
archive_kanji_code,
#if MULTIBYTE_FILENAME
-#if defined(__APPLE__)
+#if defined(__APPLE__) /* Added by Hiroto Sakai */
#include <CoreFoundation/CFString.h>
#include <CoreFoundation/CFStringEncodingExt.h>
/*
* SJIS <-> EUC ÊÑ´¹´Ø¿ô
- * ¡ÖÆüËܸì¾ðÊó½èÍý¡× ¥½¥Õ¥È¥Ð¥ó¥¯(³ô)
- * ¤è¤êÈ´¿è(by Koji Arai)
+ * ¡ÖÆüËܸì¾ðÊó½èÍý¡× ¥½¥Õ¥È¥Ð¥ó¥¯(³ô)
+ * ¤è¤êÈ´¿è(by Koji Arai)
*/
void
euc2sjis(int *p1, int *p2)
*p1 |= 0x80;
*p2 |= 0x80;
}
-#endif /* MULTIBYTE_FILENAME */
-/* Local Variables: */
-/* mode:c */
-/* tab-width:4 */
-/* compile-command:"gcc -c header.c" */
-/* End: */
-/* vi: set tabstop=4: */
+static int
+hex2int(int c)
+{
+ switch (c) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ return c - '0';
+
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ return c - 'a' + 10;
+
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ return c - 'A' + 10;
+ default:
+ return -1;
+ }
+}
+
+static int
+int2hex(int c)
+{
+ switch (c) {
+ case 0: case 1: case 2: case 3: case 4:
+ case 5: case 6: case 7: case 8: case 9:
+ return c + '0';
+
+ case 10: case 11: case 12: case 13: case 14: case 15:
+ return c + 'a' - 10;
+
+ default:
+ return -1;
+ }
+}
+
+int
+cap_to_sjis(char *dst, const char *src, size_t dstsize)
+{
+ int i, j;
+ size_t len = strlen(src);
+ int a, b;
+
+ for (i = j = 0; i < len && i < dstsize; i++) {
+ if (src[i] != ':') {
+ dst[j++] = src[i];
+ continue;
+ }
+
+ i++;
+ a = hex2int((unsigned char)src[i]);
+ b = hex2int((unsigned char)src[i+1]);
+
+ if (a == -1 || b == -1) {
+ /* leave as it */
+ dst[j++] = ':';
+ strncpy(dst+j, src+i, dstsize-j);
+ dst[dstsize-1] = 0;
+ return strlen(dst);
+ }
+
+ i++;
+
+ dst[j++] = a * 16 + b;
+ }
+ dst[j] = 0;
+ return j;
+}
+
+int
+sjis_to_cap(char *dst, const char *src, size_t dstsize)
+{
+ int i, j;
+ size_t len = strlen(src);
+ int a, b;
+
+ for (i = j = 0; i < len && i < dstsize; i++) {
+ if (src[i] == ':') {
+ strncpy(dst+j, ":3a", dstsize-j);
+ dst[dstsize-1] = 0;
+ j = strlen(dst);
+ continue;
+ }
+ if (isprint(src[i])) {
+ dst[j++] = src[i];
+ continue;
+ }
+
+ if (j + 3 >= dstsize) {
+ dst[j] = 0;
+ return j;
+ }
+
+ a = int2hex((unsigned char)src[i] / 16);
+ b = int2hex((unsigned char)src[i] % 16);
+
+ dst[j++] = ':';
+ dst[j++] = a;
+ dst[j++] = b;
+ }
+ dst[j] = 0;
+ return j;
+}
+#endif /* MULTIBYTE_FILENAME */