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) _skip_bytes(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;
64 unsigned char *pc = (unsigned char*)p;
66 while (len--) sum += *pc++;
75 error("Invalid header: %d", len);
87 if (verbose_listing && verbose > 1)
88 printf("%02d %2d: ", get_ptr - start_ptr, 1);
90 if (verbose_listing && verbose > 1) {
92 printf("%d(0x%02x) '%c'\n", c, c, c);
94 printf("%d(0x%02x)\n", c, c);
103 if (len == 0) return;
104 if (verbose_listing && verbose > 1) {
105 printf("%02d %2d: ", get_ptr - start_ptr, len);
107 error("Invalid header: %d", len);
111 printf("0x%02x ", GET_BYTE());
112 printf("... ignored\n");
126 if (verbose_listing && verbose > 1)
127 printf("%02d %2d: ", get_ptr - start_ptr, 2);
133 if (verbose_listing && verbose > 1)
134 printf("%d(0x%04x)\n", w, w);
154 if (verbose_listing && verbose > 1)
155 printf("%02d %2d: ", get_ptr - start_ptr, 4);
161 l = (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
163 if (verbose_listing && verbose > 1)
164 printf("%ld(0x%08lx)\n", l, l);
182 uint64_t b0, b1, b2, b3, b4, b5, b6, b7;
186 if (verbose_listing && verbose > 1)
187 printf("%02d %2d: ", get_ptr - start_ptr, 4);
198 l = (b7 << 24) + (b6 << 16) + (b5 << 8) + b4;
200 l |= (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
202 if (verbose_listing && verbose > 1)
203 printf("%lld(%#016llx)\n", l, l);
209 put_longlongword(uint64_t v)
223 get_bytes(buf, len, size)
230 if (verbose_listing && verbose > 1)
231 printf("%02d %2d: \"", get_ptr - start_ptr, len);
233 for (i = 0; i < len; i++) {
234 if (i < size) buf[i] = get_ptr[i];
236 if (verbose_listing && verbose > 1) {
238 printf("%c", buf[i]);
240 printf("\\x%02x", (unsigned char)buf[i]);
244 if (verbose_listing && verbose > 1)
247 for (i = 0; i < len && i < size; i++)
261 for (i = 0; i < len; i++)
265 /* added by Koji Arai */
267 convert_filename(name, len, size,
269 from_delim, to_delim,
272 int len; /* length of name */
273 int size; /* size of name buffer */
274 int from_code, to_code, case_to;
275 char *from_delim, *to_delim;
279 #ifdef MULTIBYTE_FILENAME
280 char tmp[FILENAME_LENGTH];
281 int to_code_save = NONE;
283 if (from_code == CODE_CAP) {
284 len = cap_to_sjis(tmp, name, sizeof(tmp));
285 strncpy(name, tmp, size);
288 from_code = CODE_SJIS;
291 if (to_code == CODE_CAP) {
292 to_code_save = CODE_CAP;
297 /* special case: if `name' has small lettter, not convert case. */
298 if (from_code == CODE_SJIS && case_to == TO_LOWER) {
299 for (i = 0; i < len; i++) {
300 #ifdef MULTIBYTE_FILENAME
301 if (SJIS_FIRST_P(name[i]) && SJIS_SECOND_P(name[i+1]))
305 if (islower(name[i])) {
312 #ifdef MULTIBYTE_FILENAME
313 if (from_code == CODE_SJIS && to_code == CODE_UTF8) {
314 for (i = 0; i < len; i++) {
315 if (SJIS_FIRST_P(name[i]) && SJIS_SECOND_P(name[i+1]))
318 /* FIXME: provisionally fix for the Mac OS CoreFoundation */
319 if (strchr(from_delim, name[i]))
323 sjis_to_utf8(tmp, name, sizeof(tmp));
324 strncpy(name, tmp, size);
327 for (i = 0; i < len; i++)
328 if (name[i] == '/') name[i] = LHA_PATHSEP;
329 from_code = CODE_UTF8;
331 else if (from_code == CODE_UTF8 && to_code == CODE_SJIS) {
332 for (i = 0; i < len; i++)
333 /* FIXME: provisionally fix for the Mac OS CoreFoundation */
334 if ((unsigned char)name[i] == LHA_PATHSEP) name[i] = '/';
335 utf8_to_sjis(tmp, name, sizeof(tmp));
336 strncpy(name, tmp, size);
339 for (i = 0; i < len; i++)
340 if (name[i] == '/') name[i] = LHA_PATHSEP;
341 from_code = CODE_SJIS;
345 for (i = 0; i < len; i ++) {
346 #ifdef MULTIBYTE_FILENAME
347 if (from_code == CODE_EUC &&
348 (unsigned char)name[i] == 0x8e) {
349 if (to_code != CODE_SJIS) {
355 memmove(name + i, name + i + 1, len - i);
359 if (from_code == CODE_SJIS && X0201_KANA_P(name[i])) {
360 if (to_code != CODE_EUC) {
364 if (len == size - 1) /* check overflow */
366 memmove(name+i+1, name+i, len-i);
372 if (from_code == CODE_EUC && (name[i] & 0x80) && (name[i+1] & 0x80)) {
374 if (to_code != CODE_SJIS) {
379 c1 = (unsigned char)name[i];
380 c2 = (unsigned char)name[i+1];
387 if (from_code == CODE_SJIS &&
388 SJIS_FIRST_P(name[i]) &&
389 SJIS_SECOND_P(name[i+1])) {
392 if (to_code != CODE_EUC) {
397 c1 = (unsigned char)name[i];
398 c2 = (unsigned char)name[i+1];
405 #endif /* MULTIBYTE_FILENAME */
409 /* transpose from_delim to to_delim */
411 if ((ptr = strchr(from_delim, name[i])) != NULL) {
412 name[i] = to_delim[ptr - from_delim];
417 if (case_to == TO_UPPER && islower(name[i])) {
418 name[i] = toupper(name[i]);
421 if (case_to == TO_LOWER && isupper(name[i])) {
422 name[i] = tolower(name[i]);
427 #ifdef MULTIBYTE_FILENAME
428 if (to_code_save == CODE_CAP) {
429 len = sjis_to_cap(tmp, name, sizeof(tmp));
430 strncpy(name, tmp, size);
434 #endif /* MULTIBYTE_FILENAME */
438 * Generic (MS-DOS style) time stamp format (localtime):
440 * 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
441 * |<---- year-1980 --->|<- month ->|<--- day ---->|
443 * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
444 * |<--- hour --->|<---- minute --->|<- second/2 ->|
449 generic_to_unix_stamp(t)
454 #define subbits(n, off, len) (((n) >> (off)) & ((1 << (len))-1))
456 tm.tm_sec = subbits(t, 0, 5) * 2;
457 tm.tm_min = subbits(t, 5, 6);
458 tm.tm_hour = subbits(t, 11, 5);
459 tm.tm_mday = subbits(t, 16, 5);
460 tm.tm_mon = subbits(t, 21, 4) - 1;
461 tm.tm_year = subbits(t, 25, 7) + 80;
467 return timelocal(&tm);
472 unix_to_generic_stamp(t)
475 struct tm *tm = localtime(&t);
480 return ((long)(tm->tm_year << 25) +
482 (tm->tm_mday << 16) +
483 (tm->tm_hour << 11) +
489 wintime_to_unix_stamp()
493 uint64_t epoch = ((uint64_t)0x019db1de << 32) + 0xd53e8000;
494 /* 0x019db1ded53e8000ULL: 1970-01-01 00:00:00 (UTC) */
496 t = (unsigned long)get_longword();
497 t |= (uint64_t)(unsigned long)get_longword() << 32;
498 t = (t - epoch) / 10000000;
502 unsigned long t, q, x;
503 unsigned long wintime[8];
504 unsigned long epoch[8] = {0x01,0x9d,0xb1,0xde, 0xd5,0x3e,0x80,0x00};
505 /* 1970-01-01 00:00:00 (UTC) */
506 /* wintime -= epoch */
508 for (i = 7; i >= 0; i--) {
509 wintime[i] = (unsigned)get_byte() - epoch[i] - borrow;
510 borrow = (wintime[i] > 0xff) ? 1 : 0;
514 /* q = wintime / 10000000 */
516 x = 10000000; /* x: 24bit */
517 for (i = 0; i < 8; i++) {
518 t = (t << 8) + wintime[i]; /* 24bit + 8bit. t must be 32bit variable */
519 q <<= 8; /* q must be 32bit (time_t) */
531 * --------------------------------
533 * 2 or 4 next-header size [*1]
534 * --------------------------------------
535 * ext header: 1 ext-type ^
536 * ? contents | [*1] next-header size
537 * 2 or 4 next-header size v
538 * --------------------------------------
540 * on level 1, 2 header:
541 * size field is 2 bytes
543 * size field is 4 bytes
547 get_extended_header(fp, hdr, header_size, hcrc)
553 char data[LZHEADER_STORAGE];
555 char dirname[FILENAME_LENGTH];
558 ssize_t whole_size = header_size;
560 int n = 1 + hdr->size_field_length; /* `ext-type' + `next-header size' */
562 if (hdr->header_level == 0)
565 name_length = strlen(hdr->name);
567 while (header_size) {
569 if (verbose_listing && verbose > 1)
573 if (sizeof(data) < header_size) {
574 error("header size (%ld) too large.", header_size);
578 if (fread(data, header_size, 1, fp) == 0) {
579 error("Invalid header (LHa file ?)");
583 ext_type = get_byte();
587 if (verbose_listing && verbose > 1) printf(" < header crc >\n");
589 /* header crc (CRC-16) */
590 hdr->header_crc = get_word();
591 /* clear buffer for CRC calculation. */
592 data[1] = data[2] = 0;
593 skip_bytes(header_size - n - 2);
597 if (verbose_listing && verbose > 1) printf(" < filename >\n");
601 get_bytes(hdr->name, header_size-n, sizeof(hdr->name)-1);
602 hdr->name[name_length] = 0;
606 if (verbose_listing && verbose > 1) printf(" < directory >\n");
609 dir_length = get_bytes(dirname, header_size-n, sizeof(dirname)-1);
610 dirname[dir_length] = 0;
614 if (verbose_listing && verbose > 1) printf(" < MS-DOS attribute >\n");
616 /* MS-DOS attribute */
617 hdr->attribute = get_word();
621 if (verbose_listing && verbose > 1) printf(" < Windows time stamp (FILETIME) >\n");
623 /* Windows time stamp (FILETIME structure) */
624 /* it is time in 100 nano seconds since 1601-01-01 00:00:00 */
626 skip_bytes(8); /* create time is ignored */
628 /* set last modified time */
629 if (hdr->header_level >= 2)
630 skip_bytes(8); /* time_t has been already set */
632 hdr->unix_last_modified_stamp = wintime_to_unix_stamp();
634 skip_bytes(8); /* last access time is ignored */
639 if (verbose_listing && verbose > 1) printf(" < 64bits file size header >\n");
642 /* 64bits file size header (UNLHA32 extension) */
643 hdr->packed_size = get_longlongword();
644 hdr->original_size = get_longlongword();
653 if (verbose_listing && verbose > 1) printf(" < UNIX permission >\n");
655 /* UNIX permission */
656 hdr->unix_mode = get_word();
660 if (verbose_listing && verbose > 1) printf(" < UNIX gid and uid >\n");
662 /* UNIX gid and uid */
663 hdr->unix_gid = get_word();
664 hdr->unix_uid = get_word();
668 if (verbose_listing && verbose > 1) printf(" < UNIX group name >\n");
670 /* UNIX group name */
671 i = get_bytes(hdr->group, header_size-n, sizeof(hdr->group)-1);
672 hdr->group[i] = '\0';
676 if (verbose_listing && verbose > 1) printf(" < UNIX user name >\n");
679 i = get_bytes(hdr->user, header_size-n, sizeof(hdr->user)-1);
684 if (verbose_listing && verbose > 1) printf(" < UNIX last modifed time (time_t) >\n");
686 /* UNIX last modified time */
687 hdr->unix_last_modified_stamp = (time_t) get_longword();
691 /* 0x39: multi-disk header
692 0x3f: uncompressed comment
693 0x42: 64bit large file size
694 0x48-0x4f(?): reserved for authenticity verification
696 0x7e: extended attribute - platform information
697 0x7f: extended attribute - permission, owner-id and timestamp
699 0xc4: compressed comment (dict size: 4096)
700 0xc5: compressed comment (dict size: 8192)
701 0xc6: compressed comment (dict size: 16384)
702 0xc7: compressed comment (dict size: 32768)
703 0xc8: compressed comment (dict size: 65536)
704 0xd0-0xdf(?): operating systemm specific information
705 0xfc: encapsulation (another opinion)
706 0xfe: extended attribute - platform information(another opinion)
707 0xff: extended attribute - permission, owner-id and timestamp
708 (level 3 on UNLHA32) */
710 warning("unknown extended header 0x%02x", ext_type);
711 skip_bytes(header_size - n);
716 *hcrc = calccrc(*hcrc, data, header_size);
718 if (hdr->size_field_length == 2)
719 whole_size += header_size = get_word();
721 whole_size += header_size = get_longword();
724 /* concatenate dirname and filename */
726 if (name_length + dir_length >= sizeof(hdr->name)) {
727 warning("the length of pathname \"%s%s\" is too long.",
729 name_length = sizeof(hdr->name) - dir_length - 1;
730 hdr->name[name_length] = 0;
732 strcat(dirname, hdr->name); /* ok */
733 strcpy(hdr->name, dirname); /* ok */
734 name_length += dir_length;
740 #define I_HEADER_SIZE 0 /* level 0,1,2 */
741 #define I_HEADER_CHECKSUM 1 /* level 0,1 */
742 #define I_METHOD 2 /* level 0,1,2,3 */
743 #define I_PACKED_SIZE 7 /* level 0,1,2,3 */
744 #define I_ATTRIBUTE 19 /* level 0,1,2,3 */
745 #define I_HEADER_LEVEL 20 /* level 0,1,2,3 */
747 #define COMMON_HEADER_SIZE 21 /* size of common part */
749 #define I_GENERIC_HEADER_SIZE 24 /* + name_length */
750 #define I_LEVEL0_HEADER_SIZE 36 /* + name_length (unix extended) */
751 #define I_LEVEL1_HEADER_SIZE 27 /* + name_length */
752 #define I_LEVEL2_HEADER_SIZE 26 /* + padding */
753 #define I_LEVEL3_HEADER_SIZE 32
759 * offset size field name
760 * ----------------------------------
761 * 0 1 header size [*1]
763 * ---------------------------------------
765 * 7 4 packed size [*2] |
766 * 11 4 original size |
769 * 19 1 attribute | [*1] header size (X+Y+22)
770 * 20 1 level (0x00 fixed) |
773 * X +22 2 file crc (CRC-16) |
774 * X +24 Y ext-header(old style) v
775 * -------------------------------------------------
777 * : | [*2] packed size
779 * -------------------------------------------------
781 * ext-header(old style)
795 * bit6 archive bit (need to backup)
799 get_header_level0(fp, hdr, data)
811 hdr->size_field_length = 2; /* in bytes */
812 hdr->header_size = header_size = get_byte();
813 checksum = get_byte();
815 /* The data variable has been already read as COMMON_HEADER_SIZE bytes.
816 So we must read the remaining header size by the header_size. */
817 remain_size = header_size + 2 - COMMON_HEADER_SIZE;
818 if (remain_size <= 0) {
819 error("Invalid header size (LHarc file ?)");
822 if (fread(data + COMMON_HEADER_SIZE, remain_size, 1, fp) == 0) {
823 error("Invalid header (LHarc file ?)");
824 return FALSE; /* finish */
827 if (calc_sum(data + I_METHOD, header_size) != checksum) {
828 error("Checksum error (LHarc file?)");
832 get_bytes(hdr->method, 5, sizeof(hdr->method));
833 hdr->packed_size = (unsigned long)get_longword();
834 hdr->original_size = (unsigned long)get_longword();
835 hdr->unix_last_modified_stamp = generic_to_unix_stamp(get_longword());
836 hdr->attribute = get_byte(); /* MS-DOS attribute */
837 hdr->header_level = get_byte();
838 name_length = get_byte();
839 i = get_bytes(hdr->name, name_length, sizeof(hdr->name)-1);
842 /* defaults for other type */
843 hdr->unix_mode = UNIX_FILE_REGULAR | UNIX_RW_RW_RW;
847 extend_size = header_size+2 - name_length - 24;
849 if (extend_size < 0) {
850 if (extend_size == -2) {
851 /* CRC field is not given */
852 hdr->extend_type = EXTEND_GENERIC;
853 hdr->has_crc = FALSE;
858 error("Unkonwn header (lha file?)");
863 hdr->crc = get_word();
865 if (extend_size == 0)
868 hdr->extend_type = get_byte();
871 if (hdr->extend_type == EXTEND_UNIX) {
872 if (extend_size >= 11) {
873 hdr->minor_version = get_byte();
874 hdr->unix_last_modified_stamp = (time_t) get_longword();
875 hdr->unix_mode = get_word();
876 hdr->unix_uid = get_word();
877 hdr->unix_gid = get_word();
880 hdr->extend_type = EXTEND_GENERIC;
884 skip_bytes(extend_size);
886 hdr->header_size += 2;
894 * offset size field name
895 * -----------------------------------
896 * 0 1 header size [*1]
898 * -------------------------------------
900 * 7 4 skip size [*2] |
901 * 11 4 original size |
904 * 19 1 attribute (0x20 fixed) | [*1] header size (X+Y+25)
905 * 20 1 level (0x01 fixed) |
908 * X+ 22 2 file crc (CRC-16) |
911 * X+Y+25 2 next-header size v
912 * -------------------------------------------------
913 * X+Y+27 Z ext-header ^
915 * ----------------------------------- | [*2] skip size
918 * -------------------------------------------------
922 get_header_level1(fp, hdr, data)
934 hdr->size_field_length = 2; /* in bytes */
935 hdr->header_size = header_size = get_byte();
936 checksum = get_byte();
938 /* The data variable has been already read as COMMON_HEADER_SIZE bytes.
939 So we must read the remaining header size by the header_size. */
940 remain_size = header_size + 2 - COMMON_HEADER_SIZE;
941 if (remain_size <= 0) {
942 error("Invalid header size (LHarc file ?)");
945 if (fread(data + COMMON_HEADER_SIZE, remain_size, 1, fp) == 0) {
946 error("Invalid header (LHarc file ?)");
947 return FALSE; /* finish */
950 if (calc_sum(data + I_METHOD, header_size) != checksum) {
951 error("Checksum error (LHarc file?)");
955 get_bytes(hdr->method, 5, sizeof(hdr->method));
956 hdr->packed_size = (unsigned long)get_longword(); /* skip size */
957 hdr->original_size = (unsigned long)get_longword();
958 hdr->unix_last_modified_stamp = generic_to_unix_stamp(get_longword());
959 hdr->attribute = get_byte(); /* 0x20 fixed */
960 hdr->header_level = get_byte();
962 name_length = get_byte();
963 i = get_bytes(hdr->name, name_length, sizeof(hdr->name)-1);
966 /* defaults for other type */
967 hdr->unix_mode = UNIX_FILE_REGULAR | UNIX_RW_RW_RW;
972 hdr->crc = get_word();
973 hdr->extend_type = get_byte();
975 dummy = header_size+2 - name_length - I_LEVEL1_HEADER_SIZE;
977 skip_bytes(dummy); /* skip old style extend header */
979 extend_size = get_word();
980 extend_size = get_extended_header(fp, hdr, extend_size, 0);
981 if (extend_size == -1)
984 /* On level 1 header, size fields should be adjusted. */
985 /* the `packed_size' field contains the extended header size. */
986 /* the `header_size' field does not. */
987 hdr->packed_size -= extend_size;
988 hdr->header_size += extend_size + 2;
997 * offset size field name
998 * --------------------------------------------------
999 * 0 2 total header size [*1] ^
1000 * ----------------------- |
1002 * 7 4 packed size [*2] |
1003 * 11 4 original size |
1005 * 19 1 RESERVED (0x20 fixed) | [*1] total header size
1006 * 20 1 level (0x02 fixed) | (X+26+(1))
1007 * 21 2 file crc (CRC-16) |
1009 * 24 2 next-header size |
1010 * ----------------------------------- |
1013 * ----------------------------------- |
1014 * X +26 (1) padding v
1015 * -------------------------------------------------
1017 * : | [*2] packed size
1019 * -------------------------------------------------
1023 get_header_level2(fp, hdr, data)
1029 ssize_t extend_size;
1033 hdr->size_field_length = 2; /* in bytes */
1034 hdr->header_size = header_size = get_word();
1036 if (fread(data + COMMON_HEADER_SIZE,
1037 I_LEVEL2_HEADER_SIZE - COMMON_HEADER_SIZE, 1, fp) == 0) {
1038 error("Invalid header (LHarc file ?)");
1039 return FALSE; /* finish */
1042 get_bytes(hdr->method, 5, sizeof(hdr->method));
1043 hdr->packed_size = (unsigned long)get_longword();
1044 hdr->original_size = (unsigned long)get_longword();
1045 hdr->unix_last_modified_stamp = get_longword();
1046 hdr->attribute = get_byte(); /* reserved */
1047 hdr->header_level = get_byte();
1049 /* defaults for other type */
1050 hdr->unix_mode = UNIX_FILE_REGULAR | UNIX_RW_RW_RW;
1054 hdr->has_crc = TRUE;
1055 hdr->crc = get_word();
1056 hdr->extend_type = get_byte();
1057 extend_size = get_word();
1059 INITIALIZE_CRC(hcrc);
1060 hcrc = calccrc(hcrc, data, get_ptr - data);
1062 extend_size = get_extended_header(fp, hdr, extend_size, &hcrc);
1063 if (extend_size == -1)
1066 padding = header_size - I_LEVEL2_HEADER_SIZE - extend_size;
1067 while (padding--) /* padding should be 0 or 1 */
1068 hcrc = UPDATE_CRC(hcrc, fgetc(fp));
1070 if (hdr->header_crc != hcrc)
1071 error("header CRC error");
1080 * offset size field name
1081 * --------------------------------------------------
1082 * 0 2 size field length (4 fixed) ^
1084 * 7 4 packed size [*2] |
1085 * 11 4 original size |
1087 * 19 1 RESERVED (0x20 fixed) | [*1] total header size
1088 * 20 1 level (0x03 fixed) | (X+32)
1089 * 21 2 file crc (CRC-16) |
1091 * 24 4 total header size [*1] |
1092 * 28 4 next-header size |
1093 * ----------------------------------- |
1096 * -------------------------------------------------
1098 * : | [*2] packed size
1100 * -------------------------------------------------
1104 get_header_level3(fp, hdr, data)
1110 ssize_t extend_size;
1114 hdr->size_field_length = get_word();
1116 if (fread(data + COMMON_HEADER_SIZE,
1117 I_LEVEL3_HEADER_SIZE - COMMON_HEADER_SIZE, 1, fp) == 0) {
1118 error("Invalid header (LHarc file ?)");
1119 return FALSE; /* finish */
1122 get_bytes(hdr->method, 5, sizeof(hdr->method));
1123 hdr->packed_size = (unsigned long)get_longword();
1124 hdr->original_size = (unsigned long)get_longword();
1125 hdr->unix_last_modified_stamp = get_longword();
1126 hdr->attribute = get_byte(); /* reserved */
1127 hdr->header_level = get_byte();
1129 /* defaults for other type */
1130 hdr->unix_mode = UNIX_FILE_REGULAR | UNIX_RW_RW_RW;
1134 hdr->has_crc = TRUE;
1135 hdr->crc = get_word();
1136 hdr->extend_type = get_byte();
1137 hdr->header_size = header_size = get_longword();
1138 extend_size = get_longword();
1140 INITIALIZE_CRC(hcrc);
1141 hcrc = calccrc(hcrc, data, get_ptr - data);
1143 extend_size = get_extended_header(fp, hdr, extend_size, &hcrc);
1144 if (extend_size == -1)
1147 padding = header_size - I_LEVEL3_HEADER_SIZE - extend_size;
1148 while (padding--) /* padding should be 0 */
1149 hcrc = UPDATE_CRC(hcrc, fgetc(fp));
1151 if (hdr->header_crc != hcrc)
1152 error("header CRC error");
1162 char data[LZHEADER_STORAGE];
1164 int archive_kanji_code = CODE_SJIS;
1165 int system_kanji_code = default_system_kanji_code;
1166 char *archive_delim = "\377\\"; /* `\' is for level 0 header and
1168 char *system_delim = "//";
1169 int filename_case = NONE;
1172 memset(hdr, 0, sizeof(LzHeader));
1176 if ((end_mark = getc(fp)) == EOF || end_mark == 0) {
1177 return FALSE; /* finish */
1181 if (fread(data + 1, COMMON_HEADER_SIZE - 1, 1, fp) == 0) {
1182 error("Invalid header (LHarc file ?)");
1183 return FALSE; /* finish */
1186 switch (data[I_HEADER_LEVEL]) {
1188 if (get_header_level0(fp, hdr, data) == FALSE)
1192 if (get_header_level1(fp, hdr, data) == FALSE)
1196 if (get_header_level2(fp, hdr, data) == FALSE)
1200 if (get_header_level3(fp, hdr, data) == FALSE)
1204 error("Unknown level header (level %d)", data[I_HEADER_LEVEL]);
1208 /* filename conversion */
1209 switch (hdr->extend_type) {
1211 filename_case = convertcase ? TO_LOWER : NONE;
1218 filename_case = NONE;
1222 archive_delim = "\377/:\\";
1223 /* `\' is for level 0 header and broken archive. */
1224 system_delim = "/://";
1225 filename_case = NONE;
1229 filename_case = convertcase ? TO_LOWER : NONE;
1233 if (optional_archive_kanji_code)
1234 archive_kanji_code = optional_archive_kanji_code;
1235 if (optional_system_kanji_code)
1236 system_kanji_code = optional_system_kanji_code;
1237 if (optional_archive_delim)
1238 archive_delim = optional_archive_delim;
1239 if (optional_system_delim)
1240 system_delim = optional_system_delim;
1241 if (optional_filename_case)
1242 filename_case = optional_filename_case;
1244 /* kanji code and delimiter conversion */
1245 convert_filename(hdr->name, strlen(hdr->name), sizeof(hdr->name),
1248 archive_delim, system_delim, filename_case);
1250 if ((hdr->unix_mode & UNIX_FILE_SYMLINK) == UNIX_FILE_SYMLINK) {
1252 /* split symbolic link */
1253 p = strchr(hdr->name, '|');
1255 /* hdr->name is symbolic link name */
1256 /* hdr->realname is real name */
1258 strcpy(hdr->realname, p+1); /* ok */
1261 error("unknown symlink name \"%s\"", hdr->name);
1267 /* skip SFX header */
1272 unsigned char buffer[64 * 1024]; /* max seek size */
1276 n = fread(buffer, 1, sizeof(buffer), fp);
1278 for (p = buffer; p < buffer + n; p++) {
1279 if (! (p[I_METHOD]=='-' &&
1280 (p[I_METHOD+1]=='l' || p[I_METHOD+1]=='p') &&
1281 p[I_METHOD+4]=='-'))
1283 /* found "-[lp]??-" keyword (as METHOD type string) */
1285 /* level 0 or 1 header */
1286 if ((p[I_HEADER_LEVEL] == 0 || p[I_HEADER_LEVEL] == 1)
1287 && p[I_HEADER_SIZE] > 20
1288 && p[I_HEADER_CHECKSUM] == calc_sum(p+2, p[I_HEADER_SIZE])) {
1289 if (fseeko(fp, (p - buffer) - n, SEEK_CUR) == -1)
1290 fatal_error("cannot seek header");
1294 /* level 2 header */
1295 if (p[I_HEADER_LEVEL] == 2
1296 && p[I_HEADER_SIZE] >= 24
1297 && p[I_ATTRIBUTE] == 0x20) {
1298 if (fseeko(fp, (p - buffer) - n, SEEK_CUR) == -1)
1299 fatal_error("cannot seek header");
1304 if (fseeko(fp, -n, SEEK_CUR) == -1)
1305 fatal_error("cannot seek header");
1310 /* remove leading `xxxx/..' */
1312 remove_leading_dots(char *path)
1317 if (strcmp(first, "..") == 0) {
1318 warning("Removing leading `..' from member name.");
1319 return first+1; /* change to "." */
1322 if (strstr(first, "..") == 0)
1325 while (path && *path) {
1327 if (strcmp(path, "..") == 0)
1328 ptr = path = path+2;
1329 else if (strncmp(path, "../", 3) == 0)
1330 ptr = path = path+3;
1332 path = strchr(path, '/');
1334 if (path && *path == '/') {
1340 warning("Removing leading `%.*s' from member name.", ptr-first, first);
1348 copy_path_element(char *dst, const char *src, int size)
1352 if (size < 1) return 0;
1354 for (i = 0; i < size; i++) {
1358 if (dst[i] == '/') {
1372 remove leading "xxx/../"
1373 remove "./", "././", "././ ... ./"
1374 remove duplicated "/"
1377 canon_path(char *newpath, char *path, size_t size)
1381 path = remove_leading_dots(path);
1384 if (path[0] == '.' && path[1] == '/')
1388 len = copy_path_element(newpath, path, size);
1397 /* remove duplicated '/' */
1398 while (*path == '/') path++;
1401 /* When newpath is empty, set "." */
1403 strcpy(newpath, ".");
1407 return newpath - p; /* string length */
1411 init_header(name, v_stat, hdr)
1413 struct stat *v_stat;
1418 memset(hdr, 0, sizeof(LzHeader));
1420 /* the `method' member is rewrote by the encoding function.
1421 but need set for empty files */
1422 memcpy(hdr->method, LZHUFF0_METHOD, METHOD_TYPE_STORAGE);
1424 hdr->packed_size = 0;
1425 hdr->original_size = v_stat->st_size;
1426 hdr->attribute = GENERIC_ATTRIBUTE;
1427 hdr->header_level = header_level;
1429 len = canon_path(hdr->name, name, sizeof(hdr->name));
1432 hdr->extend_type = EXTEND_UNIX;
1433 hdr->unix_last_modified_stamp = v_stat->st_mtime;
1434 /* since 00:00:00 JAN.1.1970 */
1435 #ifdef NOT_COMPATIBLE_MODE
1436 /* Please need your modification in this space. */
1439 if (S_ISREG(v_stat->st_mode))
1440 hdr->unix_mode = hdr->unix_mode | UNIX_FILE_REGULAR;
1441 if (S_ISDIR(v_stat->st_mode))
1442 hdr->unix_mode = hdr->unix_mode | UNIX_FILE_DIRECTORY;
1443 if (S_ISLNK(v_stat->st_mode))
1444 hdr->unix_mode = hdr->unix_mode | UNIX_FILE_SYMLINK;
1445 if (v_stat->st_mode & S_IRUSR)
1446 hdr->unix_mode = hdr->unix_mode | UNIX_OWNER_READ_PERM;
1447 if (v_stat->st_mode & S_IRGRP)
1448 hdr->unix_mode = hdr->unix_mode | UNIX_GROUP_READ_PERM;
1449 if (v_stat->st_mode & S_IROTH)
1450 hdr->unix_mode = hdr->unix_mode | UNIX_OTHER_READ_PERM;
1451 if (v_stat->st_mode & S_IWUSR)
1452 hdr->unix_mode = hdr->unix_mode | UNIX_OWNER_WRITE_PERM;
1453 if (v_stat->st_mode & S_IWGRP)
1454 hdr->unix_mode = hdr->unix_mode | UNIX_GROUP_WRITE_PERM;
1455 if (v_stat->st_mode & S_IWOTH)
1456 hdr->unix_mode = hdr->unix_mode | UNIX_OTHER_WRITE_PERM;
1457 if (v_stat->st_mode & S_IXUSR)
1458 hdr->unix_mode = hdr->unix_mode | UNIX_OWNER_EXEC_PERM;
1459 if (v_stat->st_mode & S_IXGRP)
1460 hdr->unix_mode = hdr->unix_mode | UNIX_GROUP_EXEC_PERM;
1461 if (v_stat->st_mode & S_IXOTH)
1462 hdr->unix_mode = hdr->unix_mode | UNIX_OTHER_EXEC_PERM;
1463 if (v_stat->st_mode & S_ISUID)
1464 hdr->unix_mode = hdr->unix_mode | UNIX_SETUID;
1465 if (v_stat->st_mode & S_ISGID)
1466 hdr->unix_mode = hdr->unix_mode | UNIX_SETGID;
1467 #endif /* __DJGPP__ */
1469 hdr->unix_mode = v_stat->st_mode;
1472 hdr->unix_uid = v_stat->st_uid;
1473 hdr->unix_gid = v_stat->st_gid;
1475 #if INCLUDE_OWNER_NAME_IN_HEADER
1478 struct passwd *ent = getpwuid(hdr->unix_uid);
1481 strncpy(hdr->user, ent->pw_name, sizeof(hdr->user));
1482 if (hdr->user[sizeof(hdr->user)-1])
1483 hdr->user[sizeof(hdr->user)-1] = 0;
1489 struct group *ent = getgrgid(hdr->unix_gid);
1492 strncpy(hdr->group, ent->gr_name, sizeof(hdr->group));
1493 if (hdr->group[sizeof(hdr->group)-1])
1494 hdr->group[sizeof(hdr->group)-1] = 0;
1498 #endif /* INCLUDE_OWNER_NAME_IN_HEADER */
1499 if (is_directory(v_stat)) {
1500 memcpy(hdr->method, LZHDIRS_METHOD, METHOD_TYPE_STORAGE);
1501 hdr->attribute = GENERIC_DIRECTORY_ATTRIBUTE;
1502 hdr->original_size = 0;
1503 if (len > 0 && hdr->name[len - 1] != '/') {
1504 if (len < sizeof(hdr->name)-1)
1505 strcpy(&hdr->name[len++], "/"); /* ok */
1507 warning("the length of dirname \"%s\" is too long.",
1513 if (is_symlink(v_stat)) {
1514 memcpy(hdr->method, LZHDIRS_METHOD, METHOD_TYPE_STORAGE);
1515 hdr->attribute = GENERIC_DIRECTORY_ATTRIBUTE;
1516 hdr->original_size = 0;
1517 readlink(name, hdr->realname, sizeof(hdr->realname));
1523 write_unix_info(hdr)
1526 /* UNIX specific informations */
1528 put_word(5); /* size */
1529 put_byte(0x50); /* permission */
1530 put_word(hdr->unix_mode);
1532 put_word(7); /* size */
1533 put_byte(0x51); /* gid and uid */
1534 put_word(hdr->unix_gid);
1535 put_word(hdr->unix_uid);
1537 if (hdr->group[0]) {
1538 int len = strlen(hdr->group);
1539 put_word(len + 3); /* size */
1540 put_byte(0x52); /* group name */
1541 put_bytes(hdr->group, len);
1545 int len = strlen(hdr->user);
1546 put_word(len + 3); /* size */
1547 put_byte(0x53); /* user name */
1548 put_bytes(hdr->user, len);
1551 if (hdr->header_level == 1) {
1552 put_word(7); /* size */
1553 put_byte(0x54); /* time stamp */
1554 put_longword(hdr->unix_last_modified_stamp);
1559 write_header_level0(data, hdr, pathname)
1561 char *data, *pathname;
1568 memset(data, 0, LZHEADER_STORAGE);
1570 put_byte(0x00); /* header size */
1571 put_byte(0x00); /* check sum */
1572 put_bytes(hdr->method, 5);
1573 put_longword(hdr->packed_size);
1574 put_longword(hdr->original_size);
1575 put_longword(unix_to_generic_stamp(hdr->unix_last_modified_stamp));
1576 put_byte(hdr->attribute);
1577 put_byte(hdr->header_level); /* level 0 */
1579 /* write pathname (level 0 header contains the directory part) */
1580 name_length = strlen(pathname);
1582 limit = 255 - I_GENERIC_HEADER_SIZE + 2;
1584 limit = 255 - I_LEVEL0_HEADER_SIZE + 2;
1586 if (name_length > limit) {
1587 warning("the length of pathname \"%s\" is too long.", pathname);
1588 name_length = limit;
1590 put_byte(name_length);
1591 put_bytes(pathname, name_length);
1594 if (generic_format) {
1595 header_size = I_GENERIC_HEADER_SIZE + name_length - 2;
1596 data[I_HEADER_SIZE] = header_size;
1597 data[I_HEADER_CHECKSUM] = calc_sum(data + I_METHOD, header_size);
1599 /* write old-style extend header */
1600 put_byte(EXTEND_UNIX);
1601 put_byte(CURRENT_UNIX_MINOR_VERSION);
1602 put_longword(hdr->unix_last_modified_stamp);
1603 put_word(hdr->unix_mode);
1604 put_word(hdr->unix_uid);
1605 put_word(hdr->unix_gid);
1607 /* size of extended header is 12 */
1608 header_size = I_LEVEL0_HEADER_SIZE + name_length - 2;
1609 data[I_HEADER_SIZE] = header_size;
1610 data[I_HEADER_CHECKSUM] = calc_sum(data + I_METHOD, header_size);
1613 return header_size + 2;
1617 write_header_level1(data, hdr, pathname)
1619 char *data, *pathname;
1621 int name_length, dir_length, limit;
1622 char *basename, *dirname;
1624 char *extend_header_top;
1625 size_t extend_header_size;
1627 basename = strrchr(pathname, LHA_PATHSEP);
1630 name_length = strlen(basename);
1632 dir_length = basename - dirname;
1635 basename = pathname;
1636 name_length = strlen(basename);
1642 memset(data, 0, LZHEADER_STORAGE);
1644 put_byte(0x00); /* header size */
1645 put_byte(0x00); /* check sum */
1646 put_bytes(hdr->method, 5);
1647 put_longword(hdr->packed_size);
1648 put_longword(hdr->original_size);
1649 put_longword(unix_to_generic_stamp(hdr->unix_last_modified_stamp));
1651 put_byte(hdr->header_level); /* level 1 */
1653 /* level 1 header: write filename (basename only) */
1654 limit = 255 - I_LEVEL1_HEADER_SIZE + 2;
1655 if (name_length > limit) {
1656 put_byte(0); /* name length */
1659 put_byte(name_length);
1660 put_bytes(basename, name_length);
1668 put_byte(EXTEND_UNIX);
1670 /* write extend header from here. */
1672 extend_header_top = put_ptr+2; /* +2 for the field `next header size' */
1673 header_size = extend_header_top - data - 2;
1675 /* write filename and dirname */
1677 if (name_length > limit) {
1678 put_word(name_length + 3); /* size */
1679 put_byte(0x01); /* filename */
1680 put_bytes(basename, name_length);
1683 if (dir_length > 0) {
1684 put_word(dir_length + 3); /* size */
1685 put_byte(0x02); /* dirname */
1686 put_bytes(dirname, dir_length);
1689 if (!generic_format)
1690 write_unix_info(hdr);
1692 put_word(0x0000); /* next header size */
1694 extend_header_size = put_ptr - extend_header_top;
1695 /* On level 1 header, the packed size field is contains the ext-header */
1696 hdr->packed_size += put_ptr - extend_header_top;
1698 /* put `skip size' */
1699 setup_put(data + I_PACKED_SIZE);
1700 put_longword(hdr->packed_size);
1702 data[I_HEADER_SIZE] = header_size;
1703 data[I_HEADER_CHECKSUM] = calc_sum(data + I_METHOD, header_size);
1705 return header_size + extend_header_size + 2;
1709 write_header_level2(data, hdr, pathname)
1711 char *data, *pathname;
1713 int name_length, dir_length;
1714 char *basename, *dirname;
1716 char *extend_header_top;
1717 char *headercrc_ptr;
1720 basename = strrchr(pathname, LHA_PATHSEP);
1723 name_length = strlen(basename);
1725 dir_length = basename - dirname;
1728 basename = pathname;
1729 name_length = strlen(basename);
1735 memset(data, 0, LZHEADER_STORAGE);
1737 put_word(0x0000); /* header size */
1738 put_bytes(hdr->method, 5);
1739 put_longword(hdr->packed_size);
1740 put_longword(hdr->original_size);
1741 put_longword(hdr->unix_last_modified_stamp);
1743 put_byte(hdr->header_level); /* level 2 */
1750 put_byte(EXTEND_UNIX);
1752 /* write extend header from here. */
1754 extend_header_top = put_ptr+2; /* +2 for the field `next header size' */
1756 /* write common header */
1759 headercrc_ptr = put_ptr;
1760 put_word(0x0000); /* header CRC */
1762 /* write filename and dirname */
1763 /* must have this header, even if the name_length is 0. */
1764 put_word(name_length + 3); /* size */
1765 put_byte(0x01); /* filename */
1766 put_bytes(basename, name_length);
1768 if (dir_length > 0) {
1769 put_word(dir_length + 3); /* size */
1770 put_byte(0x02); /* dirname */
1771 put_bytes(dirname, dir_length);
1774 if (!generic_format)
1775 write_unix_info(hdr);
1777 put_word(0x0000); /* next header size */
1779 header_size = put_ptr - data;
1780 if ((header_size & 0xff) == 0) {
1781 /* cannot put zero at the first byte on level 2 header. */
1782 /* adjust header size. */
1783 put_byte(0); /* padding */
1787 /* put header size */
1788 setup_put(data + I_HEADER_SIZE);
1789 put_word(header_size);
1791 /* put header CRC in extended header */
1792 INITIALIZE_CRC(hcrc);
1793 hcrc = calccrc(hcrc, data, (unsigned int) header_size);
1794 setup_put(headercrc_ptr);
1801 write_header(fp, hdr)
1806 char data[LZHEADER_STORAGE];
1808 int archive_kanji_code = CODE_SJIS;
1809 int system_kanji_code = default_system_kanji_code;
1810 char *archive_delim = "\377";
1811 char *system_delim = "/";
1812 int filename_case = NONE;
1813 char pathname[FILENAME_LENGTH];
1815 if (optional_archive_kanji_code)
1816 archive_kanji_code = optional_archive_kanji_code;
1817 if (optional_system_kanji_code)
1818 system_kanji_code = optional_system_kanji_code;
1820 if (generic_format && convertcase)
1821 filename_case = TO_UPPER;
1823 if (hdr->header_level == 0) {
1824 archive_delim = "\\";
1827 if ((hdr->unix_mode & UNIX_FILE_SYMLINK) == UNIX_FILE_SYMLINK) {
1829 p = strchr(hdr->name, '|');
1831 error("symlink name \"%s\" contains '|' char. change it into '_'",
1835 if (xsnprintf(pathname, sizeof(pathname),
1836 "%s|%s", hdr->name, hdr->realname) == -1)
1837 error("file name is too long (%s -> %s)", hdr->name, hdr->realname);
1840 strncpy(pathname, hdr->name, sizeof(pathname));
1841 pathname[sizeof(pathname)-1] = 0;
1844 convert_filename(pathname, strlen(pathname), sizeof(pathname),
1847 system_delim, archive_delim, filename_case);
1849 switch (hdr->header_level) {
1851 header_size = write_header_level0(data, hdr, pathname);
1854 header_size = write_header_level1(data, hdr, pathname);
1857 header_size = write_header_level2(data, hdr, pathname);
1860 error("Unknown level header (level %d)", hdr->header_level);
1864 if (fwrite(data, header_size, 1, fp) == 0)
1865 fatal_error("Cannot write to temporary file");
1868 #if MULTIBYTE_FILENAME
1870 #if defined(__APPLE__) /* Added by Hiroto Sakai */
1872 #include <CoreFoundation/CFString.h>
1873 #include <CoreFoundation/CFStringEncodingExt.h>
1875 /* this is not need for Mac OS X v 10.2 later */
1877 kCFStringEncodingAllowLossyConversion = 1,
1878 kCFStringEncodingBasicDirectionLeftToRight = (1 << 1),
1879 kCFStringEncodingBasicDirectionRightToLeft = (1 << 2),
1880 kCFStringEncodingSubstituteCombinings = (1 << 3),
1881 kCFStringEncodingComposeCombinings = (1 << 4),
1882 kCFStringEncodingIgnoreCombinings = (1 << 5),
1883 kCFStringEncodingUseCanonical = (1 << 6),
1884 kCFStringEncodingUseHFSPlusCanonical = (1 << 7),
1885 kCFStringEncodingPrependBOM = (1 << 8),
1886 kCFStringEncodingDisableCorporateArea = (1 << 9),
1887 kCFStringEncodingASCIICompatibleConversion = (1 << 10),
1891 ConvertEncodingToUTF8(const char* inCStr,
1892 char* outUTF8Buffer,
1893 int outUTF8BufferLength,
1894 unsigned long scriptEncoding,
1895 unsigned long flags)
1897 unsigned long unicodeChars;
1898 unsigned long srcCharsUsed;
1899 unsigned long usedByteLen = 0;
1900 UniChar uniStr[512];
1901 unsigned long cfResult;
1903 cfResult = CFStringEncodingBytesToUnicode(scriptEncoding,
1911 if (cfResult == 0) {
1912 cfResult = CFStringEncodingUnicodeToBytes(kCFStringEncodingUTF8,
1917 (char*)outUTF8Buffer,
1918 outUTF8BufferLength - 1,
1920 outUTF8Buffer[usedByteLen] = '\0';
1927 ConvertUTF8ToEncoding(const char* inUTF8Buf,
1928 int inUTF8BufLength,
1929 char* outCStrBuffer,
1930 int outCStrBufferLength,
1931 unsigned long scriptEncoding,
1932 unsigned long flags)
1934 unsigned long unicodeChars;
1935 unsigned long srcCharsUsed;
1936 unsigned long usedByteLen = 0;
1937 UniChar uniStr[256];
1938 unsigned long cfResult;
1940 cfResult = CFStringEncodingBytesToUnicode(kCFStringEncodingUTF8,
1948 if (cfResult == 0) {
1949 cfResult = CFStringEncodingUnicodeToBytes(scriptEncoding,
1954 (char*)outCStrBuffer,
1955 outCStrBufferLength - 1,
1957 outCStrBuffer[usedByteLen] = '\0';
1967 ConvertEncodingByIconv(const char *src, char *dst, int dstsize,
1968 const char *srcEnc, const char *dstEnc)
1971 static char szTmpBuf[2048];
1977 dst_p = &szTmpBuf[0];
1978 iLen = (size_t)sizeof(szTmpBuf)-1;
1979 src_p = (char *)src;
1980 sLen = (size_t)strlen(src);
1981 memset(szTmpBuf, 0, sizeof(szTmpBuf));
1982 memset(dst, 0, dstsize);
1984 ic = iconv_open(dstEnc, srcEnc);
1985 if (ic == (iconv_t)-1) {
1986 error("iconv_open() failure: %s", strerror(errno));
1990 if (iconv(ic, &src_p, &sLen, &dst_p, &iLen) == (size_t)-1) {
1991 error("iconv() failure: %s", strerror(errno));
1996 strncpy(dst, szTmpBuf, dstsize);
2002 #endif /* defined(__APPLE__) */
2005 sjis_to_utf8(char *dst, const char *src, size_t dstsize)
2007 #if defined(__APPLE__)
2009 if (ConvertEncodingToUTF8(src, dst, dstsize,
2010 kCFStringEncodingDOSJapanese,
2011 kCFStringEncodingUseHFSPlusCanonical) == 0)
2014 if (ConvertEncodingByIconv(src, dst, dstsize, "SJIS", "UTF-8") != -1)
2017 error("not support utf-8 conversion");
2020 if (dstsize < 1) return dst;
2022 return strncpy(dst, src, dstsize-1);
2026 utf8_to_sjis(char *dst, const char *src, size_t dstsize)
2028 #if defined(__APPLE__)
2032 srclen = strlen(src);
2033 if (ConvertUTF8ToEncoding(src, srclen, dst, dstsize,
2034 kCFStringEncodingDOSJapanese,
2035 kCFStringEncodingUseHFSPlusCanonical) == 0)
2038 if (ConvertEncodingByIconv(src, dst, dstsize, "UTF-8", "SJIS") != -1)
2041 error("not support utf-8 conversion");
2044 if (dstsize < 1) return dst;
2046 return strncpy(dst, src, dstsize-1);
2051 * 「日本語情報処理」 ソフトバンク(株)
2052 * より抜粋(by Koji Arai)
2055 euc2sjis(int *p1, int *p2)
2057 unsigned char c1 = *p1 & 0x7f;
2058 unsigned char c2 = *p2 & 0x7f;
2059 int rowoff = c1 < 0x5f ? 0x70 : 0xb0;
2060 int celoff = c1 % 2 ? (c2 > 0x5f ? 0x20 : 0x1f) : 0x7e;
2061 *p1 = ((c1 + 1) >> 1) + rowoff;
2062 *p2 += celoff - 0x80;
2066 sjis2euc(int *p1, int *p2)
2068 unsigned char c1 = *p1;
2069 unsigned char c2 = *p2;
2070 int adjust = c2 < 0x9f;
2071 int rowoff = c1 < 0xa0 ? 0x70 : 0xb0;
2072 int celoff = adjust ? (c2 > 0x7f ? 0x20 : 0x1f) : 0x7e;
2073 *p1 = ((c1 - rowoff) << 1) - adjust;
2084 case '0': case '1': case '2': case '3': case '4':
2085 case '5': case '6': case '7': case '8': case '9':
2088 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
2089 return c - 'a' + 10;
2091 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
2092 return c - 'A' + 10;
2102 case 0: case 1: case 2: case 3: case 4:
2103 case 5: case 6: case 7: case 8: case 9:
2106 case 10: case 11: case 12: case 13: case 14: case 15:
2107 return c + 'a' - 10;
2115 cap_to_sjis(char *dst, const char *src, size_t dstsize)
2118 size_t len = strlen(src);
2121 for (i = j = 0; i < len && i < dstsize; i++) {
2122 if (src[i] != ':') {
2128 a = hex2int((unsigned char)src[i]);
2129 b = hex2int((unsigned char)src[i+1]);
2131 if (a == -1 || b == -1) {
2134 strncpy(dst+j, src+i, dstsize-j);
2141 dst[j++] = a * 16 + b;
2148 sjis_to_cap(char *dst, const char *src, size_t dstsize)
2151 size_t len = strlen(src);
2154 for (i = j = 0; i < len && i < dstsize; i++) {
2155 if (src[i] == ':') {
2156 strncpy(dst+j, ":3a", dstsize-j);
2161 if (isprint(src[i])) {
2166 if (j + 3 >= dstsize) {
2171 a = int2hex((unsigned char)src[i] / 16);
2172 b = int2hex((unsigned char)src[i] % 16);
2181 #endif /* MULTIBYTE_FILENAME */