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 /* ------------------------------------------------------------------------ */
27 int optional_archive_kanji_code = NONE;
28 int optional_system_kanji_code = NONE;
29 char *optional_archive_delim = NULL;
30 char *optional_system_delim = NULL;
31 int optional_filename_case = NONE;
33 #ifdef MULTIBYTE_FILENAME
34 int default_system_kanji_code = MULTIBYTE_FILENAME;
36 int default_system_kanji_code = NONE;
39 /* ------------------------------------------------------------------------ */
47 for (sum = 0; len; len--)
53 /* ------------------------------------------------------------------------ */
61 return (b1 << 8) + b0;
64 /* ------------------------------------------------------------------------ */
73 /* ------------------------------------------------------------------------ */
83 return (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
86 /* ------------------------------------------------------------------------ */
98 /* ------------------------------------------------------------------------ */
100 msdos_to_unix_filename(name, len)
106 #ifdef MULTIBYTE_FILENAME
107 for (i = 0; i < len; i++) {
108 if (MULTIBYTE_FIRST_P(name[i]) &&
109 MULTIBYTE_SECOND_P(name[i + 1]))
111 else if (name[i] == '\\')
113 else if (!noconvertcase && isupper(name[i]))
114 name[i] = tolower(name[i]);
117 for (i = 0; i < len; i++) {
120 else if (!noconvertcase && isupper(name[i]))
121 name[i] = tolower(name[i]);
126 /* ------------------------------------------------------------------------ */
128 generic_to_unix_filename(name, len)
133 boolean lower_case_used = FALSE;
135 #ifdef MULTIBYTE_FILENAME
136 for (i = 0; i < len; i++) {
137 if (MULTIBYTE_FIRST_P(name[i]) &&
138 MULTIBYTE_SECOND_P(name[i + 1]))
140 else if (islower(name[i])) {
141 lower_case_used = TRUE;
145 for (i = 0; i < len; i++) {
146 if (MULTIBYTE_FIRST_P(name[i]) &&
147 MULTIBYTE_SECOND_P(name[i + 1]))
149 else if (name[i] == '\\')
151 else if (!noconvertcase && !lower_case_used && isupper(name[i]))
152 name[i] = tolower(name[i]);
155 for (i = 0; i < len; i++)
156 if (islower(name[i])) {
157 lower_case_used = TRUE;
160 for (i = 0; i < len; i++) {
163 else if (!noconvertcase && !lower_case_used && isupper(name[i]))
164 name[i] = tolower(name[i]);
169 /* ------------------------------------------------------------------------ */
171 macos_to_unix_filename(name, len)
177 for (i = 0; i < len; i++) {
180 else if (name[i] == '/')
185 /* ------------------------------------------------------------------------ */
187 unix_to_generic_filename(name, len)
193 for (i = 0; i < len; i++) {
196 else if (islower(name[i]))
197 name[i] = toupper(name[i]);
202 /* added by Koji Arai */
204 convert_filename(name, len, size,
206 from_delim, to_delim,
211 int from_code, to_code, case_to;
212 char *from_delim, *to_delim;
216 #ifdef MULTIBYTE_FILENAME
217 char tmp[FILENAME_LENGTH];
219 if (from_code == CODE_SJIS && to_code == CODE_UTF8) {
220 for (i = 0; i < len; i++)
221 /* FIXME: provisionally fix for the Mac OS CoreFoundation */
222 if ((unsigned char)name[i] == LHA_PATHSEP) name[i] = '/';
223 sjis_to_utf8(tmp, name, sizeof(tmp));
224 strncpy(name, tmp, size);
227 for (i = 0; i < len; i++)
228 if (name[i] == '/') name[i] = LHA_PATHSEP;
229 from_code = CODE_UTF8;
231 else if (from_code == CODE_UTF8 && to_code == CODE_SJIS) {
232 for (i = 0; i < len; i++)
233 /* FIXME: provisionally fix for the Mac OS CoreFoundation */
234 if ((unsigned char)name[i] == LHA_PATHSEP) name[i] = '/';
235 utf8_to_sjis(tmp, name, sizeof(tmp));
236 strncpy(name, tmp, size);
239 for (i = 0; i < len; i++)
240 if (name[i] == '/') name[i] = LHA_PATHSEP;
241 from_code = CODE_SJIS;
245 for (i = 0; i < len; i ++) {
246 #ifdef MULTIBYTE_FILENAME
247 if (from_code == CODE_EUC &&
248 (unsigned char)name[i] == 0x8e) {
249 if (to_code != CODE_SJIS) {
255 memmove(name + i, name + i + 1, len - i);
259 if (from_code == CODE_SJIS && X0201_KANA_P(name[i])) {
260 if (to_code != CODE_EUC) {
264 if (len == size - 1) /* check overflow */
266 memmove(name+i+1, name+i, len-i);
272 if (from_code == CODE_EUC && (name[i] & 0x80) && (name[i+1] & 0x80)) {
274 if (to_code != CODE_SJIS) {
279 c1 = (unsigned char)name[i];
280 c2 = (unsigned char)name[i+1];
287 if (from_code == CODE_SJIS &&
288 SJC_FIRST_P(name[i]) &&
289 SJC_SECOND_P(name[i+1])) {
292 if (to_code != CODE_EUC) {
297 c1 = (unsigned char)name[i];
298 c2 = (unsigned char)name[i+1];
305 #endif /* MULTIBYTE_FILENAME */
309 /* transpose from_delim to to_delim */
311 if ((ptr = strchr(from_delim, name[i])) != NULL) {
312 name[i] = to_delim[ptr - from_delim];
317 if (case_to == TO_UPPER && islower(name[i])) {
318 name[i] = toupper(name[i]);
321 if (case_to == TO_LOWER && isupper(name[i])) {
322 name[i] = tolower(name[i]);
328 /* ------------------------------------------------------------------------ */
330 /* Generic stamp format: */
332 /* 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 */
333 /* |<-------- year ------->|<- month ->|<-- day -->| */
335 /* 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 */
336 /* |<--- hour --->|<---- minute --->|<- second*2 ->| */
338 /* ------------------------------------------------------------------------ */
341 * NOTE : If you don't have `gettimeofday(2)', or your gettimeofday(2)
342 * returns bogus timezone information, try FTIME, MKTIME, TIMELOCAL or TZSET.
346 #if defined(HAVE_MKTIME)
347 #ifdef HAVE_TIMELOCAL
348 #undef HAVE_TIMELOCAL
350 #endif /* defined(HAVE_MKTIME) */
352 #if defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL)
356 #endif /* defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL) */
358 #if defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL) || defined(HAVE_TZSET)
364 #if defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL) || defined(HAVE_TZSET) || defined(HAVE_FTIME)
365 #ifdef HAVE_GETTIMEOFDAY
366 #undef HAVE_GETTIMEOFDAY
369 #ifndef HAVE_GETTIMEOFDAY
370 #define HAVE_GETTIMEOFDAY /* use gettimeofday() */
375 #include <sys/timeb.h>
379 * You may define as : #define TIMEZONE_HOOK \ extern long
380 * timezone ; \ extern void tzset();
384 /* Which do you like better, `TIMEZONE_HOOK' or `TIMEZONE_HOOK;' ? */
387 #if defined(HAVE_TZSET) && defined(_MINIX)
388 extern long timezone; /* not defined in time.h */
391 /* ------------------------------------------------------------------------ */
392 #if defined(HAVE_FTIME) || defined(HAVE_GETTIMEOFDAY) || defined(HAVE_TZSET)
402 /* ------------------------------------------------------------------------ */
403 #if !defined(HAVE_TZSET) && defined(HAVE_FTIME)
408 return buf.timezone * 60L;
412 /* ------------------------------------------------------------------------ */
413 #if !defined(HAVE_TZSET) && !defined(HAVE_FTIME) /* maybe defined(HAVE_GETTIMEOFDAY) */
415 #ifdef HAVE_STRUCT_TM_TM_GMTOFF
419 return -localtime(&tt)->tm_gmtoff;
420 #else /* HAVE_STRUCT_TM_TM_GMTOFF */
423 gettimeofday(&tp, &tzp);/* specific to 4.3BSD */
425 * return (tzp.tz_minuteswest * 60L + (tzp.tz_dsttime != 0 ? 60L *
428 return (tzp.tz_minuteswest * 60L);
429 #endif /* HAVE_STRUCT_TM_TM_GMTOFF */
432 #endif /* defined(HAVE_FTIME) || defined(HAVE_GETTIMEOFDAY) ||
433 * defined(HAVE_TZSET) */
435 /* ------------------------------------------------------------------------ */
438 msdos_to_unix_stamp_tm(a)
443 t.tm_sec = (a & 0x1f) * 2;
444 t.tm_min = (a >> 5) & 0x3f;
445 t.tm_hour = (a >> 11) & 0x1f;
446 t.tm_mday = (a >> 16) & 0x1f;
447 t.tm_mon = ((a >> 16 + 5) & 0x0f) - 1;
448 t.tm_year = ((a >> 16 + 9) & 0x7f) + 80;
453 /* ------------------------------------------------------------------------ */
455 generic_to_unix_stamp(t)
457 #if defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL)
462 * special case: if MSDOS format date and time were zero, then we
463 * set time to be zero here too.
468 dostm.tm_sec = (t & 0x1f) * 2;
469 dostm.tm_min = t >> 5 & 0x3f;
470 dostm.tm_hour = t >> 11 & 0x1f;
471 dostm.tm_mday = t >> 16 & 0x1f;
472 dostm.tm_mon = (t >> 16 + 5 & 0x0f) - 1; /* 0..11 */
473 dostm.tm_year = (t >> 16 + 9 & 0x7f) + 80;
475 dostm.tm_isdst = 0; /* correct? */
477 dostm.tm_isdst = -1; /* correct? */
479 return (time_t) mktime(&dostm);
480 #else /* maybe defined(HAVE_TIMELOCAL) */
481 return (time_t) timelocal(&dostm);
485 #else /* defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL) */
487 int year, month, day, hour, min, sec;
489 static unsigned int dsboy[12] = {0, 31, 59, 90, 120, 151,
490 181, 212, 243, 273, 304, 334};
494 * special case: if MSDOS format date and time were zero, then we
495 * set time to be zero here too.
500 year = ((int) (t >> 16 + 9) & 0x7f) + 1980;
501 month = (int) (t >> 16 + 5) & 0x0f; /* 1..12 means Jan..Dec */
502 day = (int) (t >> 16) & 0x1f; /* 1..31 means 1st,...31st */
504 hour = ((int) t >> 11) & 0x1f;
505 min = ((int) t >> 5) & 0x3f;
506 sec = ((int) t & 0x1f) * 2;
508 /* Calculate days since 1970.01.01 */
509 days = (365 * (year - 1970) + /* days due to whole years */
510 (year - 1970 + 1) / 4 + /* days due to leap years */
511 dsboy[month - 1] + /* days since beginning of this year */
512 day - 1); /* days since beginning of month */
514 if ((year % 4 == 0) &&
515 (year % 100 != 0 || year % 400 == 0) && /* 1999.5.24 t.oka */
516 (month >= 3)) /* if this is a leap year and month */
517 days++; /* is March or later, add a day */
519 /* Knowing the days, we can find seconds */
520 longtime = (((days * 24) + hour) * 60 + min) * 60 + sec;
521 longtime += gettz(); /* adjust for timezone */
523 /* LONGTIME is now the time in seconds, since 1970/01/01 00:00:00. */
524 return (time_t) longtime;
526 #endif /* defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL) */
528 /* ------------------------------------------------------------------------ */
530 unix_to_generic_stamp(t)
533 struct tm *tm = localtime(&t);
535 return ((((long) (tm->tm_year - 80)) << 25) +
536 (((long) (tm->tm_mon + 1)) << 21) +
537 (((long) tm->tm_mday) << 16) +
538 (long) ((tm->tm_hour << 11) +
543 /* ------------------------------------------------------------------------ */
544 /* build header functions */
545 /* ------------------------------------------------------------------------ */
549 register LzHeader *hdr;
553 char data[LZHEADER_STRAGE];
554 char dirname[FILENAME_LENGTH];
562 int archive_kanji_code = CODE_SJIS;
563 int system_kanji_code = default_system_kanji_code;
564 char *archive_delim = "\377\\"; /* `\' is for level 0 header and
566 char *system_delim = "//";
567 int filename_case = NONE;
569 memset(hdr, 0, sizeof(LzHeader));
571 if (((header_size = getc(fp)) == EOF) || (header_size == 0)) {
572 return FALSE; /* finish */
575 if (fread(data + 1, I_NAME_LENGTH - 1, 1, fp) == 0) {
576 fatal_error("Invalid header (LHarc file ?)");
577 return FALSE; /* finish */
579 setup_get(data + I_HEADER_LEVEL);
580 hdr->header_level = get_byte();
582 if (hdr->header_level >= 3) {
583 error("Unknown level header (level %d)", hdr->header_level);
587 setup_get(data + I_HEADER_CHECKSUM);
588 checksum = get_byte();
590 if (hdr->header_level == 2) {
591 hdr->header_size = header_size += checksum*256;
593 hdr->header_size = header_size;
596 if (fread(data + I_NAME_LENGTH, header_size - I_NAME_LENGTH, 1, fp) == 0) {
597 fatal_error("Invalid header (LHarc file ?)");
598 return FALSE; /* finish */
601 if (hdr->header_level != 2 &&
602 fread(data + header_size, sizeof(char), 2, fp) < 2) {
603 fatal_error("Invalid header (LHarc file ?)");
604 return FALSE; /* finish */
607 memcpy(hdr->method, data + I_METHOD, METHOD_TYPE_STRAGE);
608 setup_get(data + I_PACKED_SIZE);
609 hdr->packed_size = get_longword();
610 hdr->original_size = get_longword();
611 hdr->last_modified_stamp = get_longword();
612 hdr->attribute = get_byte();
614 if ((hdr->header_level = get_byte()) != 2) {
615 if (calc_sum(data + I_METHOD, header_size) != checksum)
616 warning("Checksum error (LHarc file?)");
617 name_length = get_byte();
618 for (i = 0; i < name_length; i++)
619 hdr->name[i] = (char) get_byte();
620 hdr->name[name_length] = '\0';
623 hdr->unix_last_modified_stamp = hdr->last_modified_stamp;
627 /* defaults for other type */
628 hdr->unix_mode = UNIX_FILE_REGULAR | UNIX_RW_RW_RW;
632 if (hdr->header_level == 0) {
633 extend_size = header_size - name_length -22;
634 if (extend_size < 0) {
635 if (extend_size == -2) {
636 hdr->extend_type = EXTEND_GENERIC;
637 hdr->has_crc = FALSE;
639 error("Unkonwn header (lha file?)");
644 hdr->crc = get_word();
647 if (extend_size >= 1) {
648 hdr->extend_type = get_byte();
651 if (hdr->extend_type == EXTEND_UNIX) {
652 if (extend_size >= 11) {
653 hdr->minor_version = get_byte();
654 hdr->unix_last_modified_stamp = (time_t) get_longword();
655 hdr->unix_mode = get_word();
656 hdr->unix_uid = get_word();
657 hdr->unix_gid = get_word();
660 hdr->extend_type = EXTEND_GENERIC;
663 while (extend_size-- > 0)
665 } else if (hdr->header_level == 1) {
667 extend_size = header_size - name_length-25;
668 hdr->crc = get_word();
669 hdr->extend_type = get_byte();
670 while (extend_size-- > 0)
672 } else { /* level 2 */
674 hdr->crc = get_word();
675 hdr->extend_type = get_byte();
678 if (hdr->header_level > 0) {
680 if (hdr->header_level != 2)
681 setup_get(data + hdr->header_size);
683 while ((header_size = get_word()) != 0) {
684 if (hdr->header_level != 2 &&
685 ((data + LZHEADER_STRAGE - get_ptr < header_size) ||
686 fread(get_ptr, sizeof(char), header_size, fp) < header_size)) {
687 error("Invalid header (LHa file ?)");
690 switch (get_byte()) {
695 setup_get(get_ptr + header_size - 3);
701 for (i = 0; i < header_size-3 && i < sizeof(hdr->name)-1; i++)
702 hdr->name[i] = (char) get_byte();
705 for (; i < header_size-3; i++)
712 for (i = 0; i < header_size-3 && i < sizeof(dirname)-1; i++)
713 dirname[i] = (char) get_byte();
716 for (; i < header_size-3; i++)
723 if (hdr->extend_type == EXTEND_MSDOS ||
724 hdr->extend_type == EXTEND_HUMAN ||
725 hdr->extend_type == EXTEND_GENERIC)
726 hdr->attribute = get_word();
732 if (hdr->extend_type == EXTEND_UNIX)
733 hdr->unix_mode = get_word();
739 if (hdr->extend_type == EXTEND_UNIX) {
740 hdr->unix_gid = get_word();
741 hdr->unix_uid = get_word();
748 for (i = 0; i < header_size-3 && i < sizeof(hdr->group)-1; i++)
749 hdr->group[i] = get_byte();
750 hdr->group[i] = '\0';
751 for (; i < header_size-3; i++)
758 for (i = 0; i < header_size-3 && i < sizeof(hdr->user)-1; i++)
759 hdr->user[i] = get_byte();
761 for (; i < header_size-3; i++)
766 * UNIX last modified time
768 if (hdr->extend_type == EXTEND_UNIX)
769 hdr->unix_last_modified_stamp = (time_t) get_longword();
775 setup_get(get_ptr + header_size - 3);
779 if (hdr->header_level != 2 && get_ptr - ptr != 2) {
780 hdr->packed_size -= get_ptr - ptr - 2;
781 hdr->header_size += get_ptr - ptr - 2;
785 switch (hdr->extend_type) {
787 filename_case = noconvertcase ? NONE : TO_LOWER;
791 if (hdr->header_level == 2)
792 hdr->unix_last_modified_stamp = hdr->last_modified_stamp;
794 hdr->unix_last_modified_stamp =
795 generic_to_unix_stamp(hdr->last_modified_stamp);
803 filename_case = NONE;
808 archive_delim = "\377/:\\";
809 /* `\' is for level 0 header and broken archive. */
810 system_delim = "/://";
811 filename_case = NONE;
813 hdr->unix_last_modified_stamp =
814 generic_to_unix_stamp(hdr->last_modified_stamp, sizeof(hdr->name));
818 filename_case = noconvertcase ? NONE : TO_LOWER;
819 /* FIXME: if small letter is included in filename,
820 the generic_to_unix_filename() do not case conversion,
821 but this code does not consider it. */
823 if (hdr->header_level == 2)
824 hdr->unix_last_modified_stamp = hdr->last_modified_stamp;
826 hdr->unix_last_modified_stamp =
827 generic_to_unix_stamp(hdr->last_modified_stamp);
830 /* filename kanji code and delimiter conversion */
831 if (optional_archive_kanji_code)
832 archive_kanji_code = optional_archive_kanji_code;
833 if (optional_system_kanji_code)
834 system_kanji_code = optional_system_kanji_code;
835 if (optional_archive_delim)
836 archive_delim = optional_archive_delim;
837 if (optional_system_delim)
838 system_delim = optional_system_delim;
839 if (optional_filename_case)
840 filename_case = optional_filename_case;
843 strcat(dirname, hdr->name);
844 strcpy(hdr->name, dirname);
845 name_length += dir_length;
848 convert_filename(hdr->name, name_length, sizeof(hdr->name),
851 archive_delim, system_delim, filename_case);
856 /* ------------------------------------------------------------------------ */
858 init_header(name, v_stat, hdr)
865 memset(hdr, 0, sizeof(LzHeader));
867 if (compress_method == LZHUFF5_METHOD_NUM) /* Changed N.Watazaki */
868 memcpy(hdr->method, LZHUFF5_METHOD, METHOD_TYPE_STRAGE);
869 else if (compress_method)
870 memcpy(hdr->method, LZHUFF1_METHOD, METHOD_TYPE_STRAGE);
872 memcpy(hdr->method, LZHUFF0_METHOD, METHOD_TYPE_STRAGE);
874 hdr->packed_size = 0;
875 hdr->original_size = v_stat->st_size;
876 hdr->last_modified_stamp = unix_to_generic_stamp(v_stat->st_mtime);
877 hdr->attribute = GENERIC_ATTRIBUTE;
878 hdr->header_level = header_level;
879 strcpy(hdr->name, name);
882 hdr->extend_type = EXTEND_UNIX;
883 hdr->unix_last_modified_stamp = v_stat->st_mtime;
884 /* since 00:00:00 JAN.1.1970 */
885 #ifdef NOT_COMPATIBLE_MODE
886 /* Please need your modification in this space. */
888 hdr->unix_mode = v_stat->st_mode;
891 hdr->unix_uid = v_stat->st_uid;
892 hdr->unix_gid = v_stat->st_gid;
894 #if INCLUDE_OWNER_NAME_IN_HEADER
897 struct passwd *ent = getpwuid(hdr->unix_uid);
900 strncpy(hdr->user, ent->pw_name, sizeof(hdr->user));
901 if (hdr->user[sizeof(hdr->user)-1])
902 hdr->user[sizeof(hdr->user)-1] = 0;
908 struct group *ent = getgrgid(hdr->unix_gid);
911 strncpy(hdr->group, ent->gr_name, sizeof(hdr->group));
912 if (hdr->group[sizeof(hdr->group)-1])
913 hdr->group[sizeof(hdr->group)-1] = 0;
917 #endif /* INCLUDE_OWNER_NAME_IN_HEADER */
918 if (is_directory(v_stat)) {
919 memcpy(hdr->method, LZHDIRS_METHOD, METHOD_TYPE_STRAGE);
920 hdr->attribute = GENERIC_DIRECTORY_ATTRIBUTE;
921 hdr->original_size = 0;
922 if (len > 0 && hdr->name[len - 1] != '/')
923 strcpy(&hdr->name[len++], "/");
927 if (is_symlink(v_stat)) {
928 char lkname[FILENAME_LENGTH];
930 memcpy(hdr->method, LZHDIRS_METHOD, METHOD_TYPE_STRAGE);
931 hdr->attribute = GENERIC_DIRECTORY_ATTRIBUTE;
932 hdr->original_size = 0;
933 len = readlink(name, lkname, sizeof(lkname));
934 if (xsnprintf(hdr->name, sizeof(hdr->name),
935 "%s|%.*s", hdr->name, len, lkname) == -1)
936 error("file name is too long (%s -> %.*s)", hdr->name, len, lkname);
941 /* ------------------------------------------------------------------------ */
942 /* Write unix extended header or generic header. */
944 write_header(nafp, hdr)
950 char data[LZHEADER_STRAGE];
954 int archive_kanji_code = CODE_SJIS;
955 int system_kanji_code = default_system_kanji_code;
956 char *archive_delim = "\377";
957 char *system_delim = "/";
958 int filename_case = NONE;
959 char lzname[FILENAME_LENGTH];
961 if (optional_archive_kanji_code)
962 archive_kanji_code = optional_archive_kanji_code;
963 if (optional_system_kanji_code)
964 system_kanji_code = optional_system_kanji_code;
966 memset(data, 0, LZHEADER_STRAGE);
967 memcpy(data + I_METHOD, hdr->method, METHOD_TYPE_STRAGE);
968 setup_put(data + I_PACKED_SIZE);
969 put_longword(hdr->packed_size);
970 put_longword(hdr->original_size);
972 if (hdr->header_level == HEADER_LEVEL2)
973 put_longword((long) hdr->unix_last_modified_stamp);
975 put_longword(hdr->last_modified_stamp);
977 switch (hdr->header_level) {
979 put_byte(hdr->attribute);
987 put_byte(hdr->header_level);
990 filename_case = TO_UPPER;
992 if (hdr->header_level == HEADER_LEVEL0) {
993 archive_delim = "\\";
996 strncpy(lzname, hdr->name, sizeof(lzname));
997 convert_filename(lzname, strlen(lzname), sizeof(lzname),
1000 system_delim, archive_delim, filename_case);
1002 if (hdr->header_level != HEADER_LEVEL2) {
1004 /* level 0 header: write pathname (contain the directory part) */
1005 /* level 1 header: write filename (basename only) */
1006 if (hdr->header_level == HEADER_LEVEL0 ||
1007 (p = strrchr(lzname, LHA_PATHSEP)) == 0)
1011 name_length = strlen(p);
1013 limit = 255 - I_UNIX_EXTEND_BOTTOM + 2;
1014 if (header_level == 0) {
1016 limit = 255 - I_GENERIC_HEADER_BOTTOM + 2;
1018 if (name_length > limit) {
1019 warning("the length of pathname \"%s\" is too long.", p);
1020 name_length = limit;
1024 if (header_level == 1) {
1028 put_byte(name_length);
1029 memcpy(data + I_NAME, p, name_length);
1030 setup_put(data + I_NAME + name_length);
1035 if (header_level == HEADER_LEVEL0) {
1036 if (generic_format) {
1037 header_size = I_GENERIC_HEADER_BOTTOM - 2 + name_length;
1038 data[I_HEADER_SIZE] = header_size;
1039 data[I_HEADER_CHECKSUM] = calc_sum(data + I_METHOD, header_size);
1041 /* write old-style extend header */
1042 put_byte(EXTEND_UNIX);
1043 put_byte(CURRENT_UNIX_MINOR_VERSION);
1044 put_longword((long) hdr->unix_last_modified_stamp);
1045 put_word(hdr->unix_mode);
1046 put_word(hdr->unix_uid);
1047 put_word(hdr->unix_gid);
1048 header_size = I_UNIX_EXTEND_BOTTOM - 2 + name_length;
1049 data[I_HEADER_SIZE] = header_size;
1050 data[I_HEADER_CHECKSUM] = calc_sum(data + I_METHOD, header_size);
1053 /* write extend header. */
1059 put_byte(EXTEND_UNIX);
1062 if (hdr->header_level == HEADER_LEVEL2) {
1063 /* write common header */
1066 headercrc_ptr = put_ptr;
1070 if (generic_format) {
1071 header_size = put_ptr - data; /* +2 for last 0x0000 */
1074 if (hdr->header_level == HEADER_LEVEL1)
1075 header_size = put_ptr - data - 2;
1076 put_byte(0x50); /* permission */
1077 put_word(hdr->unix_mode);
1079 put_byte(0x51); /* gid and uid */
1080 put_word(hdr->unix_gid);
1081 put_word(hdr->unix_uid);
1084 int i, len = strlen(hdr->group);
1087 put_byte(0x52); /* group name */
1088 for (i = 0; i < len; i++)
1089 put_byte(hdr->group[i]);
1092 len = strlen(hdr->user);
1095 put_byte(0x53); /* user name */
1096 for (i = 0; i < len; i++)
1097 put_byte(hdr->user[i]);
1101 if (hdr->header_level == 1) {
1103 if (p = strrchr(lzname, LHA_PATHSEP))
1104 name_length = strlen(++p);
1107 name_length = strlen(lzname);
1109 put_word(name_length + 3);
1110 put_byte(1); /* filename */
1111 for (i = 0; i < name_length; i++)
1115 if (p = strrchr(lzname, LHA_PATHSEP)) {
1118 name_length = p - lzname + 1;
1119 put_word(name_length + 3);
1120 put_byte(2); /* dirname */
1121 for (i = 0; i < name_length; i++)
1122 put_byte(lzname[i]);
1124 } /* if generic .. */
1126 if (header_level != HEADER_LEVEL2) {
1127 if (!generic_format) {
1129 put_byte(0x54); /* time stamp */
1130 put_longword(hdr->unix_last_modified_stamp);
1132 hdr->packed_size += put_ptr - ptr;
1134 setup_put(data + I_PACKED_SIZE);
1135 put_longword(hdr->packed_size);
1137 data[I_HEADER_SIZE] = header_size;
1138 data[I_HEADER_CHECKSUM] = calc_sum(data + I_METHOD, header_size);
1139 } else { /* header level 2 */
1141 if (p = strrchr(lzname, LHA_PATHSEP))
1142 name_length = strlen(++p);
1145 name_length = strlen(lzname);
1147 put_word(name_length + 3);
1148 put_byte(1); /* filename */
1149 for (i = 0; i < name_length; i++)
1151 } /* if he.. != HEAD_LV2 */
1152 header_size = put_ptr - data;
1155 if (header_level == HEADER_LEVEL2) {
1156 unsigned short hcrc;
1157 setup_put(data + I_HEADER_SIZE);
1158 put_word(header_size + 2);
1160 hcrc = calc_header_crc(data, (unsigned int) header_size + 2);
1161 setup_put(headercrc_ptr);
1165 if (fwrite(data, header_size + 2, 1, nafp) == 0)
1166 fatal_error("Cannot write to temporary file");
1169 #if MULTIBYTE_FILENAME
1171 #if defined(__APPLE__)
1173 #include <CoreFoundation/CFString.h>
1174 #include <CoreFoundation/CFStringEncodingExt.h>
1176 /* this is not need for Mac OS X v 10.2 later */
1178 kCFStringEncodingAllowLossyConversion = 1,
1179 kCFStringEncodingBasicDirectionLeftToRight = (1 << 1),
1180 kCFStringEncodingBasicDirectionRightToLeft = (1 << 2),
1181 kCFStringEncodingSubstituteCombinings = (1 << 3),
1182 kCFStringEncodingComposeCombinings = (1 << 4),
1183 kCFStringEncodingIgnoreCombinings = (1 << 5),
1184 kCFStringEncodingUseCanonical = (1 << 6),
1185 kCFStringEncodingUseHFSPlusCanonical = (1 << 7),
1186 kCFStringEncodingPrependBOM = (1 << 8),
1187 kCFStringEncodingDisableCorporateArea = (1 << 9),
1188 kCFStringEncodingASCIICompatibleConversion = (1 << 10),
1192 ConvertEncodingToUTF8(const char* inCStr,
1193 char* outUTF8Buffer,
1194 int outUTF8BufferLength,
1195 unsigned long scriptEncoding,
1196 unsigned long flags)
1198 unsigned long unicodeChars;
1199 unsigned long srcCharsUsed;
1200 unsigned long usedByteLen = 0;
1201 UniChar uniStr[512];
1202 unsigned long cfResult;
1204 cfResult = CFStringEncodingBytesToUnicode(scriptEncoding,
1212 if (cfResult == 0) {
1213 cfResult = CFStringEncodingUnicodeToBytes(kCFStringEncodingUTF8,
1218 (char*)outUTF8Buffer,
1219 outUTF8BufferLength - 1,
1221 outUTF8Buffer[usedByteLen] = '\0';
1228 ConvertUTF8ToEncoding(const char* inUTF8Buf,
1229 int inUTF8BufLength,
1230 char* outCStrBuffer,
1231 int outCStrBufferLength,
1232 unsigned long scriptEncoding,
1233 unsigned long flags)
1235 unsigned long unicodeChars;
1236 unsigned long srcCharsUsed;
1237 unsigned long usedByteLen = 0;
1238 UniChar uniStr[256];
1239 unsigned long cfResult;
1241 cfResult = CFStringEncodingBytesToUnicode(kCFStringEncodingUTF8,
1249 if (cfResult == 0) {
1250 cfResult = CFStringEncodingUnicodeToBytes(scriptEncoding,
1255 (char*)outCStrBuffer,
1256 outCStrBufferLength - 1,
1258 outCStrBuffer[usedByteLen] = '\0';
1268 ConvertEncodingByIconv(const char *src, char *dst, int dstsize,
1269 const char *srcEnc, const char *dstEnc)
1272 static char szTmpBuf[2048];
1278 dst_p = &szTmpBuf[0];
1279 iLen = (size_t)sizeof(szTmpBuf)-1;
1280 src_p = (char *)src;
1281 sLen = (size_t)strlen(src);
1282 memset(szTmpBuf, 0, sizeof(szTmpBuf));
1283 memset(dst, 0, dstsize);
1285 ic = iconv_open(dstEnc, srcEnc);
1286 if (ic == (iconv_t)-1) {
1287 error("iconv_open() failure");
1291 if (iconv(ic, &src_p, &sLen, &dst_p, &iLen) == (size_t)-1) {
1292 error("iconv() failure");
1297 strncpy(dst, szTmpBuf, dstsize);
1303 #endif /* defined(__APPLE__) */
1306 sjis_to_utf8(char *dst, const char *src, size_t dstsize)
1308 #if defined(__APPLE__)
1310 if (ConvertEncodingToUTF8(src, dst, dstsize,
1311 kCFStringEncodingDOSJapanese,
1312 kCFStringEncodingUseHFSPlusCanonical) == 0)
1315 if (ConvertEncodingByIconv(src, dst, dstsize, "SJIS", "UTF-8") != -1)
1318 error("not support utf-8 conversion");
1322 if (dstsize < 1) return dst;
1324 return strncpy(dst, src, dstsize-1);
1328 utf8_to_sjis(char *dst, const char *src, size_t dstsize)
1330 #if defined(__APPLE__)
1334 srclen = strlen(src);
1335 if (ConvertUTF8ToEncoding(src, srclen, dst, dstsize,
1336 kCFStringEncodingDOSJapanese,
1337 kCFStringEncodingUseHFSPlusCanonical) == 0)
1340 if (ConvertEncodingByIconv(src, dst, dstsize, "UTF-8", "SJIS") != -1)
1343 error("not support utf-8 conversion");
1347 if (dstsize < 1) return dst;
1349 return strncpy(dst, src, dstsize-1);
1353 * SJIS <-> EUC ÊÑ´¹´Ø¿ô
1354 * ¡ÖÆüËܸì¾ðÊó½èÍý¡× ¥½¥Õ¥È¥Ð¥ó¥¯(³ô)
1355 * ¤è¤êÈ´¿è(by Koji Arai)
1358 euc2sjis(int *p1, int *p2)
1360 unsigned char c1 = *p1 & 0x7f;
1361 unsigned char c2 = *p2 & 0x7f;
1362 int rowoff = c1 < 0x5f ? 0x70 : 0xb0;
1363 int celoff = c1 % 2 ? (c2 > 0x5f ? 0x20 : 0x1f) : 0x7e;
1364 *p1 = ((c1 + 1) >> 1) + rowoff;
1365 *p2 += celoff - 0x80;
1369 sjis2euc(int *p1, int *p2)
1371 unsigned char c1 = *p1;
1372 unsigned char c2 = *p2;
1373 int adjust = c2 < 0x9f;
1374 int rowoff = c1 < 0xa0 ? 0x70 : 0xb0;
1375 int celoff = adjust ? (c2 > 0x7f ? 0x20 : 0x1f) : 0x7e;
1376 *p1 = ((c1 - rowoff) << 1) - adjust;
1382 #endif /* MULTIBYTE_FILENAME */
1384 /* Local Variables: */
1387 /* compile-command:"gcc -c header.c" */
1389 /* vi: set tabstop=4: */