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 /* ------------------------------------------------------------------------ */
16 #if !STRCHR_8BIT_CLEAN
17 /* should use 8 bit clean version */
20 #define strchr xstrchr
21 #define strrchr xstrrchr
24 /* ------------------------------------------------------------------------ */
26 #define setup_get(PTR) (get_ptr = (PTR))
27 #define get_byte() (*get_ptr++ & 0xff)
28 #define put_ptr get_ptr
29 #define setup_put(PTR) (put_ptr = (PTR))
30 #define put_byte(c) (*put_ptr++ = (char)(c))
32 int optional_archive_kanji_code = NONE;
33 int optional_system_kanji_code = NONE;
34 char *optional_archive_delim = NULL;
35 char *optional_system_delim = NULL;
36 int optional_filename_case = NONE;
38 #ifdef MULTIBYTE_FILENAME
39 int default_system_kanji_code = MULTIBYTE_FILENAME;
41 int default_system_kanji_code = NONE;
44 /* ------------------------------------------------------------------------ */
52 for (sum = 0; len; len--)
58 /* ------------------------------------------------------------------------ */
66 return (b1 << 8) + b0;
69 /* ------------------------------------------------------------------------ */
78 /* ------------------------------------------------------------------------ */
88 return (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
91 /* ------------------------------------------------------------------------ */
103 get_bytes(buf, len, size)
108 for (i = 0; i < len && i < size; i++)
120 for (i = 0; i < len; i++)
124 /* added by Koji Arai */
126 convert_filename(name, len, size,
128 from_delim, to_delim,
133 int from_code, to_code, case_to;
134 char *from_delim, *to_delim;
138 #ifdef MULTIBYTE_FILENAME
139 char tmp[FILENAME_LENGTH];
141 if (from_code == CODE_SJIS && to_code == CODE_UTF8) {
142 for (i = 0; i < len; i++)
143 /* FIXME: provisionally fix for the Mac OS CoreFoundation */
144 if ((unsigned char)name[i] == LHA_PATHSEP) name[i] = '/';
145 sjis_to_utf8(tmp, name, sizeof(tmp));
146 strncpy(name, tmp, size);
149 for (i = 0; i < len; i++)
150 if (name[i] == '/') name[i] = LHA_PATHSEP;
151 from_code = CODE_UTF8;
153 else if (from_code == CODE_UTF8 && to_code == CODE_SJIS) {
154 for (i = 0; i < len; i++)
155 /* FIXME: provisionally fix for the Mac OS CoreFoundation */
156 if ((unsigned char)name[i] == LHA_PATHSEP) name[i] = '/';
157 utf8_to_sjis(tmp, name, sizeof(tmp));
158 strncpy(name, tmp, size);
161 for (i = 0; i < len; i++)
162 if (name[i] == '/') name[i] = LHA_PATHSEP;
163 from_code = CODE_SJIS;
167 for (i = 0; i < len; i ++) {
168 #ifdef MULTIBYTE_FILENAME
169 if (from_code == CODE_EUC &&
170 (unsigned char)name[i] == 0x8e) {
171 if (to_code != CODE_SJIS) {
177 memmove(name + i, name + i + 1, len - i);
181 if (from_code == CODE_SJIS && X0201_KANA_P(name[i])) {
182 if (to_code != CODE_EUC) {
186 if (len == size - 1) /* check overflow */
188 memmove(name+i+1, name+i, len-i);
194 if (from_code == CODE_EUC && (name[i] & 0x80) && (name[i+1] & 0x80)) {
196 if (to_code != CODE_SJIS) {
201 c1 = (unsigned char)name[i];
202 c2 = (unsigned char)name[i+1];
209 if (from_code == CODE_SJIS &&
210 SJC_FIRST_P(name[i]) &&
211 SJC_SECOND_P(name[i+1])) {
214 if (to_code != CODE_EUC) {
219 c1 = (unsigned char)name[i];
220 c2 = (unsigned char)name[i+1];
227 #endif /* MULTIBYTE_FILENAME */
231 /* transpose from_delim to to_delim */
233 if ((ptr = strchr(from_delim, name[i])) != NULL) {
234 name[i] = to_delim[ptr - from_delim];
239 if (case_to == TO_UPPER && islower(name[i])) {
240 name[i] = toupper(name[i]);
243 if (case_to == TO_LOWER && isupper(name[i])) {
244 name[i] = tolower(name[i]);
250 /* ------------------------------------------------------------------------ */
252 /* Generic stamp format: */
254 /* 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 */
255 /* |<-------- year ------->|<- month ->|<-- day -->| */
257 /* 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 */
258 /* |<--- hour --->|<---- minute --->|<- second*2 ->| */
260 /* ------------------------------------------------------------------------ */
263 * NOTE : If you don't have `gettimeofday(2)', or your gettimeofday(2)
264 * returns bogus timezone information, try FTIME, MKTIME, TIMELOCAL or TZSET.
268 #if defined(HAVE_MKTIME)
269 #ifdef HAVE_TIMELOCAL
270 #undef HAVE_TIMELOCAL
272 #endif /* defined(HAVE_MKTIME) */
274 #if defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL)
278 #endif /* defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL) */
280 #if defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL) || defined(HAVE_TZSET)
286 #if defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL) || defined(HAVE_TZSET) || defined(HAVE_FTIME)
287 #ifdef HAVE_GETTIMEOFDAY
288 #undef HAVE_GETTIMEOFDAY
291 #ifndef HAVE_GETTIMEOFDAY
292 #define HAVE_GETTIMEOFDAY /* use gettimeofday() */
297 #include <sys/timeb.h>
301 * You may define as : #define TIMEZONE_HOOK \ extern long
302 * timezone ; \ extern void tzset();
306 /* Which do you like better, `TIMEZONE_HOOK' or `TIMEZONE_HOOK;' ? */
309 #if defined(HAVE_TZSET) && defined(_MINIX)
310 extern long timezone; /* not defined in time.h */
313 /* ------------------------------------------------------------------------ */
314 #if defined(HAVE_FTIME) || defined(HAVE_GETTIMEOFDAY) || defined(HAVE_TZSET)
324 /* ------------------------------------------------------------------------ */
325 #if !defined(HAVE_TZSET) && defined(HAVE_FTIME)
330 return buf.timezone * 60L;
334 /* ------------------------------------------------------------------------ */
335 #if !defined(HAVE_TZSET) && !defined(HAVE_FTIME) /* maybe defined(HAVE_GETTIMEOFDAY) */
337 #ifdef HAVE_STRUCT_TM_TM_GMTOFF
341 return -localtime(&tt)->tm_gmtoff;
342 #else /* HAVE_STRUCT_TM_TM_GMTOFF */
345 gettimeofday(&tp, &tzp);/* specific to 4.3BSD */
347 * return (tzp.tz_minuteswest * 60L + (tzp.tz_dsttime != 0 ? 60L *
350 return (tzp.tz_minuteswest * 60L);
351 #endif /* HAVE_STRUCT_TM_TM_GMTOFF */
354 #endif /* defined(HAVE_FTIME) || defined(HAVE_GETTIMEOFDAY) ||
355 * defined(HAVE_TZSET) */
357 /* ------------------------------------------------------------------------ */
359 generic_to_unix_stamp(t)
361 #if defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL)
366 * special case: if MSDOS format date and time were zero, then we
367 * set time to be zero here too.
372 dostm.tm_sec = (t & 0x1f) * 2;
373 dostm.tm_min = t >> 5 & 0x3f;
374 dostm.tm_hour = t >> 11 & 0x1f;
375 dostm.tm_mday = t >> 16 & 0x1f;
376 dostm.tm_mon = (t >> (16+5) & 0x0f) - 1; /* 0..11 */
377 dostm.tm_year = (t >> (16+9) & 0x7f) + 80;
379 dostm.tm_isdst = 0; /* correct? */
381 dostm.tm_isdst = -1; /* correct? */
383 return (time_t) mktime(&dostm);
384 #else /* maybe defined(HAVE_TIMELOCAL) */
385 return (time_t) timelocal(&dostm);
389 #else /* defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL) */
391 int year, month, day, hour, min, sec;
393 static unsigned int dsboy[12] = {0, 31, 59, 90, 120, 151,
394 181, 212, 243, 273, 304, 334};
398 * special case: if MSDOS format date and time were zero, then we
399 * set time to be zero here too.
404 year = ((int) (t >> 16 + 9) & 0x7f) + 1980;
405 month = (int) (t >> 16 + 5) & 0x0f; /* 1..12 means Jan..Dec */
406 day = (int) (t >> 16) & 0x1f; /* 1..31 means 1st,...31st */
408 hour = ((int) t >> 11) & 0x1f;
409 min = ((int) t >> 5) & 0x3f;
410 sec = ((int) t & 0x1f) * 2;
412 /* Calculate days since 1970.01.01 */
413 days = (365 * (year - 1970) + /* days due to whole years */
414 (year - 1970 + 1) / 4 + /* days due to leap years */
415 dsboy[month - 1] + /* days since beginning of this year */
416 day - 1); /* days since beginning of month */
418 if ((year % 4 == 0) &&
419 (year % 100 != 0 || year % 400 == 0) && /* 1999.5.24 t.oka */
420 (month >= 3)) /* if this is a leap year and month */
421 days++; /* is March or later, add a day */
423 /* Knowing the days, we can find seconds */
424 longtime = (((days * 24) + hour) * 60 + min) * 60 + sec;
425 longtime += gettz(); /* adjust for timezone */
427 /* LONGTIME is now the time in seconds, since 1970/01/01 00:00:00. */
428 return (time_t) longtime;
430 #endif /* defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL) */
432 /* ------------------------------------------------------------------------ */
434 unix_to_generic_stamp(t)
437 struct tm *tm = localtime(&t);
439 return ((((long) (tm->tm_year - 80)) << 25) +
440 (((long) (tm->tm_mon + 1)) << 21) +
441 (((long) tm->tm_mday) << 16) +
442 (long) ((tm->tm_hour << 11) +
447 /* ------------------------------------------------------------------------ */
448 /* build header functions */
449 /* ------------------------------------------------------------------------ */
455 * --------------------------------
457 * 2 next-header size [*1]
458 * --------------------------------------
459 * ext header: 1 ext-type ^
460 * ? contents | [*1] next-header size
461 * 2 next-header size v
462 * --------------------------------------
466 get_extended_header(fp, hdr, header_size)
471 char data[LZHEADER_STORAGE];
473 char dirname[FILENAME_LENGTH];
476 int whole_size = header_size;
478 if (hdr->header_level == 0)
481 name_length = strlen(hdr->name);
483 for (; header_size != 0; whole_size += header_size = get_word()) {
485 if (sizeof(data) < header_size) {
486 error("header size too large.");
490 if (fread(data, header_size, 1, fp) == 0) {
491 error("Invalid header (LHa file ?)");
494 switch (get_byte()) {
497 setup_get(get_ptr + header_size - 3); /* FIXME: ignored? */
502 get_bytes(hdr->name, header_size-3, sizeof(hdr->name)-1);
503 hdr->name[name_length] = 0;
507 dir_length = get_bytes(dirname, header_size-3, sizeof(dirname)-1);
508 dirname[dir_length] = 0;
511 /* MS-DOS attribute */
512 if (hdr->extend_type == EXTEND_MSDOS ||
513 hdr->extend_type == EXTEND_HUMAN ||
514 hdr->extend_type == EXTEND_GENERIC)
515 hdr->attribute = get_word();
518 /* UNIX permission */
519 if (hdr->extend_type == EXTEND_UNIX)
520 hdr->unix_mode = get_word();
523 /* UNIX gid and uid */
524 if (hdr->extend_type == EXTEND_UNIX) {
525 hdr->unix_gid = get_word();
526 hdr->unix_uid = get_word();
530 /* UNIX group name */
531 if (hdr->extend_type == EXTEND_UNIX) {
532 i = get_bytes(hdr->group, header_size-3, sizeof(hdr->group)-1);
533 hdr->group[i] = '\0';
538 if (hdr->extend_type == EXTEND_UNIX) {
539 i = get_bytes(hdr->user, header_size-3, sizeof(hdr->user)-1);
544 /* UNIX last modified time */
545 if (hdr->extend_type == EXTEND_UNIX)
546 hdr->unix_last_modified_stamp = (time_t) get_longword();
550 setup_get(get_ptr + header_size - 3);
556 if (name_length + dir_length >= sizeof(hdr->name)) {
557 warning("the length of pathname \"%s%s\" is too long.",
559 name_length = sizeof(hdr->name) - dir_length - 1;
560 hdr->name[name_length] = 0;
562 strcat(dirname, hdr->name);
563 strcpy(hdr->name, dirname);
564 name_length += dir_length;
574 * offset size field name
575 * ----------------------------------
576 * 0 1 header size [*1]
578 * ---------------------------------------
580 * 7 4 packed size [*2] |
581 * 11 4 original size |
584 * 19 1 attribute | [*1] header size (X+Y+22)
585 * 20 1 level (0x00 fixed) |
589 * X +24 Y ext-header(old style) v
590 * -------------------------------------------------
594 * ext-header(old style)
608 * bit6 archive bit (need to backup)
612 get_header_level0(fp, hdr, data)
623 hdr->header_size = header_size = get_byte();
624 checksum = get_byte();
626 if (fread(data+I_NAME_LENGTH, header_size+2-I_NAME_LENGTH, 1, fp) == 0) {
627 error("Invalid header (LHarc file ?)");
628 return FALSE; /* finish */
631 if (calc_sum(data + I_METHOD, header_size) != checksum) {
632 error("Checksum error (LHarc file?)");
636 get_bytes(hdr->method, 5, sizeof(hdr->method));
637 hdr->packed_size = get_longword();
638 hdr->original_size = get_longword();
639 hdr->unix_last_modified_stamp = generic_to_unix_stamp(get_longword());
640 hdr->attribute = get_byte(); /* MS-DOS attribute */
641 hdr->header_level = get_byte();
642 name_length = get_byte();
643 i = get_bytes(hdr->name, name_length, sizeof(hdr->name)-1);
646 /* defaults for other type */
647 hdr->unix_mode = UNIX_FILE_REGULAR | UNIX_RW_RW_RW;
651 extend_size = header_size+2 - name_length - 24;
653 if (extend_size < 0) {
654 if (extend_size == -2) {
655 /* CRC field is not given */
656 hdr->extend_type = EXTEND_GENERIC;
657 hdr->has_crc = FALSE;
662 error("Unkonwn header (lha file?)");
667 hdr->crc = get_word();
669 if (extend_size == 0)
672 hdr->extend_type = get_byte();
675 if (hdr->extend_type == EXTEND_UNIX) {
676 if (extend_size >= 11) {
677 hdr->minor_version = get_byte();
678 hdr->unix_last_modified_stamp = (time_t) get_longword();
679 hdr->unix_mode = get_word();
680 hdr->unix_uid = get_word();
681 hdr->unix_gid = get_word();
684 hdr->extend_type = EXTEND_GENERIC;
688 setup_get(get_ptr + extend_size);
697 * offset size field name
698 * -----------------------------------
699 * 0 1 header size [*1]
701 * -------------------------------------
703 * 7 4 skip size [*2] |
704 * 11 4 original size |
707 * 19 1 attribute (0x20 fixed) | [*1] header size (X+Y+25)
708 * 20 1 level (0x01 fixed) |
714 * X+Y+25 2 next-header size v
715 * -------------------------------------------------
716 * X+Y+27 Z ext-header ^
718 * ----------------------------------- | [*2] skip size
721 * -------------------------------------------------
725 get_header_level1(fp, hdr, data)
730 int header_size, extend_size;
735 hdr->header_size = header_size = get_byte();
736 checksum = get_byte();
738 if (fread(data+I_NAME_LENGTH, header_size+2-I_NAME_LENGTH, 1, fp) == 0) {
739 error("Invalid header (LHarc file ?)");
740 return FALSE; /* finish */
743 if (calc_sum(data + I_METHOD, header_size) != checksum) {
744 error("Checksum error (LHarc file?)");
748 get_bytes(hdr->method, 5, sizeof(hdr->method));
749 hdr->packed_size = get_longword(); /* skip size */
750 hdr->original_size = get_longword();
751 hdr->unix_last_modified_stamp = generic_to_unix_stamp(get_longword());
752 hdr->attribute = get_byte(); /* 0x20 fixed */
753 hdr->header_level = get_byte();
755 name_length = get_byte();
756 i = get_bytes(hdr->name, name_length, sizeof(hdr->name)-1);
759 /* defaults for other type */
760 hdr->unix_mode = UNIX_FILE_REGULAR | UNIX_RW_RW_RW;
765 hdr->crc = get_word();
766 hdr->extend_type = get_byte();
768 dummy = header_size+2 - name_length - 27;
770 setup_get(get_ptr + dummy); /* skip old style extend header */
772 extend_size = get_word();
773 extend_size = get_extended_header(fp, hdr, extend_size);
774 if (extend_size == -1)
777 /* On level 1 header, size fields should be adjusted. */
778 /* the `packed_size' field contains the extended header size. */
779 /* the `header_size' field does not. */
780 hdr->packed_size -= extend_size;
781 hdr->header_size += extend_size;
790 * offset size field name
791 * --------------------------------------------------
792 * 0 2 total header size [*1] ^
793 * ----------------------- |
795 * 7 4 packed size [*2] |
796 * 11 4 original size |
798 * 19 1 RESERVED | [*1] total header size
799 * 20 1 level (0x02 fixed) | (X+26+(1))
802 * 24 2 next-header size |
803 * ----------------------------------- |
806 * ----------------------------------- |
807 * X +26 (1) padding v
808 * -------------------------------------------------
810 * : | [*2] packed size
812 * -------------------------------------------------
816 get_header_level2(fp, hdr, data)
821 int header_size, extend_size;
824 hdr->header_size = header_size = get_word();
826 if (fread(data + I_NAME_LENGTH, 26 - I_NAME_LENGTH, 1, fp) == 0) {
827 error("Invalid header (LHarc file ?)");
828 return FALSE; /* finish */
831 get_bytes(hdr->method, 5, sizeof(hdr->method));
832 hdr->packed_size = get_longword();
833 hdr->original_size = get_longword();
834 hdr->unix_last_modified_stamp = get_longword();
835 hdr->attribute = get_byte(); /* reserved */
836 hdr->header_level = get_byte();
838 /* defaults for other type */
839 hdr->unix_mode = UNIX_FILE_REGULAR | UNIX_RW_RW_RW;
844 hdr->crc = get_word();
845 hdr->extend_type = get_byte();
846 extend_size = get_word();
848 extend_size = get_extended_header(fp, hdr, extend_size);
849 if (extend_size == -1)
852 padding = header_size - 26 - extend_size;
853 while (padding--) /* padding should be 0 or 1 */
856 /* FIXME: no collate the header CRC */
866 char data[LZHEADER_STORAGE];
868 int archive_kanji_code = CODE_SJIS;
869 int system_kanji_code = default_system_kanji_code;
870 char *archive_delim = "\377\\"; /* `\' is for level 0 header and
872 char *system_delim = "//";
873 int filename_case = NONE;
876 memset(hdr, 0, sizeof(LzHeader));
880 if ((end_mark = getc(fp)) == EOF || end_mark == 0) {
881 return FALSE; /* finish */
885 if (fread(data + 1, I_NAME_LENGTH - 1, 1, fp) == 0) {
886 error("Invalid header (LHarc file ?)");
887 return FALSE; /* finish */
890 switch (data[I_HEADER_LEVEL]) {
892 if (get_header_level0(fp, hdr, data) == FALSE)
896 if (get_header_level1(fp, hdr, data) == FALSE)
900 if (get_header_level2(fp, hdr, data) == FALSE)
904 error("Unknown level header (level %d)", data[I_HEADER_LEVEL]);
908 /* filename conversion */
909 switch (hdr->extend_type) {
911 filename_case = noconvertcase ? NONE : TO_LOWER;
917 filename_case = NONE;
921 archive_delim = "\377/:\\";
922 /* `\' is for level 0 header and broken archive. */
923 system_delim = "/://";
924 filename_case = NONE;
928 filename_case = noconvertcase ? NONE : TO_LOWER;
929 /* FIXME: if small letter is included in filename,
930 the generic_to_unix_filename() do not case conversion,
931 but this code does not consider it. */
935 if (optional_archive_kanji_code)
936 archive_kanji_code = optional_archive_kanji_code;
937 if (optional_system_kanji_code)
938 system_kanji_code = optional_system_kanji_code;
939 if (optional_archive_delim)
940 archive_delim = optional_archive_delim;
941 if (optional_system_delim)
942 system_delim = optional_system_delim;
943 if (optional_filename_case)
944 filename_case = optional_filename_case;
946 /* kanji code and delimiter conversion */
947 convert_filename(hdr->name, strlen(hdr->name), sizeof(hdr->name),
950 archive_delim, system_delim, filename_case);
955 /* ------------------------------------------------------------------------ */
957 init_header(name, v_stat, hdr)
964 memset(hdr, 0, sizeof(LzHeader));
966 if (compress_method == LZHUFF5_METHOD_NUM) /* Changed N.Watazaki */
967 memcpy(hdr->method, LZHUFF5_METHOD, METHOD_TYPE_STORAGE);
968 else if (compress_method)
969 memcpy(hdr->method, LZHUFF1_METHOD, METHOD_TYPE_STORAGE);
971 memcpy(hdr->method, LZHUFF0_METHOD, METHOD_TYPE_STORAGE);
973 hdr->packed_size = 0;
974 hdr->original_size = v_stat->st_size;
975 hdr->attribute = GENERIC_ATTRIBUTE;
976 hdr->header_level = header_level;
977 strcpy(hdr->name, name);
980 hdr->extend_type = EXTEND_UNIX;
981 hdr->unix_last_modified_stamp = v_stat->st_mtime;
982 /* since 00:00:00 JAN.1.1970 */
983 #ifdef NOT_COMPATIBLE_MODE
984 /* Please need your modification in this space. */
986 hdr->unix_mode = v_stat->st_mode;
989 hdr->unix_uid = v_stat->st_uid;
990 hdr->unix_gid = v_stat->st_gid;
992 #if INCLUDE_OWNER_NAME_IN_HEADER
995 struct passwd *ent = getpwuid(hdr->unix_uid);
998 strncpy(hdr->user, ent->pw_name, sizeof(hdr->user));
999 if (hdr->user[sizeof(hdr->user)-1])
1000 hdr->user[sizeof(hdr->user)-1] = 0;
1006 struct group *ent = getgrgid(hdr->unix_gid);
1009 strncpy(hdr->group, ent->gr_name, sizeof(hdr->group));
1010 if (hdr->group[sizeof(hdr->group)-1])
1011 hdr->group[sizeof(hdr->group)-1] = 0;
1015 #endif /* INCLUDE_OWNER_NAME_IN_HEADER */
1016 if (is_directory(v_stat)) {
1017 memcpy(hdr->method, LZHDIRS_METHOD, METHOD_TYPE_STORAGE);
1018 hdr->attribute = GENERIC_DIRECTORY_ATTRIBUTE;
1019 hdr->original_size = 0;
1020 if (len > 0 && hdr->name[len - 1] != '/')
1021 strcpy(&hdr->name[len++], "/");
1025 if (is_symlink(v_stat)) {
1026 char lkname[FILENAME_LENGTH];
1028 memcpy(hdr->method, LZHDIRS_METHOD, METHOD_TYPE_STORAGE);
1029 hdr->attribute = GENERIC_DIRECTORY_ATTRIBUTE;
1030 hdr->original_size = 0;
1031 len = readlink(name, lkname, sizeof(lkname));
1032 if (xsnprintf(hdr->name, sizeof(hdr->name),
1033 "%s|%.*s", hdr->name, len, lkname) == -1)
1034 error("file name is too long (%s -> %.*s)", hdr->name, len, lkname);
1039 /* ------------------------------------------------------------------------ */
1040 /* Write unix extended header or generic header. */
1043 write_header_level0(data, hdr, lzname)
1045 char *data, *lzname;
1052 memset(data, 0, LZHEADER_STORAGE);
1054 put_byte(0x00); /* header size */
1055 put_byte(0x00); /* check sum */
1056 put_bytes(hdr->method, 5);
1057 put_longword(hdr->packed_size);
1058 put_longword(hdr->original_size);
1059 put_longword(unix_to_generic_stamp(hdr->unix_last_modified_stamp));
1060 put_byte(hdr->attribute);
1061 put_byte(hdr->header_level); /* level 0 */
1063 /* level 0 header: write pathname (contain the directory part) */
1064 name_length = strlen(lzname);
1066 limit = 255 - I_GENERIC_HEADER_BOTTOM + 2;
1068 limit = 255 - I_UNIX_EXTEND_BOTTOM + 2;
1070 if (name_length > limit) {
1071 warning("the length of pathname \"%s\" is too long.", lzname);
1072 name_length = limit;
1074 put_byte(name_length);
1075 put_bytes(lzname, name_length);
1078 if (generic_format) {
1079 header_size = I_GENERIC_HEADER_BOTTOM + name_length - 2;
1080 data[I_HEADER_SIZE] = header_size;
1081 data[I_HEADER_CHECKSUM] = calc_sum(data + I_METHOD, header_size);
1083 /* write old-style extend header */
1084 put_byte(EXTEND_UNIX);
1085 put_byte(CURRENT_UNIX_MINOR_VERSION);
1086 put_longword(hdr->unix_last_modified_stamp);
1087 put_word(hdr->unix_mode);
1088 put_word(hdr->unix_uid);
1089 put_word(hdr->unix_gid);
1091 /* size of extended header is 12 */
1092 header_size = I_UNIX_EXTEND_BOTTOM + name_length - 2;
1093 data[I_HEADER_SIZE] = header_size;
1094 data[I_HEADER_CHECKSUM] = calc_sum(data + I_METHOD, header_size);
1097 return header_size + 2;
1101 write_header_level1(data, hdr, lzname)
1103 char *data, *lzname;
1105 int name_length, dir_length, limit;
1106 char *basename, *dirname;
1108 char *extend_header_top;
1109 int extend_header_size;
1111 basename = strrchr(lzname, LHA_PATHSEP);
1114 name_length = strlen(basename);
1116 dir_length = basename - dirname;
1120 name_length = strlen(basename);
1126 memset(data, 0, LZHEADER_STORAGE);
1128 put_byte(0x00); /* header size */
1129 put_byte(0x00); /* check sum */
1130 put_bytes(hdr->method, 5);
1131 put_longword(hdr->packed_size);
1132 put_longword(hdr->original_size);
1133 put_longword(unix_to_generic_stamp(hdr->unix_last_modified_stamp));
1135 put_byte(hdr->header_level); /* level 1 */
1137 /* level 1 header: write filename (basename only) */
1138 limit = 255 - 27 + 2;
1139 if (name_length > limit) {
1140 put_byte(0); /* name length */
1143 put_byte(name_length);
1144 put_bytes(basename, name_length);
1152 put_byte(EXTEND_UNIX);
1154 /* write extend header from here. */
1156 extend_header_top = put_ptr+2; /* +2 for the field `next header size' */
1157 header_size = extend_header_top - data - 2;
1159 /* write filename and dirname */
1161 if (name_length > limit) {
1162 put_word(name_length + 3); /* size */
1163 put_byte(0x01); /* filename */
1164 put_bytes(basename, name_length);
1167 if (dir_length > 0) {
1168 put_word(dir_length + 3); /* size */
1169 put_byte(0x02); /* dirname */
1170 put_bytes(dirname, dir_length);
1173 if (!generic_format) {
1174 /* UNIX specific informations */
1176 put_word(5); /* size */
1177 put_byte(0x50); /* permission */
1178 put_word(hdr->unix_mode);
1180 put_word(7); /* size */
1181 put_byte(0x51); /* gid and uid */
1182 put_word(hdr->unix_gid);
1183 put_word(hdr->unix_uid);
1185 if (hdr->group[0]) {
1186 int len = strlen(hdr->group);
1187 put_word(len + 3); /* size */
1188 put_byte(0x52); /* group name */
1189 put_bytes(hdr->group, len);
1193 int len = strlen(hdr->user);
1194 put_word(len + 3); /* size */
1195 put_byte(0x53); /* user name */
1196 put_bytes(hdr->user, len);
1199 if (hdr->header_level == 1) {
1200 put_word(7); /* size */
1201 put_byte(0x54); /* time stamp */
1202 put_longword(hdr->unix_last_modified_stamp);
1204 } /* if generic .. */
1206 put_word(0x0000); /* next header size */
1208 extend_header_size = put_ptr - extend_header_top;
1209 /* On level 1 header, the packed size field is contains the ext-header */
1210 hdr->packed_size += put_ptr - extend_header_top;
1212 /* put `skip size' */
1213 setup_put(data + I_PACKED_SIZE);
1214 put_longword(hdr->packed_size);
1216 data[I_HEADER_SIZE] = header_size;
1217 data[I_HEADER_CHECKSUM] = calc_sum(data + I_METHOD, header_size);
1219 return header_size + extend_header_size + 2;
1223 write_header_level2(data, hdr, lzname)
1225 char *data, *lzname;
1227 int name_length, dir_length;
1228 char *basename, *dirname;
1230 char *extend_header_top;
1231 char *headercrc_ptr;
1232 unsigned short hcrc;
1234 basename = strrchr(lzname, LHA_PATHSEP);
1237 name_length = strlen(basename);
1239 dir_length = basename - dirname;
1243 name_length = strlen(basename);
1249 memset(data, 0, LZHEADER_STORAGE);
1251 put_word(0x0000); /* header size */
1252 put_bytes(hdr->method, 5);
1253 put_longword(hdr->packed_size);
1254 put_longword(hdr->original_size);
1255 put_longword(hdr->unix_last_modified_stamp);
1257 put_byte(hdr->header_level); /* level 2 */
1264 put_byte(EXTEND_UNIX);
1266 /* write extend header from here. */
1268 extend_header_top = put_ptr+2; /* +2 for the field `next header size' */
1270 /* write common header */
1273 headercrc_ptr = put_ptr;
1274 put_word(0x0000); /* header CRC */
1276 /* write filename and dirname */
1277 /* must have this header, even if the name_length is 0. */
1278 put_word(name_length + 3); /* size */
1279 put_byte(0x01); /* filename */
1280 put_bytes(basename, name_length);
1282 if (dir_length > 0) {
1283 put_word(dir_length + 3); /* size */
1284 put_byte(0x02); /* dirname */
1285 put_bytes(dirname, dir_length);
1288 if (!generic_format) {
1289 /* UNIX specific informations */
1291 put_word(5); /* size */
1292 put_byte(0x50); /* permission */
1293 put_word(hdr->unix_mode);
1295 put_word(7); /* size */
1296 put_byte(0x51); /* gid and uid */
1297 put_word(hdr->unix_gid);
1298 put_word(hdr->unix_uid);
1300 if (hdr->group[0]) {
1301 int len = strlen(hdr->group);
1302 put_word(len + 3); /* size */
1303 put_byte(0x52); /* group name */
1304 put_bytes(hdr->group, len);
1308 int len = strlen(hdr->user);
1309 put_word(len + 3); /* size */
1310 put_byte(0x53); /* user name */
1311 put_bytes(hdr->user, len);
1314 if (hdr->header_level == 1) {
1315 put_word(7); /* size */
1316 put_byte(0x54); /* time stamp */
1317 put_longword(hdr->unix_last_modified_stamp);
1319 } /* if generic .. */
1321 put_word(0x0000); /* next header size */
1323 header_size = put_ptr - data;
1324 if ((header_size & 0xff) == 0) {
1325 /* cannot put zero at the first byte on level 2 header. */
1326 /* adjust header size. */
1327 put_byte(0); /* padding */
1331 /* put hader size */
1332 setup_put(data + I_HEADER_SIZE);
1333 put_word(header_size);
1335 /* put hader CRC in extended header */
1336 hcrc = calc_header_crc(data, (unsigned int) header_size);
1337 setup_put(headercrc_ptr);
1344 write_header(fp, hdr)
1349 char data[LZHEADER_STORAGE];
1351 int archive_kanji_code = CODE_SJIS;
1352 int system_kanji_code = default_system_kanji_code;
1353 char *archive_delim = "\377";
1354 char *system_delim = "/";
1355 int filename_case = NONE;
1356 char pathname[FILENAME_LENGTH];
1358 if (optional_archive_kanji_code)
1359 archive_kanji_code = optional_archive_kanji_code;
1360 if (optional_system_kanji_code)
1361 system_kanji_code = optional_system_kanji_code;
1364 filename_case = TO_UPPER;
1366 if (hdr->header_level == HEADER_LEVEL0) {
1367 archive_delim = "\\";
1370 strncpy(pathname, hdr->name, sizeof(pathname));
1371 pathname[sizeof(pathname)-1] = 0;
1372 convert_filename(pathname, strlen(pathname), sizeof(pathname),
1375 system_delim, archive_delim, filename_case);
1377 switch (hdr->header_level) {
1379 header_size = write_header_level0(data, hdr, pathname);
1382 header_size = write_header_level1(data, hdr, pathname);
1385 header_size = write_header_level2(data, hdr, pathname);
1388 error("Unknown level header (level %d)", hdr->header_level);
1392 if (fwrite(data, header_size, 1, fp) == 0)
1393 fatal_error("Cannot write to temporary file");
1396 #if MULTIBYTE_FILENAME
1398 #if defined(__APPLE__)
1400 #include <CoreFoundation/CFString.h>
1401 #include <CoreFoundation/CFStringEncodingExt.h>
1403 /* this is not need for Mac OS X v 10.2 later */
1405 kCFStringEncodingAllowLossyConversion = 1,
1406 kCFStringEncodingBasicDirectionLeftToRight = (1 << 1),
1407 kCFStringEncodingBasicDirectionRightToLeft = (1 << 2),
1408 kCFStringEncodingSubstituteCombinings = (1 << 3),
1409 kCFStringEncodingComposeCombinings = (1 << 4),
1410 kCFStringEncodingIgnoreCombinings = (1 << 5),
1411 kCFStringEncodingUseCanonical = (1 << 6),
1412 kCFStringEncodingUseHFSPlusCanonical = (1 << 7),
1413 kCFStringEncodingPrependBOM = (1 << 8),
1414 kCFStringEncodingDisableCorporateArea = (1 << 9),
1415 kCFStringEncodingASCIICompatibleConversion = (1 << 10),
1419 ConvertEncodingToUTF8(const char* inCStr,
1420 char* outUTF8Buffer,
1421 int outUTF8BufferLength,
1422 unsigned long scriptEncoding,
1423 unsigned long flags)
1425 unsigned long unicodeChars;
1426 unsigned long srcCharsUsed;
1427 unsigned long usedByteLen = 0;
1428 UniChar uniStr[512];
1429 unsigned long cfResult;
1431 cfResult = CFStringEncodingBytesToUnicode(scriptEncoding,
1439 if (cfResult == 0) {
1440 cfResult = CFStringEncodingUnicodeToBytes(kCFStringEncodingUTF8,
1445 (char*)outUTF8Buffer,
1446 outUTF8BufferLength - 1,
1448 outUTF8Buffer[usedByteLen] = '\0';
1455 ConvertUTF8ToEncoding(const char* inUTF8Buf,
1456 int inUTF8BufLength,
1457 char* outCStrBuffer,
1458 int outCStrBufferLength,
1459 unsigned long scriptEncoding,
1460 unsigned long flags)
1462 unsigned long unicodeChars;
1463 unsigned long srcCharsUsed;
1464 unsigned long usedByteLen = 0;
1465 UniChar uniStr[256];
1466 unsigned long cfResult;
1468 cfResult = CFStringEncodingBytesToUnicode(kCFStringEncodingUTF8,
1476 if (cfResult == 0) {
1477 cfResult = CFStringEncodingUnicodeToBytes(scriptEncoding,
1482 (char*)outCStrBuffer,
1483 outCStrBufferLength - 1,
1485 outCStrBuffer[usedByteLen] = '\0';
1495 ConvertEncodingByIconv(const char *src, char *dst, int dstsize,
1496 const char *srcEnc, const char *dstEnc)
1499 static char szTmpBuf[2048];
1505 dst_p = &szTmpBuf[0];
1506 iLen = (size_t)sizeof(szTmpBuf)-1;
1507 src_p = (char *)src;
1508 sLen = (size_t)strlen(src);
1509 memset(szTmpBuf, 0, sizeof(szTmpBuf));
1510 memset(dst, 0, dstsize);
1512 ic = iconv_open(dstEnc, srcEnc);
1513 if (ic == (iconv_t)-1) {
1514 error("iconv_open() failure: %s", strerror(errno));
1518 if (iconv(ic, &src_p, &sLen, &dst_p, &iLen) == (size_t)-1) {
1519 error("iconv() failure: %s", strerror(errno));
1524 strncpy(dst, szTmpBuf, dstsize);
1530 #endif /* defined(__APPLE__) */
1533 sjis_to_utf8(char *dst, const char *src, size_t dstsize)
1535 #if defined(__APPLE__)
1537 if (ConvertEncodingToUTF8(src, dst, dstsize,
1538 kCFStringEncodingDOSJapanese,
1539 kCFStringEncodingUseHFSPlusCanonical) == 0)
1542 if (ConvertEncodingByIconv(src, dst, dstsize, "SJIS", "UTF-8") != -1)
1545 error("not support utf-8 conversion");
1548 if (dstsize < 1) return dst;
1550 return strncpy(dst, src, dstsize-1);
1554 utf8_to_sjis(char *dst, const char *src, size_t dstsize)
1556 #if defined(__APPLE__)
1560 srclen = strlen(src);
1561 if (ConvertUTF8ToEncoding(src, srclen, dst, dstsize,
1562 kCFStringEncodingDOSJapanese,
1563 kCFStringEncodingUseHFSPlusCanonical) == 0)
1566 if (ConvertEncodingByIconv(src, dst, dstsize, "UTF-8", "SJIS") != -1)
1569 error("not support utf-8 conversion");
1572 if (dstsize < 1) return dst;
1574 return strncpy(dst, src, dstsize-1);
1578 * SJIS <-> EUC ÊÑ´¹´Ø¿ô
1579 * ¡ÖÆüËܸì¾ðÊó½èÍý¡× ¥½¥Õ¥È¥Ð¥ó¥¯(³ô)
1580 * ¤è¤êÈ´¿è(by Koji Arai)
1583 euc2sjis(int *p1, int *p2)
1585 unsigned char c1 = *p1 & 0x7f;
1586 unsigned char c2 = *p2 & 0x7f;
1587 int rowoff = c1 < 0x5f ? 0x70 : 0xb0;
1588 int celoff = c1 % 2 ? (c2 > 0x5f ? 0x20 : 0x1f) : 0x7e;
1589 *p1 = ((c1 + 1) >> 1) + rowoff;
1590 *p2 += celoff - 0x80;
1594 sjis2euc(int *p1, int *p2)
1596 unsigned char c1 = *p1;
1597 unsigned char c2 = *p2;
1598 int adjust = c2 < 0x9f;
1599 int rowoff = c1 < 0xa0 ? 0x70 : 0xb0;
1600 int celoff = adjust ? (c2 > 0x7f ? 0x20 : 0x1f) : 0x7e;
1601 *p1 = ((c1 - rowoff) << 1) - adjust;
1607 #endif /* MULTIBYTE_FILENAME */
1609 /* Local Variables: */
1612 /* compile-command:"gcc -c header.c" */
1614 /* vi: set tabstop=4: */