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;
name_length = strlen(hdr->name);
while (header_size) {
+#if DUMP_HEADER
+ if (verbose_listing && verbose > 1)
+ printf("---\n");
+#endif
setup_get(data);
if (sizeof(data) < header_size) {
error("header size (%ld) too large.", header_size);
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;
}
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->name[i] = '\0';
/* defaults for other type */
- hdr->unix_mode = S_IFREG | UNIX_RW_RW_RW;
+ hdr->unix_mode = UNIX_FILE_REGULAR | UNIX_RW_RW_RW;
hdr->unix_gid = 0;
hdr->unix_uid = 0;
}
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();
hdr->name[i] = '\0';
/* defaults for other type */
- hdr->unix_mode = S_IFREG | UNIX_RW_RW_RW;
+ hdr->unix_mode = UNIX_FILE_REGULAR | UNIX_RW_RW_RW;
hdr->unix_gid = 0;
hdr->unix_uid = 0;
}
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();
/* defaults for other type */
- hdr->unix_mode = S_IFREG | UNIX_RW_RW_RW;
+ hdr->unix_mode = UNIX_FILE_REGULAR | UNIX_RW_RW_RW;
hdr->unix_gid = 0;
hdr->unix_uid = 0;
}
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();
/* defaults for other type */
- hdr->unix_mode = S_IFREG | UNIX_RW_RW_RW;
+ hdr->unix_mode = UNIX_FILE_REGULAR | UNIX_RW_RW_RW;
hdr->unix_gid = 0;
hdr->unix_uid = 0;
/* 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;
}
system_kanji_code,
archive_delim, system_delim, filename_case);
- if (S_ISLNK(hdr->unix_mode)) {
+ if ((hdr->unix_mode & UNIX_FILE_SYMLINK) == UNIX_FILE_SYMLINK) {
char *p;
/* split symbolic link */
p = strchr(hdr->name, '|');
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;
+}
+
+/* remove leading "xxx/../" and "./" */
+static int
+remove_dots(char *newpath, char *path, size_t size)
+{
+ int len;
+ 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;
+ }
+ }
+
+ /* 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;
- len = str_safe_copy(hdr->name,
- remove_leading_dots(name),
- sizeof(hdr->name));
+
+ len = remove_dots(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
}
}
-#if defined(S_IFLNK) && !defined(__DJGPP__)
+#ifdef S_IFLNK
if (is_symlink(v_stat)) {
memcpy(hdr->method, LZHDIRS_METHOD, METHOD_TYPE_STORAGE);
hdr->attribute = GENERIC_DIRECTORY_ATTRIBUTE;
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) {
archive_delim = "\\";
}
- if (S_ISLNK(hdr->unix_mode)) {
+ if ((hdr->unix_mode & UNIX_FILE_SYMLINK) == UNIX_FILE_SYMLINK) {
char *p;
p = strchr(hdr->name, '|');
if (p) {