X-Git-Url: http://git.osdn.net/view?p=lha%2Flha.git;a=blobdiff_plain;f=src%2Fheader.c;h=035d5d26a027fe308d3dacd4693ec192c519a4cb;hp=3f36c83ea0378074bfaeed27b09e84e3637ee5c5;hb=82efba6a7e8997694bc94370a1d7aae808308e9a;hpb=578687bcf31bdb4c712283c78198d47e11aa7c44 diff --git a/src/header.c b/src/header.c index 3f36c83..035d5d2 100644 --- a/src/header.c +++ b/src/header.c @@ -27,17 +27,16 @@ #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)) @@ -57,16 +56,38 @@ int default_system_kanji_code = NONE; 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() @@ -75,7 +96,7 @@ 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); @@ -92,12 +113,16 @@ dump_skip_bytes(len) 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 @@ -111,8 +136,8 @@ get_word() 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) @@ -139,10 +164,10 @@ get_longword() 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) @@ -152,8 +177,7 @@ get_longword() } static void -put_longword(v) - long v; +put_longword(long v) { put_byte(v); put_byte(v >> 8); @@ -161,6 +185,50 @@ put_longword(v) 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) char *buf; @@ -171,9 +239,13 @@ 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])) @@ -186,6 +258,10 @@ get_bytes(buf, len, size) 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 @@ -234,11 +310,34 @@ convert_filename(name, len, size, 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; @@ -261,21 +360,6 @@ convert_filename(name, len, size, } #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 && @@ -424,7 +508,8 @@ wintime_to_unix_stamp() { #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 = (unsigned long)get_longword(); t |= (uint64_t)(unsigned long)get_longword() << 32; @@ -498,7 +583,11 @@ get_extended_header(fp, hdr, header_size, hcrc) 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); @@ -512,6 +601,9 @@ get_extended_header(fp, hdr, header_size, hcrc) 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. */ @@ -519,21 +611,33 @@ get_extended_header(fp, hdr, header_size, hcrc) 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 */ @@ -548,26 +652,55 @@ get_extended_header(fp, hdr, header_size, hcrc) 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; @@ -614,8 +747,8 @@ get_extended_header(fp, hdr, header_size, hcrc) 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; } @@ -687,6 +820,7 @@ get_header_level0(fp, hdr, data) char *data; { size_t header_size; + ssize_t remain_size; ssize_t extend_size; int checksum; int name_length; @@ -696,8 +830,14 @@ get_header_level0(fp, hdr, data) 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 */ } @@ -708,8 +848,8 @@ get_header_level0(fp, hdr, data) } 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(); @@ -731,7 +871,7 @@ get_header_level0(fp, hdr, data) hdr->has_crc = FALSE; return TRUE; - } + } error("Unkonwn header (lha file?)"); exit(1); @@ -803,6 +943,7 @@ get_header_level1(fp, hdr, data) char *data; { size_t header_size; + ssize_t remain_size; ssize_t extend_size; int checksum; int name_length; @@ -812,8 +953,14 @@ get_header_level1(fp, hdr, data) 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 */ } @@ -824,8 +971,8 @@ get_header_level1(fp, hdr, data) } 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(); @@ -897,6 +1044,7 @@ get_header_level2(fp, hdr, data) char *data; { size_t header_size; + ssize_t remain_size; ssize_t extend_size; int padding; unsigned int hcrc; @@ -904,6 +1052,13 @@ get_header_level2(fp, hdr, data) 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 ?)"); @@ -911,8 +1066,8 @@ get_header_level2(fp, hdr, data) } 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(); @@ -935,7 +1090,12 @@ get_header_level2(fp, hdr, data) 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) @@ -978,6 +1138,7 @@ get_header_level3(fp, hdr, data) char *data; { size_t header_size; + ssize_t remain_size; ssize_t extend_size; int padding; unsigned int hcrc; @@ -991,8 +1152,8 @@ get_header_level3(fp, hdr, data) } 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(); @@ -1006,6 +1167,11 @@ get_header_level3(fp, hdr, data) 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); @@ -1015,9 +1181,12 @@ get_header_level3(fp, hdr, data) 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"); @@ -1042,7 +1211,7 @@ get_header(fp, hdr) 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 */ @@ -1079,7 +1248,7 @@ get_header(fp, hdr) /* 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: @@ -1097,7 +1266,7 @@ get_header(fp, hdr) break; default: - filename_case = noconvertcase ? NONE : TO_LOWER; + filename_case = convertcase ? TO_LOWER : NONE; break; } @@ -1126,7 +1295,7 @@ get_header(fp, hdr) /* hdr->name is symbolic link name */ /* hdr->realname is real name */ *p = 0; - strcpy(hdr->realname, p+1); + strcpy(hdr->realname, p+1); /* ok */ } else error("unknown symlink name \"%s\"", hdr->name); @@ -1147,9 +1316,11 @@ seek_lha_header(fp) 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) @@ -1175,6 +1346,107 @@ seek_lha_header(fp) 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; @@ -1193,14 +1465,46 @@ init_header(name, v_stat, hdr) 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 @@ -1236,8 +1540,13 @@ init_header(name, v_stat, hdr) 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 @@ -1515,11 +1824,11 @@ write_header_level2(data, hdr, pathname) 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); @@ -1548,7 +1857,7 @@ write_header(fp, hdr) 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 == 0) { @@ -1778,9 +2087,9 @@ utf8_to_sjis(char *dst, const char *src, size_t dstsize) } /* - * SJIS <-> EUC ÊÑ´¹´Ø¿ô - * ¡ÖÆüËܸì¾ðÊó½èÍý¡× ¥½¥Õ¥È¥Ð¥ó¥¯(³ô) - * ¤è¤êÈ´¿è(by Koji Arai) + * SJIS <-> EUC 変換関数 + * 「日本語情報処理」 ソフトバンク(æ ª) + * より抜粋(by Koji Arai) */ void euc2sjis(int *p1, int *p2)