/* 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"
#endif
static char *get_ptr;
-#define GET_BYTE() (*get_ptr++ & 0xff)
+static char *start_ptr;
+static off_t storage_size;
+#define setup_get(PTR, SIZE) (start_ptr = get_ptr = (PTR), storage_size = (SIZE))
#if DUMP_HEADER
-static char *start_ptr;
-#define setup_get(PTR) (start_ptr = get_ptr = (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 skip_bytes(len) (get_ptr += (len))
+#define get_byte() _get_byte()
+#define skip_bytes(len) _skip_bytes(len)
#endif
#define put_ptr get_ptr
#define setup_put(PTR) (put_ptr = (PTR))
int
calc_sum(p, len)
- char *p;
+ void *p;
int len;
{
int sum = 0;
+ unsigned char *pc = (unsigned char*)p;
- while (len--) sum += *p++;
+ while (len--) sum += *pc++;
return sum & 0xff;
}
+static void
+_skip_bytes(len)
+{
+ if (len < 0) {
+ error("Invalid header: %d", len);
+ exit(1);
+ }
+ get_ptr += len;
+}
+
+static int
+_get_byte()
+{
+ if (get_ptr < start_ptr || get_ptr - start_ptr >= storage_size) {
+ error("Invalid header");
+ exit(1);
+ }
+
+ return (*get_ptr++ & 0xff);
+}
+
#if DUMP_HEADER
static int
dump_get_byte()
if (verbose_listing && verbose > 1)
printf("%02d %2d: ", get_ptr - start_ptr, 1);
- c = GET_BYTE();
+ c = _get_byte();
if (verbose_listing && verbose > 1) {
if (isprint(c))
printf("%d(0x%02x) '%c'\n", c, c, c);
if (len == 0) return;
if (verbose_listing && verbose > 1) {
printf("%02d %2d: ", get_ptr - start_ptr, len);
+ if (len < 0) {
+ error("Invalid header: %d", len);
+ exit(1);
+ }
while (len--)
- printf("0x%02x ", GET_BYTE());
+ printf("0x%02x ", _get_byte());
printf("... ignored\n");
}
else
- get_ptr += len;
+ _skip_bytes(len);
}
#endif
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)
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)
}
static void
-put_longword(v)
- long v;
+put_longword(long v)
+{
+ put_byte(v);
+ put_byte(v >> 8);
+ put_byte(v >> 16);
+ put_byte(v >> 24);
+}
+
+#ifdef HAVE_UINT64_T
+static uint64_t
+get_longlongword()
+{
+ uint64_t b0, b1, b2, b3, b4, b5, b6, b7;
+ uint64_t 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();
+ b4 = _get_byte();
+ b5 = _get_byte();
+ b6 = _get_byte();
+ b7 = _get_byte();
+
+ l = (b7 << 24) + (b6 << 16) + (b5 << 8) + b4;
+ l <<= 32;
+ l |= (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
+#if DUMP_HEADER
+ if (verbose_listing && verbose > 1)
+ printf("%lld(%#016llx)\n", l, l);
+#endif
+ return l;
+}
+
+static void
+put_longlongword(uint64_t v)
{
put_byte(v);
put_byte(v >> 8);
put_byte(v >> 16);
put_byte(v >> 24);
+ put_byte(v >> 32);
+ put_byte(v >> 40);
+ put_byte(v >> 48);
+ put_byte(v >> 56);
}
+#endif
static int
get_bytes(buf, len, size)
#if DUMP_HEADER
if (verbose_listing && verbose > 1)
printf("%02d %2d: \"", get_ptr - start_ptr, len);
+ if (len < 0) {
+ error("Invalid header: %d", len);
+ exit(1);
+ }
- for (i = 0; i < len; i++) {
- if (i < size) buf[i] = get_ptr[i];
+ for (i = 0; i < len && i < size; i++) {
+ buf[i] = get_ptr[i];
if (verbose_listing && verbose > 1) {
if (isprint(buf[i]))
if (verbose_listing && verbose > 1)
printf("\"\n");
#else
+ if (len < 0) {
+ error("Invalid header: %d", len);
+ exit(1);
+ }
for (i = 0; i < len && i < size; i++)
buf[i] = get_ptr[i];
#endif
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;
+ }
+#endif
+
+ /* special case: if `name' has small lettter, not convert case. */
+ if (from_code == CODE_SJIS && case_to == TO_LOWER) {
+ for (i = 0; i < len; i++) {
+#ifdef MULTIBYTE_FILENAME
+ if (SJIS_FIRST_P(name[i]) && SJIS_SECOND_P(name[i+1]))
+ i++;
+ else
+#endif
+ if (islower(name[i])) {
+ case_to = NONE;
+ break;
+ }
+ }
+ }
+#ifdef MULTIBYTE_FILENAME
if (from_code == CODE_SJIS && to_code == CODE_UTF8) {
- for (i = 0; i < len; i++)
- /* FIXME: provisionally fix for the Mac OS CoreFoundation */
- if ((unsigned char)name[i] == LHA_PATHSEP) name[i] = '/';
+ for (i = 0; i < len; i++) {
+ if (SJIS_FIRST_P(name[i]) && SJIS_SECOND_P(name[i+1]))
+ i++;
+ else {
+ /* FIXME: provisionally fix for the Mac OS CoreFoundation */
+ if (strchr(from_delim, name[i]))
+ name[i] = '/';
+ }
+ }
sjis_to_utf8(tmp, name, sizeof(tmp));
strncpy(name, tmp, size);
name[size-1] = 0;
}
#endif
- /* special case: if `name' has small lettter, not convert case. */
- if (from_code == CODE_SJIS && case_to == TO_LOWER) {
- for (i = 0; i < len; i++) {
-#ifdef MULTIBYTE_FILENAME
- if (SJIS_FIRST_P(name[i]) && SJIS_SECOND_P(name[i+1]))
- i++;
- else
-#endif
- if (islower(name[i])) {
- case_to = NONE;
- break;
- }
- }
- }
-
for (i = 0; i < len; i ++) {
#ifdef MULTIBYTE_FILENAME
if (from_code == CODE_EUC &&
continue;
}
}
+
+#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 */
}
/*
- * Generic (MS-DOS style) time stamp format:
+ * 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 ----->|<- month ->|<--- day ---->|
+ * |<---- year-1980 --->|<- month ->|<--- day ---->|
*
* 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- * |<--- hour --->|<---- minute --->|<- second*2 ->|
+ * |<--- hour --->|<---- minute --->|<- second/2 ->|
*
*/
generic_to_unix_stamp(t)
long t;
{
- struct tm dostm;
+ struct tm tm;
- /*
- * special case: if MSDOS format date and time were zero, then we
- * set time to be zero here too.
- */
- if (t == 0)
- return 0;
+#define subbits(n, off, len) (((n) >> (off)) & ((1 << (len))-1))
- 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 = -1;
+ 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 HAVE_MKTIME
- return mktime(&dostm);
+ return mktime(&tm);
#else
- return timelocal(&dostm);
+ return timelocal(&tm);
#endif
}
{
#if HAVE_UINT64_T
uint64_t t;
- uint64_t epoch = 0x019db1ded53e8000; /* 1970-01-01 00:00:00 (UTC) */
+ uint64_t epoch = ((uint64_t)0x019db1de << 32) + 0xd53e8000;
+ /* 0x019db1ded53e8000ULL: 1970-01-01 00:00:00 (UTC) */
- t = get_longword();
- t += (uint64_t)get_longword() << 32;
+ t = (unsigned long)get_longword();
+ t |= (uint64_t)(unsigned long)get_longword() << 32;
t = (t - epoch) / 10000000;
return t;
#else
name_length = strlen(hdr->name);
while (header_size) {
- setup_get(data);
+#if DUMP_HEADER
+ if (verbose_listing && verbose > 1)
+ printf("---\n");
+#endif
+ setup_get(data, sizeof(data));
if (sizeof(data) < header_size) {
error("header size (%ld) too large.", header_size);
exit(1);
ext_type = get_byte();
switch (ext_type) {
case 0:
+#if DUMP_HEADER
+ if (verbose_listing && verbose > 1) printf(" < header crc >\n");
+#endif
/* header crc (CRC-16) */
hdr->header_crc = get_word();
/* clear buffer for CRC calculation. */
skip_bytes(header_size - n - 2);
break;
case 1:
+#if DUMP_HEADER
+ if (verbose_listing && verbose > 1) printf(" < filename >\n");
+#endif
/* filename */
name_length =
get_bytes(hdr->name, header_size-n, sizeof(hdr->name)-1);
hdr->name[name_length] = 0;
break;
case 2:
+#if DUMP_HEADER
+ if (verbose_listing && verbose > 1) printf(" < directory >\n");
+#endif
/* directory */
dir_length = get_bytes(dirname, header_size-n, sizeof(dirname)-1);
dirname[dir_length] = 0;
break;
case 0x40:
+#if DUMP_HEADER
+ if (verbose_listing && verbose > 1) printf(" < MS-DOS attribute >\n");
+#endif
/* MS-DOS attribute */
hdr->attribute = get_word();
break;
case 0x41:
+#if DUMP_HEADER
+ if (verbose_listing && verbose > 1) printf(" < Windows time stamp (FILETIME) >\n");
+#endif
/* Windows time stamp (FILETIME structure) */
/* it is time in 100 nano seconds since 1601-01-01 00:00:00 */
skip_bytes(8); /* last access time is ignored */
break;
+ case 0x42:
+#if DUMP_HEADER
+ if (verbose_listing && verbose > 1) printf(" < 64bits file size header >\n");
+#endif
+#ifdef HAVE_UINT64_T
+ /* 64bits file size header (UNLHA32 extension) */
+ hdr->packed_size = get_longlongword();
+ hdr->original_size = get_longlongword();
+#else
+ skip_bytes(8);
+ skip_bytes(8);
+#endif
+
+ break;
case 0x50:
+#if DUMP_HEADER
+ if (verbose_listing && verbose > 1) printf(" < UNIX permission >\n");
+#endif
/* UNIX permission */
hdr->unix_mode = get_word();
break;
case 0x51:
+#if DUMP_HEADER
+ if (verbose_listing && verbose > 1) printf(" < UNIX gid and uid >\n");
+#endif
/* UNIX gid and uid */
hdr->unix_gid = get_word();
hdr->unix_uid = get_word();
break;
case 0x52:
+#if DUMP_HEADER
+ if (verbose_listing && verbose > 1) printf(" < UNIX group name >\n");
+#endif
/* UNIX group name */
i = get_bytes(hdr->group, header_size-n, sizeof(hdr->group)-1);
hdr->group[i] = '\0';
break;
case 0x53:
+#if DUMP_HEADER
+ if (verbose_listing && verbose > 1) printf(" < UNIX user name >\n");
+#endif
/* UNIX user name */
i = get_bytes(hdr->user, header_size-n, sizeof(hdr->user)-1);
hdr->user[i] = '\0';
break;
case 0x54:
+#if DUMP_HEADER
+ if (verbose_listing && verbose > 1) printf(" < UNIX last modifed time (time_t) >\n");
+#endif
/* UNIX last modified time */
hdr->unix_last_modified_stamp = (time_t) get_longword();
break;
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;
}
char *data;
{
size_t header_size;
+ ssize_t remain_size;
ssize_t extend_size;
int checksum;
int name_length;
hdr->header_size = header_size = get_byte();
checksum = get_byte();
- if (fread(data + COMMON_HEADER_SIZE,
- header_size + 2 - COMMON_HEADER_SIZE, 1, fp) == 0) {
+ /* The data variable has been already read as COMMON_HEADER_SIZE bytes.
+ So we must read the remaining header size by the header_size. */
+ remain_size = header_size + 2 - COMMON_HEADER_SIZE;
+ if (remain_size <= 0) {
+ error("Invalid header size (LHarc file ?)");
+ return FALSE;
+ }
+ if (fread(data + COMMON_HEADER_SIZE, remain_size, 1, fp) == 0) {
error("Invalid header (LHarc file ?)");
return FALSE; /* finish */
}
}
get_bytes(hdr->method, 5, sizeof(hdr->method));
- hdr->packed_size = get_longword();
- hdr->original_size = get_longword();
+ hdr->packed_size = (unsigned long)get_longword();
+ hdr->original_size = (unsigned long)get_longword();
hdr->unix_last_modified_stamp = generic_to_unix_stamp(get_longword());
hdr->attribute = get_byte(); /* MS-DOS attribute */
hdr->header_level = get_byte();
hdr->has_crc = FALSE;
return TRUE;
- }
+ }
error("Unkonwn header (lha file?)");
exit(1);
char *data;
{
size_t header_size;
+ ssize_t remain_size;
ssize_t extend_size;
int checksum;
int name_length;
hdr->header_size = header_size = get_byte();
checksum = get_byte();
- if (fread(data + COMMON_HEADER_SIZE,
- header_size + 2 - COMMON_HEADER_SIZE, 1, fp) == 0) {
+ /* The data variable has been already read as COMMON_HEADER_SIZE bytes.
+ So we must read the remaining header size by the header_size. */
+ remain_size = header_size + 2 - COMMON_HEADER_SIZE;
+ if (remain_size <= 0) {
+ error("Invalid header size (LHarc file ?)");
+ return FALSE;
+ }
+ if (fread(data + COMMON_HEADER_SIZE, remain_size, 1, fp) == 0) {
error("Invalid header (LHarc file ?)");
return FALSE; /* finish */
}
}
get_bytes(hdr->method, 5, sizeof(hdr->method));
- hdr->packed_size = get_longword(); /* skip size */
- hdr->original_size = get_longword();
+ hdr->packed_size = (unsigned long)get_longword(); /* skip size */
+ hdr->original_size = (unsigned long)get_longword();
hdr->unix_last_modified_stamp = generic_to_unix_stamp(get_longword());
hdr->attribute = get_byte(); /* 0x20 fixed */
hdr->header_level = get_byte();
char *data;
{
size_t header_size;
+ ssize_t remain_size;
ssize_t extend_size;
int padding;
unsigned int hcrc;
hdr->size_field_length = 2; /* in bytes */
hdr->header_size = header_size = get_word();
+ /* The data variable has been already read as COMMON_HEADER_SIZE bytes.
+ So we must read the remaining header size without ext-header. */
+ remain_size = header_size - I_LEVEL2_HEADER_SIZE;
+ if (remain_size < 0) {
+ error("Invalid header size (LHarc file ?)");
+ return FALSE;
+ }
if (fread(data + COMMON_HEADER_SIZE,
I_LEVEL2_HEADER_SIZE - COMMON_HEADER_SIZE, 1, fp) == 0) {
error("Invalid header (LHarc file ?)");
}
get_bytes(hdr->method, 5, sizeof(hdr->method));
- hdr->packed_size = get_longword();
- hdr->original_size = get_longword();
+ hdr->packed_size = (unsigned long)get_longword();
+ hdr->original_size = (unsigned long)get_longword();
hdr->unix_last_modified_stamp = get_longword();
hdr->attribute = get_byte(); /* reserved */
hdr->header_level = get_byte();
return FALSE;
padding = header_size - I_LEVEL2_HEADER_SIZE - extend_size;
- while (padding--) /* padding should be 0 or 1 */
+ /* padding should be 0 or 1 */
+ if (padding != 0 && padding != 1) {
+ error("Invalid header size (padding: %d)", padding);
+ return FALSE;
+ }
+ while (padding--)
hcrc = UPDATE_CRC(hcrc, fgetc(fp));
if (hdr->header_crc != hcrc)
char *data;
{
size_t header_size;
+ ssize_t remain_size;
ssize_t extend_size;
int padding;
unsigned int hcrc;
}
get_bytes(hdr->method, 5, sizeof(hdr->method));
- hdr->packed_size = get_longword();
- hdr->original_size = get_longword();
+ hdr->packed_size = (unsigned long)get_longword();
+ hdr->original_size = (unsigned long)get_longword();
hdr->unix_last_modified_stamp = get_longword();
hdr->attribute = get_byte(); /* reserved */
hdr->header_level = get_byte();
hdr->crc = get_word();
hdr->extend_type = get_byte();
hdr->header_size = header_size = get_longword();
+ remain_size = header_size - I_LEVEL3_HEADER_SIZE;
+ if (remain_size < 0) {
+ error("Invalid header size (LHarc file ?)");
+ return FALSE;
+ }
extend_size = get_longword();
INITIALIZE_CRC(hcrc);
if (extend_size == -1)
return FALSE;
- padding = header_size - I_LEVEL3_HEADER_SIZE - extend_size;
- while (padding--) /* padding should be 0 */
- hcrc = UPDATE_CRC(hcrc, fgetc(fp));
+ padding = remain_size - extend_size;
+ /* padding should be 0 */
+ if (padding != 0) {
+ error("Invalid header size (padding: %d)", padding);
+ return FALSE;
+ }
if (hdr->header_crc != hcrc)
error("header CRC error");
memset(hdr, 0, sizeof(LzHeader));
- setup_get(data);
+ setup_get(data, sizeof(data));
if ((end_mark = getc(fp)) == EOF || end_mark == 0) {
return FALSE; /* finish */
/* filename conversion */
switch (hdr->extend_type) {
case EXTEND_MSDOS:
- filename_case = noconvertcase ? NONE : TO_LOWER;
+ filename_case = convertcase ? TO_LOWER : NONE;
break;
case EXTEND_HUMAN:
case EXTEND_OS68K:
break;
default:
- filename_case = noconvertcase ? NONE : TO_LOWER;
+ filename_case = convertcase ? TO_LOWER : NONE;
break;
}
/* hdr->name is symbolic link name */
/* hdr->realname is real name */
*p = 0;
- strncpy(hdr->realname, p+1, sizeof(hdr->realname));
+ strcpy(hdr->realname, p+1); /* ok */
}
else
error("unknown symlink name \"%s\"", hdr->name);
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]=='-'))
+ if (! (p[I_METHOD]=='-' &&
+ (p[I_METHOD+1]=='l' || p[I_METHOD+1]=='p') &&
+ p[I_METHOD+4]=='-'))
continue;
- /* found "-l??-" keyword (as METHOD type string) */
+ /* found "-[lp]??-" 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 (fseek(fp, (p - buffer) - n, SEEK_CUR) == -1)
+ if (fseeko(fp, (p - buffer) - n, SEEK_CUR) == -1)
fatal_error("cannot seek header");
return 0;
}
if (p[I_HEADER_LEVEL] == 2
&& p[I_HEADER_SIZE] >= 24
&& p[I_ATTRIBUTE] == 0x20) {
- if (fseek(fp, (p - buffer) - n, SEEK_CUR) == -1)
+ if (fseeko(fp, (p - buffer) - n, SEEK_CUR) == -1)
fatal_error("cannot seek header");
return 0;
}
}
- if (fseek(fp, -n, SEEK_CUR) == -1)
+ 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;
+}
+
+static int
+copy_path_element(char *dst, const char *src, int size)
+{
+ int i;
+
+ if (size < 1) return 0;
+
+ for (i = 0; i < size; i++) {
+ dst[i] = src[i];
+ if (dst[i] == '\0')
+ return i;
+ if (dst[i] == '/') {
+ dst[++i] = 0;
+ return i;
+ }
+ }
+
+ dst[--i] = 0;
+
+ return i;
+}
+
+/*
+ canonicalize path
+
+ remove leading "xxx/../"
+ remove "./", "././", "././ ... ./"
+ remove duplicated "/"
+*/
+static int
+canon_path(char *newpath, char *path, size_t size)
+{
+ char *p = newpath;
+
+ path = remove_leading_dots(path);
+
+ while (*path) {
+ if (path[0] == '.' && path[1] == '/')
+ path += 2;
+ else {
+ int len;
+ len = copy_path_element(newpath, path, size);
+
+ path += len;
+ newpath += len;
+ size -= len;
+ if (size <= 1)
+ break;
+ }
+
+ /* remove duplicated '/' */
+ while (*path == '/') path++;
+ }
+
+ /* When newpath is empty, set "." */
+ if (newpath == p) {
+ strcpy(newpath, ".");
+ newpath++;
+ }
+
+ return newpath - p; /* string length */
+}
+
void
init_header(name, v_stat, hdr)
char *name;
hdr->original_size = v_stat->st_size;
hdr->attribute = GENERIC_ATTRIBUTE;
hdr->header_level = header_level;
- strcpy(hdr->name, name);
- len = strlen(name);
+
+ len = canon_path(hdr->name, 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. */
+#ifdef __DJGPP__
+ hdr->unix_mode = 0;
+ if (S_ISREG(v_stat->st_mode))
+ hdr->unix_mode = hdr->unix_mode | UNIX_FILE_REGULAR;
+ if (S_ISDIR(v_stat->st_mode))
+ hdr->unix_mode = hdr->unix_mode | UNIX_FILE_DIRECTORY;
+ if (S_ISLNK(v_stat->st_mode))
+ hdr->unix_mode = hdr->unix_mode | UNIX_FILE_SYMLINK;
+ if (v_stat->st_mode & S_IRUSR)
+ hdr->unix_mode = hdr->unix_mode | UNIX_OWNER_READ_PERM;
+ if (v_stat->st_mode & S_IRGRP)
+ hdr->unix_mode = hdr->unix_mode | UNIX_GROUP_READ_PERM;
+ if (v_stat->st_mode & S_IROTH)
+ hdr->unix_mode = hdr->unix_mode | UNIX_OTHER_READ_PERM;
+ if (v_stat->st_mode & S_IWUSR)
+ hdr->unix_mode = hdr->unix_mode | UNIX_OWNER_WRITE_PERM;
+ if (v_stat->st_mode & S_IWGRP)
+ hdr->unix_mode = hdr->unix_mode | UNIX_GROUP_WRITE_PERM;
+ if (v_stat->st_mode & S_IWOTH)
+ hdr->unix_mode = hdr->unix_mode | UNIX_OTHER_WRITE_PERM;
+ if (v_stat->st_mode & S_IXUSR)
+ hdr->unix_mode = hdr->unix_mode | UNIX_OWNER_EXEC_PERM;
+ if (v_stat->st_mode & S_IXGRP)
+ hdr->unix_mode = hdr->unix_mode | UNIX_GROUP_EXEC_PERM;
+ if (v_stat->st_mode & S_IXOTH)
+ hdr->unix_mode = hdr->unix_mode | UNIX_OTHER_EXEC_PERM;
+ if (v_stat->st_mode & S_ISUID)
+ hdr->unix_mode = hdr->unix_mode | UNIX_SETUID;
+ if (v_stat->st_mode & S_ISGID)
+ hdr->unix_mode = hdr->unix_mode | UNIX_SETGID;
+#endif /* __DJGPP__ */
#else
hdr->unix_mode = v_stat->st_mode;
#endif
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 (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
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);
if (optional_system_kanji_code)
system_kanji_code = optional_system_kanji_code;
- if (generic_format)
+ if (generic_format && convertcase)
filename_case = TO_UPPER;
- if (hdr->header_level == HEADER_LEVEL0) {
+ if (hdr->header_level == 0) {
archive_delim = "\\";
}
}
/*
- * SJIS <-> EUC ÊÑ´¹´Ø¿ô
- * ¡ÖÆüËܸì¾ðÊó½èÍý¡× ¥½¥Õ¥È¥Ð¥ó¥¯(³ô)
- * ¤è¤êÈ´¿è(by Koji Arai)
+ * SJIS <-> EUC 変換関数
+ * 「日本語情報処理」 ソフトバンク(株)
+ * より抜粋(by Koji Arai)
*/
void
euc2sjis(int *p1, int *p2)
*p1 |= 0x80;
*p2 |= 0x80;
}
+
+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 */