1 /* ------------------------------------------------------------------------ */
3 /* header.c -- header manipulate functions */
5 /* Modified Nobutaka Watazaki */
7 /* Original Y.Tagawa */
8 /* modified 1991.12.16 M.Oki */
9 /* Ver. 1.10 Symbolic Link added 1993.10.01 N.Watazaki */
10 /* Ver. 1.13b Symbolic Link Bug Fix 1994.08.22 N.Watazaki */
11 /* Ver. 1.14 Source All chagned 1995.01.14 N.Watazaki */
12 /* Ver. 1.14i bug fixed 2000.10.06 t.okamoto */
13 /* Ver. 1.14i Contributed UTF-8 convertion for Mac OS X */
14 /* 2002.06.29 Hiroto Sakai */
15 /* Ver. 1.14i autoconfiscated & rewritten 2003.02.23 Koji Arai */
16 /* ------------------------------------------------------------------------ */
19 #define DUMP_HEADER 1 /* for debugging */
21 #if !STRCHR_8BIT_CLEAN
22 /* should use 8 bit clean version */
25 #define strchr xstrchr
26 #define strrchr xstrrchr
30 #define GET_BYTE() (*get_ptr++ & 0xff)
33 static char *start_ptr;
34 #define setup_get(PTR) (start_ptr = get_ptr = (PTR))
35 #define get_byte() dump_get_byte()
36 #define skip_bytes(len) dump_skip_bytes(len)
38 #define setup_get(PTR) (get_ptr = (PTR))
39 #define get_byte() GET_BYTE()
40 #define skip_bytes(len) (get_ptr += (len))
42 #define put_ptr get_ptr
43 #define setup_put(PTR) (put_ptr = (PTR))
44 #define put_byte(c) (*put_ptr++ = (char)(c))
46 int optional_archive_kanji_code = NONE;
47 int optional_system_kanji_code = NONE;
48 char *optional_archive_delim = NULL;
49 char *optional_system_delim = NULL;
50 int optional_filename_case = NONE;
52 #ifdef MULTIBYTE_FILENAME
53 int default_system_kanji_code = MULTIBYTE_FILENAME;
55 int default_system_kanji_code = NONE;
65 while (len--) sum += *(unsigned char*)p++;
76 if (verbose_listing && verbose > 1)
77 printf("%02d %2d: ", get_ptr - start_ptr, 1);
79 if (verbose_listing && verbose > 1) {
81 printf("%d(0x%02x) '%c'\n", c, c, c);
83 printf("%d(0x%02x)\n", c, c);
93 if (verbose_listing && verbose > 1) {
94 printf("%02d %2d: ", get_ptr - start_ptr, len);
96 printf("0x%02x ", GET_BYTE());
97 printf("... ignored\n");
111 if (verbose_listing && verbose > 1)
112 printf("%02d %2d: ", get_ptr - start_ptr, 2);
118 if (verbose_listing && verbose > 1)
119 printf("%d(0x%04x)\n", w, w);
139 if (verbose_listing && verbose > 1)
140 printf("%02d %2d: ", get_ptr - start_ptr, 4);
146 l = (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
148 if (verbose_listing && verbose > 1)
149 printf("%ld(0x%08lx)\n", l, l);
167 uint64_t b0, b1, b2, b3, b4, b5, b6, b7;
171 if (verbose_listing && verbose > 1)
172 printf("%02d %2d: ", get_ptr - start_ptr, 4);
183 l = (b7 << 24) + (b6 << 16) + (b5 << 8) + b4;
185 l |= (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
187 if (verbose_listing && verbose > 1)
188 printf("%lld(%#016llx)\n", l, l);
194 put_longlongword(uint64_t v)
208 get_bytes(buf, len, size)
215 if (verbose_listing && verbose > 1)
216 printf("%02d %2d: \"", get_ptr - start_ptr, len);
218 for (i = 0; i < len; i++) {
219 if (i < size) buf[i] = get_ptr[i];
221 if (verbose_listing && verbose > 1) {
223 printf("%c", buf[i]);
225 printf("\\x%02x", (unsigned char)buf[i]);
229 if (verbose_listing && verbose > 1)
232 for (i = 0; i < len && i < size; i++)
246 for (i = 0; i < len; i++)
250 /* added by Koji Arai */
252 convert_filename(name, len, size,
254 from_delim, to_delim,
257 int len; /* length of name */
258 int size; /* size of name buffer */
259 int from_code, to_code, case_to;
260 char *from_delim, *to_delim;
264 #ifdef MULTIBYTE_FILENAME
265 char tmp[FILENAME_LENGTH];
266 int to_code_save = NONE;
268 if (from_code == CODE_CAP) {
269 len = cap_to_sjis(tmp, name, sizeof(tmp));
270 strncpy(name, tmp, size);
273 from_code = CODE_SJIS;
276 if (to_code == CODE_CAP) {
277 to_code_save = CODE_CAP;
281 if (from_code == CODE_SJIS && to_code == CODE_UTF8) {
282 for (i = 0; i < len; i++) {
283 if (SJIS_FIRST_P(name[i]) && SJIS_SECOND_P(name[i+1]))
286 /* FIXME: provisionally fix for the Mac OS CoreFoundation */
287 if (strchr(from_delim, name[i]))
291 sjis_to_utf8(tmp, name, sizeof(tmp));
292 strncpy(name, tmp, size);
295 for (i = 0; i < len; i++)
296 if (name[i] == '/') name[i] = LHA_PATHSEP;
297 from_code = CODE_UTF8;
299 else if (from_code == CODE_UTF8 && to_code == CODE_SJIS) {
300 for (i = 0; i < len; i++)
301 /* FIXME: provisionally fix for the Mac OS CoreFoundation */
302 if ((unsigned char)name[i] == LHA_PATHSEP) name[i] = '/';
303 utf8_to_sjis(tmp, name, sizeof(tmp));
304 strncpy(name, tmp, size);
307 for (i = 0; i < len; i++)
308 if (name[i] == '/') name[i] = LHA_PATHSEP;
309 from_code = CODE_SJIS;
313 /* special case: if `name' has small lettter, not convert case. */
314 if (from_code == CODE_SJIS && case_to == TO_LOWER) {
315 for (i = 0; i < len; i++) {
316 #ifdef MULTIBYTE_FILENAME
317 if (SJIS_FIRST_P(name[i]) && SJIS_SECOND_P(name[i+1]))
321 if (islower(name[i])) {
328 for (i = 0; i < len; i ++) {
329 #ifdef MULTIBYTE_FILENAME
330 if (from_code == CODE_EUC &&
331 (unsigned char)name[i] == 0x8e) {
332 if (to_code != CODE_SJIS) {
338 memmove(name + i, name + i + 1, len - i);
342 if (from_code == CODE_SJIS && X0201_KANA_P(name[i])) {
343 if (to_code != CODE_EUC) {
347 if (len == size - 1) /* check overflow */
349 memmove(name+i+1, name+i, len-i);
355 if (from_code == CODE_EUC && (name[i] & 0x80) && (name[i+1] & 0x80)) {
357 if (to_code != CODE_SJIS) {
362 c1 = (unsigned char)name[i];
363 c2 = (unsigned char)name[i+1];
370 if (from_code == CODE_SJIS &&
371 SJIS_FIRST_P(name[i]) &&
372 SJIS_SECOND_P(name[i+1])) {
375 if (to_code != CODE_EUC) {
380 c1 = (unsigned char)name[i];
381 c2 = (unsigned char)name[i+1];
388 #endif /* MULTIBYTE_FILENAME */
392 /* transpose from_delim to to_delim */
394 if ((ptr = strchr(from_delim, name[i])) != NULL) {
395 name[i] = to_delim[ptr - from_delim];
400 if (case_to == TO_UPPER && islower(name[i])) {
401 name[i] = toupper(name[i]);
404 if (case_to == TO_LOWER && isupper(name[i])) {
405 name[i] = tolower(name[i]);
410 #ifdef MULTIBYTE_FILENAME
411 if (to_code_save == CODE_CAP) {
412 len = sjis_to_cap(tmp, name, sizeof(tmp));
413 strncpy(name, tmp, size);
417 #endif /* MULTIBYTE_FILENAME */
421 * Generic (MS-DOS style) time stamp format (localtime):
423 * 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
424 * |<---- year-1980 --->|<- month ->|<--- day ---->|
426 * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
427 * |<--- hour --->|<---- minute --->|<- second/2 ->|
432 generic_to_unix_stamp(t)
437 #define subbits(n, off, len) (((n) >> (off)) & ((1 << (len))-1))
439 tm.tm_sec = subbits(t, 0, 5) * 2;
440 tm.tm_min = subbits(t, 5, 6);
441 tm.tm_hour = subbits(t, 11, 5);
442 tm.tm_mday = subbits(t, 16, 5);
443 tm.tm_mon = subbits(t, 21, 4) - 1;
444 tm.tm_year = subbits(t, 25, 7) + 80;
450 return timelocal(&tm);
455 unix_to_generic_stamp(t)
458 struct tm *tm = localtime(&t);
463 return ((long)(tm->tm_year << 25) +
465 (tm->tm_mday << 16) +
466 (tm->tm_hour << 11) +
472 wintime_to_unix_stamp()
476 uint64_t epoch = ((uint64_t)0x019db1de << 32) + 0xd53e8000;
477 /* 0x019db1ded53e8000ULL: 1970-01-01 00:00:00 (UTC) */
479 t = (unsigned long)get_longword();
480 t |= (uint64_t)(unsigned long)get_longword() << 32;
481 t = (t - epoch) / 10000000;
485 unsigned long t, q, x;
486 unsigned long wintime[8];
487 unsigned long epoch[8] = {0x01,0x9d,0xb1,0xde, 0xd5,0x3e,0x80,0x00};
488 /* 1970-01-01 00:00:00 (UTC) */
489 /* wintime -= epoch */
491 for (i = 7; i >= 0; i--) {
492 wintime[i] = (unsigned)get_byte() - epoch[i] - borrow;
493 borrow = (wintime[i] > 0xff) ? 1 : 0;
497 /* q = wintime / 10000000 */
499 x = 10000000; /* x: 24bit */
500 for (i = 0; i < 8; i++) {
501 t = (t << 8) + wintime[i]; /* 24bit + 8bit. t must be 32bit variable */
502 q <<= 8; /* q must be 32bit (time_t) */
514 * --------------------------------
516 * 2 or 4 next-header size [*1]
517 * --------------------------------------
518 * ext header: 1 ext-type ^
519 * ? contents | [*1] next-header size
520 * 2 or 4 next-header size v
521 * --------------------------------------
523 * on level 1, 2 header:
524 * size field is 2 bytes
526 * size field is 4 bytes
530 get_extended_header(fp, hdr, header_size, hcrc)
536 char data[LZHEADER_STORAGE];
538 char dirname[FILENAME_LENGTH];
541 ssize_t whole_size = header_size;
543 int n = 1 + hdr->size_field_length; /* `ext-type' + `next-header size' */
545 if (hdr->header_level == 0)
548 name_length = strlen(hdr->name);
550 while (header_size) {
552 if (verbose_listing && verbose > 1)
556 if (sizeof(data) < header_size) {
557 error("header size (%ld) too large.", header_size);
561 if (fread(data, header_size, 1, fp) == 0) {
562 error("Invalid header (LHa file ?)");
566 ext_type = get_byte();
570 if (verbose_listing && verbose > 1) printf(" < header crc >\n");
572 /* header crc (CRC-16) */
573 hdr->header_crc = get_word();
574 /* clear buffer for CRC calculation. */
575 data[1] = data[2] = 0;
576 skip_bytes(header_size - n - 2);
580 if (verbose_listing && verbose > 1) printf(" < filename >\n");
584 get_bytes(hdr->name, header_size-n, sizeof(hdr->name)-1);
585 hdr->name[name_length] = 0;
589 if (verbose_listing && verbose > 1) printf(" < directory >\n");
592 dir_length = get_bytes(dirname, header_size-n, sizeof(dirname)-1);
593 dirname[dir_length] = 0;
597 if (verbose_listing && verbose > 1) printf(" < MS-DOS attribute >\n");
599 /* MS-DOS attribute */
600 hdr->attribute = get_word();
604 if (verbose_listing && verbose > 1) printf(" < Windows time stamp (FILETIME) >\n");
606 /* Windows time stamp (FILETIME structure) */
607 /* it is time in 100 nano seconds since 1601-01-01 00:00:00 */
609 skip_bytes(8); /* create time is ignored */
611 /* set last modified time */
612 if (hdr->header_level >= 2)
613 skip_bytes(8); /* time_t has been already set */
615 hdr->unix_last_modified_stamp = wintime_to_unix_stamp();
616 if (file_time_stamp < hdr->unix_last_modified_stamp) {
617 file_time_stamp = hdr->unix_last_modified_stamp;
620 skip_bytes(8); /* last access time is ignored */
625 if (verbose_listing && verbose > 1) printf(" < 64bits file size header >\n");
628 /* 64bits file size header (UNLHA32 extension) */
629 hdr->packed_size = get_longlongword();
630 hdr->original_size = get_longlongword();
639 if (verbose_listing && verbose > 1) printf(" < UNIX permission >\n");
641 /* UNIX permission */
642 hdr->unix_mode = get_word();
646 if (verbose_listing && verbose > 1) printf(" < UNIX gid and uid >\n");
648 /* UNIX gid and uid */
649 hdr->unix_gid = get_word();
650 hdr->unix_uid = get_word();
654 if (verbose_listing && verbose > 1) printf(" < UNIX group name >\n");
656 /* UNIX group name */
657 i = get_bytes(hdr->group, header_size-n, sizeof(hdr->group)-1);
658 hdr->group[i] = '\0';
662 if (verbose_listing && verbose > 1) printf(" < UNIX user name >\n");
665 i = get_bytes(hdr->user, header_size-n, sizeof(hdr->user)-1);
670 if (verbose_listing && verbose > 1) printf(" < UNIX last modifed time (time_t) >\n");
672 /* UNIX last modified time */
673 hdr->unix_last_modified_stamp = (time_t) get_longword();
674 if (file_time_stamp < hdr->unix_last_modified_stamp) {
675 file_time_stamp = hdr->unix_last_modified_stamp;
680 /* 0x39: multi-disk header
681 0x3f: uncompressed comment
682 0x42: 64bit large file size
683 0x48-0x4f(?): reserved for authenticity verification
685 0x7e: extended attribute - platform information
686 0x7f: extended attribute - permission, owner-id and timestamp
688 0xc4: compressed comment (dict size: 4096)
689 0xc5: compressed comment (dict size: 8192)
690 0xc6: compressed comment (dict size: 16384)
691 0xc7: compressed comment (dict size: 32768)
692 0xc8: compressed comment (dict size: 65536)
693 0xd0-0xdf(?): operating systemm specific information
694 0xfc: encapsulation (another opinion)
695 0xfe: extended attribute - platform information(another opinion)
696 0xff: extended attribute - permission, owner-id and timestamp
697 (level 3 on UNLHA32) */
699 warning("unknown extended header 0x%02x", ext_type);
700 skip_bytes(header_size - n);
705 *hcrc = calccrc(*hcrc, data, header_size);
707 if (hdr->size_field_length == 2)
708 whole_size += header_size = get_word();
710 whole_size += header_size = get_longword();
713 /* concatenate dirname and filename */
715 if (name_length + dir_length >= sizeof(hdr->name)) {
716 warning("the length of pathname \"%s%s\" is too long.",
718 name_length = sizeof(hdr->name) - dir_length - 1;
719 hdr->name[name_length] = 0;
721 strcat(dirname, hdr->name); /* ok */
722 strcpy(hdr->name, dirname); /* ok */
723 name_length += dir_length;
729 #define I_HEADER_SIZE 0 /* level 0,1,2 */
730 #define I_HEADER_CHECKSUM 1 /* level 0,1 */
731 #define I_METHOD 2 /* level 0,1,2,3 */
732 #define I_PACKED_SIZE 7 /* level 0,1,2,3 */
733 #define I_ATTRIBUTE 19 /* level 0,1,2,3 */
734 #define I_HEADER_LEVEL 20 /* level 0,1,2,3 */
736 #define COMMON_HEADER_SIZE 21 /* size of common part */
738 #define I_GENERIC_HEADER_SIZE 24 /* + name_length */
739 #define I_LEVEL0_HEADER_SIZE 36 /* + name_length (unix extended) */
740 #define I_LEVEL1_HEADER_SIZE 27 /* + name_length */
741 #define I_LEVEL2_HEADER_SIZE 26 /* + padding */
742 #define I_LEVEL3_HEADER_SIZE 32
748 * offset size field name
749 * ----------------------------------
750 * 0 1 header size [*1]
752 * ---------------------------------------
754 * 7 4 packed size [*2] |
755 * 11 4 original size |
758 * 19 1 attribute | [*1] header size (X+Y+22)
759 * 20 1 level (0x00 fixed) |
762 * X +22 2 file crc (CRC-16) |
763 * X +24 Y ext-header(old style) v
764 * -------------------------------------------------
766 * : | [*2] packed size
768 * -------------------------------------------------
770 * ext-header(old style)
784 * bit6 archive bit (need to backup)
788 get_header_level0(fp, hdr, data)
799 hdr->size_field_length = 2; /* in bytes */
800 hdr->header_size = header_size = get_byte();
801 checksum = get_byte();
803 if (fread(data + COMMON_HEADER_SIZE,
804 header_size + 2 - COMMON_HEADER_SIZE, 1, fp) == 0) {
805 error("Invalid header (LHarc file ?)");
806 return FALSE; /* finish */
809 if (calc_sum(data + I_METHOD, header_size) != checksum) {
810 error("Checksum error (LHarc file?)");
814 get_bytes(hdr->method, 5, sizeof(hdr->method));
815 hdr->packed_size = (unsigned long)get_longword();
816 hdr->original_size = (unsigned long)get_longword();
817 hdr->unix_last_modified_stamp = generic_to_unix_stamp(get_longword());
818 if (file_time_stamp < hdr->unix_last_modified_stamp) {
819 file_time_stamp = hdr->unix_last_modified_stamp;
821 hdr->attribute = get_byte(); /* MS-DOS attribute */
822 hdr->header_level = get_byte();
823 name_length = get_byte();
824 i = get_bytes(hdr->name, name_length, sizeof(hdr->name)-1);
827 /* defaults for other type */
828 hdr->unix_mode = UNIX_FILE_REGULAR | UNIX_RW_RW_RW;
832 extend_size = header_size+2 - name_length - 24;
834 if (extend_size < 0) {
835 if (extend_size == -2) {
836 /* CRC field is not given */
837 hdr->extend_type = EXTEND_GENERIC;
838 hdr->has_crc = FALSE;
843 error("Unkonwn header (lha file?)");
848 hdr->crc = get_word();
850 if (extend_size == 0)
853 hdr->extend_type = get_byte();
856 if (hdr->extend_type == EXTEND_UNIX) {
857 if (extend_size >= 11) {
858 hdr->minor_version = get_byte();
859 hdr->unix_last_modified_stamp = (time_t) get_longword();
860 if (file_time_stamp < hdr->unix_last_modified_stamp) {
861 file_time_stamp = hdr->unix_last_modified_stamp;
863 hdr->unix_mode = get_word();
864 hdr->unix_uid = get_word();
865 hdr->unix_gid = get_word();
868 hdr->extend_type = EXTEND_GENERIC;
872 skip_bytes(extend_size);
874 hdr->header_size += 2;
882 * offset size field name
883 * -----------------------------------
884 * 0 1 header size [*1]
886 * -------------------------------------
888 * 7 4 skip size [*2] |
889 * 11 4 original size |
892 * 19 1 attribute (0x20 fixed) | [*1] header size (X+Y+25)
893 * 20 1 level (0x01 fixed) |
896 * X+ 22 2 file crc (CRC-16) |
899 * X+Y+25 2 next-header size v
900 * -------------------------------------------------
901 * X+Y+27 Z ext-header ^
903 * ----------------------------------- | [*2] skip size
906 * -------------------------------------------------
910 get_header_level1(fp, hdr, data)
921 hdr->size_field_length = 2; /* in bytes */
922 hdr->header_size = header_size = get_byte();
923 checksum = get_byte();
925 if (fread(data + COMMON_HEADER_SIZE,
926 header_size + 2 - COMMON_HEADER_SIZE, 1, fp) == 0) {
927 error("Invalid header (LHarc file ?)");
928 return FALSE; /* finish */
931 if (calc_sum(data + I_METHOD, header_size) != checksum) {
932 error("Checksum error (LHarc file?)");
936 get_bytes(hdr->method, 5, sizeof(hdr->method));
937 hdr->packed_size = (unsigned long)get_longword(); /* skip size */
938 hdr->original_size = (unsigned long)get_longword();
939 hdr->unix_last_modified_stamp = generic_to_unix_stamp(get_longword());
940 if (file_time_stamp < hdr->unix_last_modified_stamp) {
941 file_time_stamp = hdr->unix_last_modified_stamp;
943 hdr->attribute = get_byte(); /* 0x20 fixed */
944 hdr->header_level = get_byte();
946 name_length = get_byte();
947 i = get_bytes(hdr->name, name_length, sizeof(hdr->name)-1);
950 /* defaults for other type */
951 hdr->unix_mode = UNIX_FILE_REGULAR | UNIX_RW_RW_RW;
956 hdr->crc = get_word();
957 hdr->extend_type = get_byte();
959 dummy = header_size+2 - name_length - I_LEVEL1_HEADER_SIZE;
961 skip_bytes(dummy); /* skip old style extend header */
963 extend_size = get_word();
964 extend_size = get_extended_header(fp, hdr, extend_size, 0);
965 if (extend_size == -1)
968 /* On level 1 header, size fields should be adjusted. */
969 /* the `packed_size' field contains the extended header size. */
970 /* the `header_size' field does not. */
971 hdr->packed_size -= extend_size;
972 hdr->header_size += extend_size + 2;
981 * offset size field name
982 * --------------------------------------------------
983 * 0 2 total header size [*1] ^
984 * ----------------------- |
986 * 7 4 packed size [*2] |
987 * 11 4 original size |
989 * 19 1 RESERVED (0x20 fixed) | [*1] total header size
990 * 20 1 level (0x02 fixed) | (X+26+(1))
991 * 21 2 file crc (CRC-16) |
993 * 24 2 next-header size |
994 * ----------------------------------- |
997 * ----------------------------------- |
998 * X +26 (1) padding v
999 * -------------------------------------------------
1001 * : | [*2] packed size
1003 * -------------------------------------------------
1007 get_header_level2(fp, hdr, data)
1013 ssize_t extend_size;
1017 hdr->size_field_length = 2; /* in bytes */
1018 hdr->header_size = header_size = get_word();
1020 if (fread(data + COMMON_HEADER_SIZE,
1021 I_LEVEL2_HEADER_SIZE - COMMON_HEADER_SIZE, 1, fp) == 0) {
1022 error("Invalid header (LHarc file ?)");
1023 return FALSE; /* finish */
1026 get_bytes(hdr->method, 5, sizeof(hdr->method));
1027 hdr->packed_size = (unsigned long)get_longword();
1028 hdr->original_size = (unsigned long)get_longword();
1029 hdr->unix_last_modified_stamp = get_longword();
1030 if (file_time_stamp < hdr->unix_last_modified_stamp) {
1031 file_time_stamp = hdr->unix_last_modified_stamp;
1033 hdr->attribute = get_byte(); /* reserved */
1034 hdr->header_level = get_byte();
1036 /* defaults for other type */
1037 hdr->unix_mode = UNIX_FILE_REGULAR | UNIX_RW_RW_RW;
1041 hdr->has_crc = TRUE;
1042 hdr->crc = get_word();
1043 hdr->extend_type = get_byte();
1044 extend_size = get_word();
1046 INITIALIZE_CRC(hcrc);
1047 hcrc = calccrc(hcrc, data, get_ptr - data);
1049 extend_size = get_extended_header(fp, hdr, extend_size, &hcrc);
1050 if (extend_size == -1)
1053 padding = header_size - I_LEVEL2_HEADER_SIZE - extend_size;
1054 while (padding--) /* padding should be 0 or 1 */
1055 hcrc = UPDATE_CRC(hcrc, fgetc(fp));
1057 if (hdr->header_crc != hcrc)
1058 error("header CRC error");
1067 * offset size field name
1068 * --------------------------------------------------
1069 * 0 2 size field length (4 fixed) ^
1071 * 7 4 packed size [*2] |
1072 * 11 4 original size |
1074 * 19 1 RESERVED (0x20 fixed) | [*1] total header size
1075 * 20 1 level (0x03 fixed) | (X+32)
1076 * 21 2 file crc (CRC-16) |
1078 * 24 4 total header size [*1] |
1079 * 28 4 next-header size |
1080 * ----------------------------------- |
1083 * -------------------------------------------------
1085 * : | [*2] packed size
1087 * -------------------------------------------------
1091 get_header_level3(fp, hdr, data)
1097 ssize_t extend_size;
1101 hdr->size_field_length = get_word();
1103 if (fread(data + COMMON_HEADER_SIZE,
1104 I_LEVEL3_HEADER_SIZE - COMMON_HEADER_SIZE, 1, fp) == 0) {
1105 error("Invalid header (LHarc file ?)");
1106 return FALSE; /* finish */
1109 get_bytes(hdr->method, 5, sizeof(hdr->method));
1110 hdr->packed_size = (unsigned long)get_longword();
1111 hdr->original_size = (unsigned long)get_longword();
1112 hdr->unix_last_modified_stamp = get_longword();
1113 if (file_time_stamp < hdr->unix_last_modified_stamp) {
1114 file_time_stamp = hdr->unix_last_modified_stamp;
1116 hdr->attribute = get_byte(); /* reserved */
1117 hdr->header_level = get_byte();
1119 /* defaults for other type */
1120 hdr->unix_mode = UNIX_FILE_REGULAR | UNIX_RW_RW_RW;
1124 hdr->has_crc = TRUE;
1125 hdr->crc = get_word();
1126 hdr->extend_type = get_byte();
1127 hdr->header_size = header_size = get_longword();
1128 extend_size = get_longword();
1130 INITIALIZE_CRC(hcrc);
1131 hcrc = calccrc(hcrc, data, get_ptr - data);
1133 extend_size = get_extended_header(fp, hdr, extend_size, &hcrc);
1134 if (extend_size == -1)
1137 padding = header_size - I_LEVEL3_HEADER_SIZE - extend_size;
1138 while (padding--) /* padding should be 0 */
1139 hcrc = UPDATE_CRC(hcrc, fgetc(fp));
1141 if (hdr->header_crc != hcrc)
1142 error("header CRC error");
1152 char data[LZHEADER_STORAGE];
1154 int archive_kanji_code = CODE_SJIS;
1155 int system_kanji_code = default_system_kanji_code;
1156 char *archive_delim = "\377\\"; /* `\' is for level 0 header and
1158 char *system_delim = "//";
1159 int filename_case = NONE;
1162 memset(hdr, 0, sizeof(LzHeader));
1166 if ((end_mark = getc(fp)) == EOF || end_mark == 0) {
1167 return FALSE; /* finish */
1171 if (fread(data + 1, COMMON_HEADER_SIZE - 1, 1, fp) == 0) {
1172 error("Invalid header (LHarc file ?)");
1173 return FALSE; /* finish */
1176 switch (data[I_HEADER_LEVEL]) {
1178 if (get_header_level0(fp, hdr, data) == FALSE)
1182 if (get_header_level1(fp, hdr, data) == FALSE)
1186 if (get_header_level2(fp, hdr, data) == FALSE)
1190 if (get_header_level3(fp, hdr, data) == FALSE)
1194 error("Unknown level header (level %d)", data[I_HEADER_LEVEL]);
1198 /* filename conversion */
1199 switch (hdr->extend_type) {
1201 filename_case = convertcase ? TO_LOWER : NONE;
1208 filename_case = NONE;
1212 archive_delim = "\377/:\\";
1213 /* `\' is for level 0 header and broken archive. */
1214 system_delim = "/://";
1215 filename_case = NONE;
1219 filename_case = convertcase ? TO_LOWER : NONE;
1223 if (optional_archive_kanji_code)
1224 archive_kanji_code = optional_archive_kanji_code;
1225 if (optional_system_kanji_code)
1226 system_kanji_code = optional_system_kanji_code;
1227 if (optional_archive_delim)
1228 archive_delim = optional_archive_delim;
1229 if (optional_system_delim)
1230 system_delim = optional_system_delim;
1231 if (optional_filename_case)
1232 filename_case = optional_filename_case;
1234 /* kanji code and delimiter conversion */
1235 convert_filename(hdr->name, strlen(hdr->name), sizeof(hdr->name),
1238 archive_delim, system_delim, filename_case);
1240 if ((hdr->unix_mode & UNIX_FILE_SYMLINK) == UNIX_FILE_SYMLINK) {
1242 /* split symbolic link */
1243 p = strchr(hdr->name, '|');
1245 /* hdr->name is symbolic link name */
1246 /* hdr->realname is real name */
1248 strcpy(hdr->realname, p+1); /* ok */
1251 error("unknown symlink name \"%s\"", hdr->name);
1257 /* skip SFX header */
1262 unsigned char buffer[64 * 1024]; /* max seek size */
1266 n = fread(buffer, 1, sizeof(buffer), fp);
1268 for (p = buffer; p < buffer + n; p++) {
1269 if (! (p[I_METHOD]=='-' && p[I_METHOD+1]=='l' && p[I_METHOD+4]=='-'))
1271 /* found "-l??-" keyword (as METHOD type string) */
1273 /* level 0 or 1 header */
1274 if ((p[I_HEADER_LEVEL] == 0 || p[I_HEADER_LEVEL] == 1)
1275 && p[I_HEADER_SIZE] > 20
1276 && p[I_HEADER_CHECKSUM] == calc_sum(p+2, p[I_HEADER_SIZE])) {
1277 if (fseeko(fp, (p - buffer) - n, SEEK_CUR) == -1)
1278 fatal_error("cannot seek header");
1282 /* level 2 header */
1283 if (p[I_HEADER_LEVEL] == 2
1284 && p[I_HEADER_SIZE] >= 24
1285 && p[I_ATTRIBUTE] == 0x20) {
1286 if (fseeko(fp, (p - buffer) - n, SEEK_CUR) == -1)
1287 fatal_error("cannot seek header");
1292 if (fseeko(fp, -n, SEEK_CUR) == -1)
1293 fatal_error("cannot seek header");
1298 /* remove leading `xxxx/..' */
1300 remove_leading_dots(char *path)
1305 if (strcmp(first, "..") == 0) {
1306 warning("Removing leading `..' from member name.");
1307 return first+1; /* change to "." */
1310 if (strstr(first, "..") == 0)
1313 while (path && *path) {
1315 if (strcmp(path, "..") == 0)
1316 ptr = path = path+2;
1317 else if (strncmp(path, "../", 3) == 0)
1318 ptr = path = path+3;
1320 path = strchr(path, '/');
1322 if (path && *path == '/') {
1328 warning("Removing leading `%.*s' from member name.", ptr-first, first);
1336 copy_path_element(char *dst, const char *src, int size)
1340 if (size < 1) return 0;
1342 for (i = 0; i < size; i++) {
1346 if (dst[i] == '/') {
1360 remove leading "xxx/../"
1361 remove "./", "././", "././ ... ./"
1362 remove duplicated "/"
1365 canon_path(char *newpath, char *path, size_t size)
1369 path = remove_leading_dots(path);
1372 if (path[0] == '.' && path[1] == '/')
1376 len = copy_path_element(newpath, path, size);
1385 /* remove duplicated '/' */
1386 while (*path == '/') path++;
1389 /* When newpath is empty, set "." */
1391 strcpy(newpath, ".");
1395 return newpath - p; /* string length */
1399 init_header(name, v_stat, hdr)
1401 struct stat *v_stat;
1406 memset(hdr, 0, sizeof(LzHeader));
1408 /* the `method' member is rewrote by the encoding function.
1409 but need set for empty files */
1410 memcpy(hdr->method, LZHUFF0_METHOD, METHOD_TYPE_STORAGE);
1412 hdr->packed_size = 0;
1413 hdr->original_size = v_stat->st_size;
1414 hdr->attribute = GENERIC_ATTRIBUTE;
1415 hdr->header_level = header_level;
1417 len = canon_path(hdr->name, name, sizeof(hdr->name));
1420 hdr->extend_type = EXTEND_UNIX;
1421 hdr->unix_last_modified_stamp = v_stat->st_mtime;
1422 if (file_time_stamp < v_stat->st_mtime) { file_time_stamp = v_stat->st_mtime; }
1423 /* since 00:00:00 JAN.1.1970 */
1424 #ifdef NOT_COMPATIBLE_MODE
1425 /* Please need your modification in this space. */
1428 if (S_ISREG(v_stat->st_mode))
1429 hdr->unix_mode = hdr->unix_mode | UNIX_FILE_REGULAR;
1430 if (S_ISDIR(v_stat->st_mode))
1431 hdr->unix_mode = hdr->unix_mode | UNIX_FILE_DIRECTORY;
1432 if (S_ISLNK(v_stat->st_mode))
1433 hdr->unix_mode = hdr->unix_mode | UNIX_FILE_SYMLINK;
1434 if (v_stat->st_mode & S_IRUSR)
1435 hdr->unix_mode = hdr->unix_mode | UNIX_OWNER_READ_PERM;
1436 if (v_stat->st_mode & S_IRGRP)
1437 hdr->unix_mode = hdr->unix_mode | UNIX_GROUP_READ_PERM;
1438 if (v_stat->st_mode & S_IROTH)
1439 hdr->unix_mode = hdr->unix_mode | UNIX_OTHER_READ_PERM;
1440 if (v_stat->st_mode & S_IWUSR)
1441 hdr->unix_mode = hdr->unix_mode | UNIX_OWNER_WRITE_PERM;
1442 if (v_stat->st_mode & S_IWGRP)
1443 hdr->unix_mode = hdr->unix_mode | UNIX_GROUP_WRITE_PERM;
1444 if (v_stat->st_mode & S_IWOTH)
1445 hdr->unix_mode = hdr->unix_mode | UNIX_OTHER_WRITE_PERM;
1446 if (v_stat->st_mode & S_IXUSR)
1447 hdr->unix_mode = hdr->unix_mode | UNIX_OWNER_EXEC_PERM;
1448 if (v_stat->st_mode & S_IXGRP)
1449 hdr->unix_mode = hdr->unix_mode | UNIX_GROUP_EXEC_PERM;
1450 if (v_stat->st_mode & S_IXOTH)
1451 hdr->unix_mode = hdr->unix_mode | UNIX_OTHER_EXEC_PERM;
1452 if (v_stat->st_mode & S_ISUID)
1453 hdr->unix_mode = hdr->unix_mode | UNIX_SETUID;
1454 if (v_stat->st_mode & S_ISGID)
1455 hdr->unix_mode = hdr->unix_mode | UNIX_SETGID;
1456 #endif /* __DJGPP__ */
1458 hdr->unix_mode = v_stat->st_mode;
1461 hdr->unix_uid = v_stat->st_uid;
1462 hdr->unix_gid = v_stat->st_gid;
1464 #if INCLUDE_OWNER_NAME_IN_HEADER
1467 struct passwd *ent = getpwuid(hdr->unix_uid);
1470 strncpy(hdr->user, ent->pw_name, sizeof(hdr->user));
1471 if (hdr->user[sizeof(hdr->user)-1])
1472 hdr->user[sizeof(hdr->user)-1] = 0;
1478 struct group *ent = getgrgid(hdr->unix_gid);
1481 strncpy(hdr->group, ent->gr_name, sizeof(hdr->group));
1482 if (hdr->group[sizeof(hdr->group)-1])
1483 hdr->group[sizeof(hdr->group)-1] = 0;
1487 #endif /* INCLUDE_OWNER_NAME_IN_HEADER */
1488 if (is_directory(v_stat)) {
1489 memcpy(hdr->method, LZHDIRS_METHOD, METHOD_TYPE_STORAGE);
1490 hdr->attribute = GENERIC_DIRECTORY_ATTRIBUTE;
1491 hdr->original_size = 0;
1492 if (len > 0 && hdr->name[len - 1] != '/') {
1493 if (len < sizeof(hdr->name)-1)
1494 strcpy(&hdr->name[len++], "/"); /* ok */
1496 warning("the length of dirname \"%s\" is too long.",
1502 if (is_symlink(v_stat)) {
1503 memcpy(hdr->method, LZHDIRS_METHOD, METHOD_TYPE_STORAGE);
1504 hdr->attribute = GENERIC_DIRECTORY_ATTRIBUTE;
1505 hdr->original_size = 0;
1506 readlink(name, hdr->realname, sizeof(hdr->realname));
1512 write_unix_info(hdr)
1515 /* UNIX specific informations */
1517 put_word(5); /* size */
1518 put_byte(0x50); /* permission */
1519 put_word(hdr->unix_mode);
1521 put_word(7); /* size */
1522 put_byte(0x51); /* gid and uid */
1523 put_word(hdr->unix_gid);
1524 put_word(hdr->unix_uid);
1526 if (hdr->group[0]) {
1527 int len = strlen(hdr->group);
1528 put_word(len + 3); /* size */
1529 put_byte(0x52); /* group name */
1530 put_bytes(hdr->group, len);
1534 int len = strlen(hdr->user);
1535 put_word(len + 3); /* size */
1536 put_byte(0x53); /* user name */
1537 put_bytes(hdr->user, len);
1540 if (hdr->header_level == 1) {
1541 put_word(7); /* size */
1542 put_byte(0x54); /* time stamp */
1543 put_longword(hdr->unix_last_modified_stamp);
1548 write_header_level0(data, hdr, pathname)
1550 char *data, *pathname;
1557 memset(data, 0, LZHEADER_STORAGE);
1559 put_byte(0x00); /* header size */
1560 put_byte(0x00); /* check sum */
1561 put_bytes(hdr->method, 5);
1562 put_longword(hdr->packed_size);
1563 put_longword(hdr->original_size);
1564 put_longword(unix_to_generic_stamp(hdr->unix_last_modified_stamp));
1565 put_byte(hdr->attribute);
1566 put_byte(hdr->header_level); /* level 0 */
1568 /* write pathname (level 0 header contains the directory part) */
1569 name_length = strlen(pathname);
1571 limit = 255 - I_GENERIC_HEADER_SIZE + 2;
1573 limit = 255 - I_LEVEL0_HEADER_SIZE + 2;
1575 if (name_length > limit) {
1576 warning("the length of pathname \"%s\" is too long.", pathname);
1577 name_length = limit;
1579 put_byte(name_length);
1580 put_bytes(pathname, name_length);
1583 if (generic_format) {
1584 header_size = I_GENERIC_HEADER_SIZE + name_length - 2;
1585 data[I_HEADER_SIZE] = header_size;
1586 data[I_HEADER_CHECKSUM] = calc_sum(data + I_METHOD, header_size);
1588 /* write old-style extend header */
1589 put_byte(EXTEND_UNIX);
1590 put_byte(CURRENT_UNIX_MINOR_VERSION);
1591 put_longword(hdr->unix_last_modified_stamp);
1592 put_word(hdr->unix_mode);
1593 put_word(hdr->unix_uid);
1594 put_word(hdr->unix_gid);
1596 /* size of extended header is 12 */
1597 header_size = I_LEVEL0_HEADER_SIZE + name_length - 2;
1598 data[I_HEADER_SIZE] = header_size;
1599 data[I_HEADER_CHECKSUM] = calc_sum(data + I_METHOD, header_size);
1602 return header_size + 2;
1606 write_header_level1(data, hdr, pathname)
1608 char *data, *pathname;
1610 int name_length, dir_length, limit;
1611 char *basename, *dirname;
1613 char *extend_header_top;
1614 size_t extend_header_size;
1616 basename = strrchr(pathname, LHA_PATHSEP);
1619 name_length = strlen(basename);
1621 dir_length = basename - dirname;
1624 basename = pathname;
1625 name_length = strlen(basename);
1631 memset(data, 0, LZHEADER_STORAGE);
1633 put_byte(0x00); /* header size */
1634 put_byte(0x00); /* check sum */
1635 put_bytes(hdr->method, 5);
1636 put_longword(hdr->packed_size);
1637 put_longword(hdr->original_size);
1638 put_longword(unix_to_generic_stamp(hdr->unix_last_modified_stamp));
1640 put_byte(hdr->header_level); /* level 1 */
1642 /* level 1 header: write filename (basename only) */
1643 limit = 255 - I_LEVEL1_HEADER_SIZE + 2;
1644 if (name_length > limit) {
1645 put_byte(0); /* name length */
1648 put_byte(name_length);
1649 put_bytes(basename, name_length);
1657 put_byte(EXTEND_UNIX);
1659 /* write extend header from here. */
1661 extend_header_top = put_ptr+2; /* +2 for the field `next header size' */
1662 header_size = extend_header_top - data - 2;
1664 /* write filename and dirname */
1666 if (name_length > limit) {
1667 put_word(name_length + 3); /* size */
1668 put_byte(0x01); /* filename */
1669 put_bytes(basename, name_length);
1672 if (dir_length > 0) {
1673 put_word(dir_length + 3); /* size */
1674 put_byte(0x02); /* dirname */
1675 put_bytes(dirname, dir_length);
1678 if (!generic_format)
1679 write_unix_info(hdr);
1681 put_word(0x0000); /* next header size */
1683 extend_header_size = put_ptr - extend_header_top;
1684 /* On level 1 header, the packed size field is contains the ext-header */
1685 hdr->packed_size += put_ptr - extend_header_top;
1687 /* put `skip size' */
1688 setup_put(data + I_PACKED_SIZE);
1689 put_longword(hdr->packed_size);
1691 data[I_HEADER_SIZE] = header_size;
1692 data[I_HEADER_CHECKSUM] = calc_sum(data + I_METHOD, header_size);
1694 return header_size + extend_header_size + 2;
1698 write_header_level2(data, hdr, pathname)
1700 char *data, *pathname;
1702 int name_length, dir_length;
1703 char *basename, *dirname;
1705 char *extend_header_top;
1706 char *headercrc_ptr;
1709 basename = strrchr(pathname, LHA_PATHSEP);
1712 name_length = strlen(basename);
1714 dir_length = basename - dirname;
1717 basename = pathname;
1718 name_length = strlen(basename);
1724 memset(data, 0, LZHEADER_STORAGE);
1726 put_word(0x0000); /* header size */
1727 put_bytes(hdr->method, 5);
1728 put_longword(hdr->packed_size);
1729 put_longword(hdr->original_size);
1730 put_longword(hdr->unix_last_modified_stamp);
1732 put_byte(hdr->header_level); /* level 2 */
1739 put_byte(EXTEND_UNIX);
1741 /* write extend header from here. */
1743 extend_header_top = put_ptr+2; /* +2 for the field `next header size' */
1745 /* write common header */
1748 headercrc_ptr = put_ptr;
1749 put_word(0x0000); /* header CRC */
1751 /* write filename and dirname */
1752 /* must have this header, even if the name_length is 0. */
1753 put_word(name_length + 3); /* size */
1754 put_byte(0x01); /* filename */
1755 put_bytes(basename, name_length);
1757 if (dir_length > 0) {
1758 put_word(dir_length + 3); /* size */
1759 put_byte(0x02); /* dirname */
1760 put_bytes(dirname, dir_length);
1763 if (!generic_format)
1764 write_unix_info(hdr);
1766 put_word(0x0000); /* next header size */
1768 header_size = put_ptr - data;
1769 if ((header_size & 0xff) == 0) {
1770 /* cannot put zero at the first byte on level 2 header. */
1771 /* adjust header size. */
1772 put_byte(0); /* padding */
1776 /* put header size */
1777 setup_put(data + I_HEADER_SIZE);
1778 put_word(header_size);
1780 /* put header CRC in extended header */
1781 INITIALIZE_CRC(hcrc);
1782 hcrc = calccrc(hcrc, data, (unsigned int) header_size);
1783 setup_put(headercrc_ptr);
1790 write_header(fp, hdr)
1795 char data[LZHEADER_STORAGE];
1797 int archive_kanji_code = CODE_SJIS;
1798 int system_kanji_code = default_system_kanji_code;
1799 char *archive_delim = "\377";
1800 char *system_delim = "/";
1801 int filename_case = NONE;
1802 char pathname[FILENAME_LENGTH];
1804 if (optional_archive_kanji_code)
1805 archive_kanji_code = optional_archive_kanji_code;
1806 if (optional_system_kanji_code)
1807 system_kanji_code = optional_system_kanji_code;
1809 if (generic_format && convertcase)
1810 filename_case = TO_UPPER;
1812 if (hdr->header_level == 0) {
1813 archive_delim = "\\";
1816 if ((hdr->unix_mode & UNIX_FILE_SYMLINK) == UNIX_FILE_SYMLINK) {
1818 p = strchr(hdr->name, '|');
1820 error("symlink name \"%s\" contains '|' char. change it into '_'",
1824 if (xsnprintf(pathname, sizeof(pathname),
1825 "%s|%s", hdr->name, hdr->realname) == -1)
1826 error("file name is too long (%s -> %s)", hdr->name, hdr->realname);
1829 strncpy(pathname, hdr->name, sizeof(pathname));
1830 pathname[sizeof(pathname)-1] = 0;
1833 convert_filename(pathname, strlen(pathname), sizeof(pathname),
1836 system_delim, archive_delim, filename_case);
1838 switch (hdr->header_level) {
1840 header_size = write_header_level0(data, hdr, pathname);
1843 header_size = write_header_level1(data, hdr, pathname);
1846 header_size = write_header_level2(data, hdr, pathname);
1849 error("Unknown level header (level %d)", hdr->header_level);
1853 if (fwrite(data, header_size, 1, fp) == 0)
1854 fatal_error("Cannot write to temporary file");
1857 #if MULTIBYTE_FILENAME
1859 #if defined(__APPLE__) /* Added by Hiroto Sakai */
1861 #include <CoreFoundation/CFString.h>
1862 #include <CoreFoundation/CFStringEncodingExt.h>
1864 /* this is not need for Mac OS X v 10.2 later */
1866 kCFStringEncodingAllowLossyConversion = 1,
1867 kCFStringEncodingBasicDirectionLeftToRight = (1 << 1),
1868 kCFStringEncodingBasicDirectionRightToLeft = (1 << 2),
1869 kCFStringEncodingSubstituteCombinings = (1 << 3),
1870 kCFStringEncodingComposeCombinings = (1 << 4),
1871 kCFStringEncodingIgnoreCombinings = (1 << 5),
1872 kCFStringEncodingUseCanonical = (1 << 6),
1873 kCFStringEncodingUseHFSPlusCanonical = (1 << 7),
1874 kCFStringEncodingPrependBOM = (1 << 8),
1875 kCFStringEncodingDisableCorporateArea = (1 << 9),
1876 kCFStringEncodingASCIICompatibleConversion = (1 << 10),
1880 ConvertEncodingToUTF8(const char* inCStr,
1881 char* outUTF8Buffer,
1882 int outUTF8BufferLength,
1883 unsigned long scriptEncoding,
1884 unsigned long flags)
1886 unsigned long unicodeChars;
1887 unsigned long srcCharsUsed;
1888 unsigned long usedByteLen = 0;
1889 UniChar uniStr[512];
1890 unsigned long cfResult;
1892 cfResult = CFStringEncodingBytesToUnicode(scriptEncoding,
1900 if (cfResult == 0) {
1901 cfResult = CFStringEncodingUnicodeToBytes(kCFStringEncodingUTF8,
1906 (char*)outUTF8Buffer,
1907 outUTF8BufferLength - 1,
1909 outUTF8Buffer[usedByteLen] = '\0';
1916 ConvertUTF8ToEncoding(const char* inUTF8Buf,
1917 int inUTF8BufLength,
1918 char* outCStrBuffer,
1919 int outCStrBufferLength,
1920 unsigned long scriptEncoding,
1921 unsigned long flags)
1923 unsigned long unicodeChars;
1924 unsigned long srcCharsUsed;
1925 unsigned long usedByteLen = 0;
1926 UniChar uniStr[256];
1927 unsigned long cfResult;
1929 cfResult = CFStringEncodingBytesToUnicode(kCFStringEncodingUTF8,
1937 if (cfResult == 0) {
1938 cfResult = CFStringEncodingUnicodeToBytes(scriptEncoding,
1943 (char*)outCStrBuffer,
1944 outCStrBufferLength - 1,
1946 outCStrBuffer[usedByteLen] = '\0';
1956 ConvertEncodingByIconv(const char *src, char *dst, int dstsize,
1957 const char *srcEnc, const char *dstEnc)
1960 static char szTmpBuf[2048];
1966 dst_p = &szTmpBuf[0];
1967 iLen = (size_t)sizeof(szTmpBuf)-1;
1968 src_p = (char *)src;
1969 sLen = (size_t)strlen(src);
1970 memset(szTmpBuf, 0, sizeof(szTmpBuf));
1971 memset(dst, 0, dstsize);
1973 ic = iconv_open(dstEnc, srcEnc);
1974 if (ic == (iconv_t)-1) {
1975 error("iconv_open() failure: %s", strerror(errno));
1979 if (iconv(ic, &src_p, &sLen, &dst_p, &iLen) == (size_t)-1) {
1980 error("iconv() failure: %s", strerror(errno));
1985 strncpy(dst, szTmpBuf, dstsize);
1991 #endif /* defined(__APPLE__) */
1994 sjis_to_utf8(char *dst, const char *src, size_t dstsize)
1996 #if defined(__APPLE__)
1998 if (ConvertEncodingToUTF8(src, dst, dstsize,
1999 kCFStringEncodingDOSJapanese,
2000 kCFStringEncodingUseHFSPlusCanonical) == 0)
2003 if (ConvertEncodingByIconv(src, dst, dstsize, "SJIS", "UTF-8") != -1)
2006 error("not support utf-8 conversion");
2009 if (dstsize < 1) return dst;
2011 return strncpy(dst, src, dstsize-1);
2015 utf8_to_sjis(char *dst, const char *src, size_t dstsize)
2017 #if defined(__APPLE__)
2021 srclen = strlen(src);
2022 if (ConvertUTF8ToEncoding(src, srclen, dst, dstsize,
2023 kCFStringEncodingDOSJapanese,
2024 kCFStringEncodingUseHFSPlusCanonical) == 0)
2027 if (ConvertEncodingByIconv(src, dst, dstsize, "UTF-8", "SJIS") != -1)
2030 error("not support utf-8 conversion");
2033 if (dstsize < 1) return dst;
2035 return strncpy(dst, src, dstsize-1);
2039 * SJIS <-> EUC ÊÑ´¹´Ø¿ô
2040 * ¡ÖÆüËܸì¾ðÊó½èÍý¡× ¥½¥Õ¥È¥Ð¥ó¥¯(³ô)
2041 * ¤è¤êÈ´¿è(by Koji Arai)
2044 euc2sjis(int *p1, int *p2)
2046 unsigned char c1 = *p1 & 0x7f;
2047 unsigned char c2 = *p2 & 0x7f;
2048 int rowoff = c1 < 0x5f ? 0x70 : 0xb0;
2049 int celoff = c1 % 2 ? (c2 > 0x5f ? 0x20 : 0x1f) : 0x7e;
2050 *p1 = ((c1 + 1) >> 1) + rowoff;
2051 *p2 += celoff - 0x80;
2055 sjis2euc(int *p1, int *p2)
2057 unsigned char c1 = *p1;
2058 unsigned char c2 = *p2;
2059 int adjust = c2 < 0x9f;
2060 int rowoff = c1 < 0xa0 ? 0x70 : 0xb0;
2061 int celoff = adjust ? (c2 > 0x7f ? 0x20 : 0x1f) : 0x7e;
2062 *p1 = ((c1 - rowoff) << 1) - adjust;
2073 case '0': case '1': case '2': case '3': case '4':
2074 case '5': case '6': case '7': case '8': case '9':
2077 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
2078 return c - 'a' + 10;
2080 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
2081 return c - 'A' + 10;
2091 case 0: case 1: case 2: case 3: case 4:
2092 case 5: case 6: case 7: case 8: case 9:
2095 case 10: case 11: case 12: case 13: case 14: case 15:
2096 return c + 'a' - 10;
2104 cap_to_sjis(char *dst, const char *src, size_t dstsize)
2107 size_t len = strlen(src);
2110 for (i = j = 0; i < len && i < dstsize; i++) {
2111 if (src[i] != ':') {
2117 a = hex2int((unsigned char)src[i]);
2118 b = hex2int((unsigned char)src[i+1]);
2120 if (a == -1 || b == -1) {
2123 strncpy(dst+j, src+i, dstsize-j);
2130 dst[j++] = a * 16 + b;
2137 sjis_to_cap(char *dst, const char *src, size_t dstsize)
2140 size_t len = strlen(src);
2143 for (i = j = 0; i < len && i < dstsize; i++) {
2144 if (src[i] == ':') {
2145 strncpy(dst+j, ":3a", dstsize-j);
2150 if (isprint(src[i])) {
2155 if (j + 3 >= dstsize) {
2160 a = int2hex((unsigned char)src[i] / 16);
2161 b = int2hex((unsigned char)src[i] % 16);
2170 #endif /* MULTIBYTE_FILENAME */