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[256]; /* 256 is sizeof(LzHeader.name) */
219 if (from_code == CODE_SJIS && to_code == CODE_UTF8) {
220 for (i = 0; i < len; i++)
221 if ((unsigned char)name[i] == LHA_PATHSEP) name[i] = '/';
222 sjis_to_utf8(tmp, name, sizeof(tmp));
223 strncpy(name, tmp, size);
226 for (i = 0; i < len; i++)
227 if (name[i] == '/') name[i] = LHA_PATHSEP;
228 from_code = CODE_UTF8;
230 else if (from_code == CODE_UTF8 && to_code == CODE_SJIS) {
231 for (i = 0; i < len; i++)
232 if ((unsigned char)name[i] == LHA_PATHSEP) name[i] = '/';
233 utf8_to_sjis(tmp, name, sizeof(tmp));
234 strncpy(name, tmp, size);
237 for (i = 0; i < len; i++)
238 if (name[i] == '/') name[i] = LHA_PATHSEP;
239 from_code = CODE_SJIS;
243 for (i = 0; i < len; i ++) {
244 #ifdef MULTIBYTE_FILENAME
245 if (from_code == CODE_EUC &&
246 (unsigned char)name[i] == 0x8e) {
247 if (to_code != CODE_SJIS) {
253 memmove(name + i, name + i + 1, len - i);
257 if (from_code == CODE_SJIS && X0201_KANA_P(name[i])) {
258 if (to_code != CODE_EUC) {
262 if (len == size - 1) /* check overflow */
264 memmove(name+i+1, name+i, len-i);
270 if (from_code == CODE_EUC && (name[i] & 0x80) && (name[i+1] & 0x80)) {
272 if (to_code != CODE_SJIS) {
277 c1 = (unsigned char)name[i];
278 c2 = (unsigned char)name[i+1];
285 if (from_code == CODE_SJIS &&
286 SJC_FIRST_P(name[i]) &&
287 SJC_SECOND_P(name[i+1])) {
290 if (to_code != CODE_EUC) {
295 c1 = (unsigned char)name[i];
296 c2 = (unsigned char)name[i+1];
303 #endif /* MULTIBYTE_FILENAME */
307 /* transpose from_delim to to_delim */
309 if ((ptr = strchr(from_delim, name[i])) != NULL) {
310 name[i] = to_delim[ptr - from_delim];
315 if (case_to == TO_UPPER && islower(name[i])) {
316 name[i] = toupper(name[i]);
319 if (case_to == TO_LOWER && isupper(name[i])) {
320 name[i] = tolower(name[i]);
326 /* ------------------------------------------------------------------------ */
328 /* Generic stamp format: */
330 /* 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 */
331 /* |<-------- year ------->|<- month ->|<-- day -->| */
333 /* 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 */
334 /* |<--- hour --->|<---- minute --->|<- second*2 ->| */
336 /* ------------------------------------------------------------------------ */
339 * NOTE : If you don't have `gettimeofday(2)', or your gettimeofday(2)
340 * returns bogus timezone information, try FTIME, MKTIME, TIMELOCAL or TZSET.
344 #if defined(HAVE_MKTIME)
345 #ifdef HAVE_TIMELOCAL
346 #undef HAVE_TIMELOCAL
348 #endif /* defined(HAVE_MKTIME) */
350 #if defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL)
354 #endif /* defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL) */
356 #if defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL) || defined(HAVE_TZSET)
362 #if defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL) || defined(HAVE_TZSET) || defined(HAVE_FTIME)
363 #ifdef HAVE_GETTIMEOFDAY
364 #undef HAVE_GETTIMEOFDAY
367 #ifndef HAVE_GETTIMEOFDAY
368 #define HAVE_GETTIMEOFDAY /* use gettimeofday() */
373 #include <sys/timeb.h>
377 * You may define as : #define TIMEZONE_HOOK \ extern long
378 * timezone ; \ extern void tzset();
382 /* Which do you like better, `TIMEZONE_HOOK' or `TIMEZONE_HOOK;' ? */
385 #if defined(HAVE_TZSET) && defined(_MINIX)
386 extern long timezone; /* not defined in time.h */
389 /* ------------------------------------------------------------------------ */
390 #if defined(HAVE_FTIME) || defined(HAVE_GETTIMEOFDAY) || defined(HAVE_TZSET)
400 /* ------------------------------------------------------------------------ */
401 #if !defined(HAVE_TZSET) && defined(HAVE_FTIME)
406 return buf.timezone * 60L;
410 /* ------------------------------------------------------------------------ */
411 #if !defined(HAVE_TZSET) && !defined(HAVE_FTIME) /* maybe defined(HAVE_GETTIMEOFDAY) */
413 #ifdef HAVE_STRUCT_TM_TM_GMTOFF
417 return -localtime(&tt)->tm_gmtoff;
418 #else /* HAVE_STRUCT_TM_TM_GMTOFF */
421 gettimeofday(&tp, &tzp);/* specific to 4.3BSD */
423 * return (tzp.tz_minuteswest * 60L + (tzp.tz_dsttime != 0 ? 60L *
426 return (tzp.tz_minuteswest * 60L);
427 #endif /* HAVE_STRUCT_TM_TM_GMTOFF */
430 #endif /* defined(HAVE_FTIME) || defined(HAVE_GETTIMEOFDAY) ||
431 * defined(HAVE_TZSET) */
433 /* ------------------------------------------------------------------------ */
436 msdos_to_unix_stamp_tm(a)
441 t.tm_sec = (a & 0x1f) * 2;
442 t.tm_min = (a >> 5) & 0x3f;
443 t.tm_hour = (a >> 11) & 0x1f;
444 t.tm_mday = (a >> 16) & 0x1f;
445 t.tm_mon = ((a >> 16 + 5) & 0x0f) - 1;
446 t.tm_year = ((a >> 16 + 9) & 0x7f) + 80;
451 /* ------------------------------------------------------------------------ */
453 generic_to_unix_stamp(t)
455 #if defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL)
460 * special case: if MSDOS format date and time were zero, then we
461 * set time to be zero here too.
466 dostm.tm_sec = (t & 0x1f) * 2;
467 dostm.tm_min = t >> 5 & 0x3f;
468 dostm.tm_hour = t >> 11 & 0x1f;
469 dostm.tm_mday = t >> 16 & 0x1f;
470 dostm.tm_mon = (t >> 16 + 5 & 0x0f) - 1; /* 0..11 */
471 dostm.tm_year = (t >> 16 + 9 & 0x7f) + 80;
473 dostm.tm_isdst = 0; /* correct? */
475 dostm.tm_isdst = -1; /* correct? */
477 return (time_t) mktime(&dostm);
478 #else /* maybe defined(HAVE_TIMELOCAL) */
479 return (time_t) timelocal(&dostm);
483 #else /* defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL) */
485 int year, month, day, hour, min, sec;
487 static unsigned int dsboy[12] = {0, 31, 59, 90, 120, 151,
488 181, 212, 243, 273, 304, 334};
492 * special case: if MSDOS format date and time were zero, then we
493 * set time to be zero here too.
498 year = ((int) (t >> 16 + 9) & 0x7f) + 1980;
499 month = (int) (t >> 16 + 5) & 0x0f; /* 1..12 means Jan..Dec */
500 day = (int) (t >> 16) & 0x1f; /* 1..31 means 1st,...31st */
502 hour = ((int) t >> 11) & 0x1f;
503 min = ((int) t >> 5) & 0x3f;
504 sec = ((int) t & 0x1f) * 2;
506 /* Calculate days since 1970.01.01 */
507 days = (365 * (year - 1970) + /* days due to whole years */
508 (year - 1970 + 1) / 4 + /* days due to leap years */
509 dsboy[month - 1] + /* days since beginning of this year */
510 day - 1); /* days since beginning of month */
512 if ((year % 4 == 0) &&
513 (year % 100 != 0 || year % 400 == 0) && /* 1999.5.24 t.oka */
514 (month >= 3)) /* if this is a leap year and month */
515 days++; /* is March or later, add a day */
517 /* Knowing the days, we can find seconds */
518 longtime = (((days * 24) + hour) * 60 + min) * 60 + sec;
519 longtime += gettz(); /* adjust for timezone */
521 /* LONGTIME is now the time in seconds, since 1970/01/01 00:00:00. */
522 return (time_t) longtime;
524 #endif /* defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL) */
526 /* ------------------------------------------------------------------------ */
528 unix_to_generic_stamp(t)
531 struct tm *tm = localtime(&t);
533 return ((((long) (tm->tm_year - 80)) << 25) +
534 (((long) (tm->tm_mon + 1)) << 21) +
535 (((long) tm->tm_mday) << 16) +
536 (long) ((tm->tm_hour << 11) +
541 /* ------------------------------------------------------------------------ */
542 /* build header functions */
543 /* ------------------------------------------------------------------------ */
547 register LzHeader *hdr;
551 char data[LZHEADER_STRAGE];
552 char dirname[FILENAME_LENGTH];
560 int archive_kanji_code = CODE_SJIS;
561 int system_kanji_code = default_system_kanji_code;
562 char *archive_delim = "";
563 char *system_delim = "";
564 int filename_case = NONE;
566 memset(hdr, 0, sizeof(LzHeader));
568 if (((header_size = getc(fp)) == EOF) || (header_size == 0)) {
569 return FALSE; /* finish */
572 if (fread(data + I_HEADER_CHECKSUM,
573 sizeof(char), header_size - 1, fp) < header_size - 1) {
574 fatal_error("Invalid header (LHarc file ?)");
575 return FALSE; /* finish */
577 setup_get(data + I_HEADER_LEVEL);
578 hdr->header_level = get_byte();
579 if (hdr->header_level != 2 &&
580 fread(data + header_size, sizeof(char), 2, fp) < 2) {
581 fatal_error("Invalid header (LHarc file ?)");
582 return FALSE; /* finish */
585 if (hdr->header_level >= 3) {
586 fatal_error("Unknown level header (level %d)", hdr->header_level);
590 setup_get(data + I_HEADER_CHECKSUM);
591 checksum = get_byte();
593 if (hdr->header_level == 2) {
594 hdr->header_size = header_size + checksum*256;
596 hdr->header_size = header_size;
598 memcpy(hdr->method, data + I_METHOD, METHOD_TYPE_STRAGE);
599 setup_get(data + I_PACKED_SIZE);
600 hdr->packed_size = get_longword();
601 hdr->original_size = get_longword();
602 hdr->last_modified_stamp = get_longword();
603 hdr->attribute = get_byte();
605 if ((hdr->header_level = get_byte()) != 2) {
606 if (calc_sum(data + I_METHOD, header_size) != checksum)
607 warning("Checksum error (LHarc file?)");
608 name_length = get_byte();
609 for (i = 0; i < name_length; i++)
610 hdr->name[i] = (char) get_byte();
611 hdr->name[name_length] = '\0';
614 hdr->unix_last_modified_stamp = hdr->last_modified_stamp;
618 /* defaults for other type */
619 hdr->unix_mode = UNIX_FILE_REGULAR | UNIX_RW_RW_RW;
623 if (hdr->header_level == 0) {
624 extend_size = header_size - name_length -22;
625 if (extend_size < 0) {
626 if (extend_size == -2) {
627 hdr->extend_type = EXTEND_GENERIC;
628 hdr->has_crc = FALSE;
630 error("Unkonwn header (lha file?)");
635 hdr->crc = get_word();
638 if (extend_size >= 1) {
639 hdr->extend_type = get_byte();
642 if (hdr->extend_type == EXTEND_UNIX) {
643 if (extend_size >= 11) {
644 hdr->minor_version = get_byte();
645 hdr->unix_last_modified_stamp = (time_t) get_longword();
646 hdr->unix_mode = get_word();
647 hdr->unix_uid = get_word();
648 hdr->unix_gid = get_word();
651 hdr->extend_type = EXTEND_GENERIC;
654 while (extend_size-- > 0)
656 } else if (hdr->header_level == 1) {
658 extend_size = header_size - name_length-25;
659 hdr->crc = get_word();
660 hdr->extend_type = get_byte();
661 while (extend_size-- > 0)
663 } else { /* level 2 */
665 hdr->crc = get_word();
666 hdr->extend_type = get_byte();
669 if (hdr->header_level > 0) {
671 if (hdr->header_level != 2)
672 setup_get(data + hdr->header_size);
674 while ((header_size = get_word()) != 0) {
675 if (hdr->header_level != 2 &&
676 ((data + LZHEADER_STRAGE - get_ptr < header_size) ||
677 fread(get_ptr, sizeof(char), header_size, fp) < header_size)) {
678 fatal_error("Invalid header (LHa file ?)");
681 switch (get_byte()) {
686 setup_get(get_ptr + header_size - 3);
692 for (i = 0; i < header_size - 3; i++)
693 hdr->name[i] = (char) get_byte();
694 hdr->name[header_size - 3] = '\0';
695 name_length = header_size - 3;
701 for (i = 0; i < header_size - 3; i++)
702 dirname[i] = (char) get_byte();
703 dirname[header_size - 3] = '\0';
704 dir_length = header_size - 3;
710 if (hdr->extend_type == EXTEND_MSDOS ||
711 hdr->extend_type == EXTEND_HUMAN ||
712 hdr->extend_type == EXTEND_GENERIC)
713 hdr->attribute = get_word();
719 if (hdr->extend_type == EXTEND_UNIX)
720 hdr->unix_mode = get_word();
726 if (hdr->extend_type == EXTEND_UNIX) {
727 hdr->unix_gid = get_word();
728 hdr->unix_uid = get_word();
735 for (i = 0; i < header_size - 3; i++)
736 hdr->group[i] = get_byte();
737 hdr->group[i] = '\0';
743 for (i = 0; i < header_size - 3; i++)
744 hdr->user[i] = get_byte();
749 * UNIX last modified time
751 if (hdr->extend_type == EXTEND_UNIX)
752 hdr->unix_last_modified_stamp = (time_t) get_longword();
758 setup_get(get_ptr + header_size - 3);
762 if (hdr->header_level != 2 && get_ptr - ptr != 2) {
763 hdr->packed_size -= get_ptr - ptr - 2;
764 hdr->header_size += get_ptr - ptr - 2;
768 switch (hdr->extend_type) {
770 archive_delim = "\377\\";
771 /* `\' is for level 0 header and broken archive. */
773 filename_case = noconvertcase ? NONE : TO_LOWER;
777 if (hdr->header_level == 2)
778 hdr->unix_last_modified_stamp = hdr->last_modified_stamp;
780 hdr->unix_last_modified_stamp =
781 generic_to_unix_stamp(hdr->last_modified_stamp);
789 archive_delim = "\377\\";
790 /* `\' is for level 0 header and broken archive. */
792 filename_case = NONE;
797 archive_delim = "\377/:\\";
798 /* `\' is for level 0 header and broken archive. */
799 system_delim = "/://";
800 filename_case = NONE;
802 hdr->unix_last_modified_stamp =
803 generic_to_unix_stamp(hdr->last_modified_stamp, sizeof(hdr->name));
807 archive_delim = "\377\\";
808 /* `\' is for level 0 header and broken archive. */
810 filename_case = noconvertcase ? NONE : TO_LOWER;
811 /* FIXME: if small letter is included in filename,
812 the generic_to_unix_filename() do not case conversion,
813 but this code does not consider it. */
815 if (hdr->header_level == 2)
816 hdr->unix_last_modified_stamp = hdr->last_modified_stamp;
818 hdr->unix_last_modified_stamp =
819 generic_to_unix_stamp(hdr->last_modified_stamp);
822 /* filename kanji code and delimiter conversion */
823 if (optional_archive_kanji_code)
824 archive_kanji_code = optional_archive_kanji_code;
825 if (optional_system_kanji_code)
826 system_kanji_code = optional_system_kanji_code;
827 if (optional_archive_delim)
828 archive_delim = optional_archive_delim;
829 if (optional_system_delim)
830 system_delim = optional_system_delim;
831 if (optional_filename_case)
832 filename_case = optional_filename_case;
835 strcat(dirname, hdr->name);
836 strcpy(hdr->name, dirname);
837 name_length += dir_length;
840 convert_filename(hdr->name, name_length, sizeof(hdr->name),
843 archive_delim, system_delim, filename_case);
848 /* ------------------------------------------------------------------------ */
850 init_header(name, v_stat, hdr)
857 memset(hdr, 0, sizeof(LzHeader));
859 if (compress_method == LZHUFF5_METHOD_NUM) /* Changed N.Watazaki */
860 memcpy(hdr->method, LZHUFF5_METHOD, METHOD_TYPE_STRAGE);
861 else if (compress_method)
862 memcpy(hdr->method, LZHUFF1_METHOD, METHOD_TYPE_STRAGE);
864 memcpy(hdr->method, LZHUFF0_METHOD, METHOD_TYPE_STRAGE);
866 hdr->packed_size = 0;
867 hdr->original_size = v_stat->st_size;
868 hdr->last_modified_stamp = unix_to_generic_stamp(v_stat->st_mtime);
869 hdr->attribute = GENERIC_ATTRIBUTE;
870 hdr->header_level = header_level;
871 strcpy(hdr->name, name);
874 hdr->extend_type = EXTEND_UNIX;
875 hdr->unix_last_modified_stamp = v_stat->st_mtime;
876 /* since 00:00:00 JAN.1.1970 */
877 #ifdef NOT_COMPATIBLE_MODE
878 /* Please need your modification in this space. */
880 hdr->unix_mode = v_stat->st_mode;
883 hdr->unix_uid = v_stat->st_uid;
884 hdr->unix_gid = v_stat->st_gid;
886 #if INCLUDE_OWNER_NAME_IN_HEADER
889 struct passwd *ent = getpwuid(hdr->unix_uid);
892 strncpy(hdr->user, ent->pw_name, sizeof(hdr->user));
893 if (hdr->user[sizeof(hdr->user)-1])
894 hdr->user[sizeof(hdr->user)-1] = 0;
900 struct group *ent = getgrgid(hdr->unix_gid);
903 strncpy(hdr->group, ent->gr_name, sizeof(hdr->group));
904 if (hdr->group[sizeof(hdr->group)-1])
905 hdr->group[sizeof(hdr->group)-1] = 0;
909 #endif /* INCLUDE_OWNER_NAME_IN_HEADER */
910 if (is_directory(v_stat)) {
911 memcpy(hdr->method, LZHDIRS_METHOD, METHOD_TYPE_STRAGE);
912 hdr->attribute = GENERIC_DIRECTORY_ATTRIBUTE;
913 hdr->original_size = 0;
914 if (len > 0 && hdr->name[len - 1] != '/')
915 strcpy(&hdr->name[len++], "/");
919 if (is_symlink(v_stat)) {
920 char lkname[FILENAME_LENGTH];
922 memcpy(hdr->method, LZHDIRS_METHOD, METHOD_TYPE_STRAGE);
923 hdr->attribute = GENERIC_DIRECTORY_ATTRIBUTE;
924 hdr->original_size = 0;
925 len = readlink(name, lkname, sizeof(lkname));
926 if (xsnprintf(hdr->name, sizeof(hdr->name),
927 "%s|%.*s", hdr->name, len, lkname) == -1)
928 error("file name is too long (%s -> %.*s)", hdr->name, len, lkname);
933 /* ------------------------------------------------------------------------ */
934 /* Write unix extended header or generic header. */
936 write_header(nafp, hdr)
942 char data[LZHEADER_STRAGE];
946 int archive_kanji_code = CODE_SJIS;
947 int system_kanji_code = default_system_kanji_code;
948 char *archive_delim = "\377";
949 char *system_delim = "/";
950 int filename_case = NONE;
951 char lzname[FILENAME_LENGTH];
953 if (optional_archive_kanji_code)
954 archive_kanji_code = optional_archive_kanji_code;
955 if (optional_system_kanji_code)
956 system_kanji_code = optional_system_kanji_code;
958 memset(data, 0, LZHEADER_STRAGE);
959 memcpy(data + I_METHOD, hdr->method, METHOD_TYPE_STRAGE);
960 setup_put(data + I_PACKED_SIZE);
961 put_longword(hdr->packed_size);
962 put_longword(hdr->original_size);
964 if (hdr->header_level == HEADER_LEVEL2)
965 put_longword((long) hdr->unix_last_modified_stamp);
967 put_longword(hdr->last_modified_stamp);
969 switch (hdr->header_level) {
971 put_byte(hdr->attribute);
979 put_byte(hdr->header_level);
982 filename_case = TO_UPPER;
984 if (hdr->header_level == HEADER_LEVEL0) {
985 archive_delim = "\\";
988 strncpy(lzname, hdr->name, sizeof(lzname));
989 convert_filename(lzname, strlen(lzname), sizeof(lzname),
992 system_delim, archive_delim, filename_case);
994 if (hdr->header_level != HEADER_LEVEL2) {
995 if (hdr->header_level == HEADER_LEVEL0 ||
996 (p = strrchr(lzname, LHA_PATHSEP)) == 0)
1000 /* level 0 header: write pathname (contain the directory part) */
1001 /* level 1 header: write filename (basename only) */
1002 name_length = strlen(p);
1003 put_byte(name_length);
1004 memcpy(data + I_NAME, p, name_length);
1005 setup_put(data + I_NAME + name_length);
1009 if (header_level == HEADER_LEVEL0) {
1010 if (generic_format) {
1011 header_size = I_GENERIC_HEADER_BOTTOM - 2 + name_length;
1012 data[I_HEADER_SIZE] = header_size;
1013 data[I_HEADER_CHECKSUM] = calc_sum(data + I_METHOD, header_size);
1015 /* write old-style extend header */
1016 put_byte(EXTEND_UNIX);
1017 put_byte(CURRENT_UNIX_MINOR_VERSION);
1018 put_longword((long) hdr->unix_last_modified_stamp);
1019 put_word(hdr->unix_mode);
1020 put_word(hdr->unix_uid);
1021 put_word(hdr->unix_gid);
1022 header_size = I_UNIX_EXTEND_BOTTOM - 2 + name_length;
1023 data[I_HEADER_SIZE] = header_size;
1024 data[I_HEADER_CHECKSUM] = calc_sum(data + I_METHOD, header_size);
1027 /* write extend header. */
1033 put_byte(EXTEND_UNIX);
1036 if (hdr->header_level == HEADER_LEVEL2) {
1037 /* write common header */
1040 headercrc_ptr = put_ptr;
1044 if (generic_format) {
1045 header_size = put_ptr - data; /* +2 for last 0x0000 */
1048 if (hdr->header_level == HEADER_LEVEL1)
1049 header_size = put_ptr - data - 2;
1050 put_byte(0x50); /* permission */
1051 put_word(hdr->unix_mode);
1053 put_byte(0x51); /* gid and uid */
1054 put_word(hdr->unix_gid);
1055 put_word(hdr->unix_uid);
1058 int i, len = strlen(hdr->group);
1060 put_byte(0x52); /* group name */
1061 for (i = 0; i < len; i++)
1062 put_byte(hdr->group[i]);
1064 len = strlen(hdr->user);
1066 put_byte(0x53); /* user name */
1067 for (i = 0; i < len; i++)
1068 put_byte(hdr->user[i]);
1071 if (p = strrchr(lzname, LHA_PATHSEP)) {
1074 name_length = p - lzname + 1;
1075 put_word(name_length + 3);
1076 put_byte(2); /* dirname */
1077 for (i = 0; i < name_length; i++)
1078 put_byte(lzname[i]);
1080 } /* if generic .. */
1082 if (header_level != HEADER_LEVEL2) {
1083 if (!generic_format) {
1085 put_byte(0x54); /* time stamp */
1086 put_longword(hdr->unix_last_modified_stamp);
1088 hdr->packed_size += put_ptr - ptr;
1090 setup_put(data + I_PACKED_SIZE);
1091 put_longword(hdr->packed_size);
1093 data[I_HEADER_SIZE] = header_size;
1094 data[I_HEADER_CHECKSUM] = calc_sum(data + I_METHOD, header_size);
1095 } else { /* header level 2 */
1097 if (p = strrchr(lzname, LHA_PATHSEP))
1098 name_length = strlen(++p);
1101 name_length = strlen(lzname);
1103 put_word(name_length + 3);
1104 put_byte(1); /* filename */
1105 for (i = 0; i < name_length; i++)
1107 } /* if he.. != HEAD_LV2 */
1108 header_size = put_ptr - data;
1111 if (header_level == HEADER_LEVEL2) {
1112 unsigned short hcrc;
1113 setup_put(data + I_HEADER_SIZE);
1114 put_word(header_size + 2);
1116 hcrc = calc_header_crc(data, (unsigned int) header_size + 2);
1117 setup_put(headercrc_ptr);
1121 if (fwrite(data, header_size + 2, 1, nafp) == 0)
1122 fatal_error("Cannot write to temporary file");
1125 #if MULTIBYTE_FILENAME
1127 #if defined(__APPLE__)
1129 #include <CoreFoundation/CFString.h>
1130 #include <CoreFoundation/CFStringEncodingExt.h>
1132 /* this is not need for Mac OS X v 10.2 later */
1134 kCFStringEncodingAllowLossyConversion = 1,
1135 kCFStringEncodingBasicDirectionLeftToRight = (1 << 1),
1136 kCFStringEncodingBasicDirectionRightToLeft = (1 << 2),
1137 kCFStringEncodingSubstituteCombinings = (1 << 3),
1138 kCFStringEncodingComposeCombinings = (1 << 4),
1139 kCFStringEncodingIgnoreCombinings = (1 << 5),
1140 kCFStringEncodingUseCanonical = (1 << 6),
1141 kCFStringEncodingUseHFSPlusCanonical = (1 << 7),
1142 kCFStringEncodingPrependBOM = (1 << 8),
1143 kCFStringEncodingDisableCorporateArea = (1 << 9),
1144 kCFStringEncodingASCIICompatibleConversion = (1 << 10),
1148 ConvertEncodingToUTF8(const char* inCStr,
1149 char* outUTF8Buffer,
1150 int outUTF8BufferLength,
1151 unsigned long scriptEncoding,
1152 unsigned long flags)
1154 unsigned long unicodeChars;
1155 unsigned long srcCharsUsed;
1156 unsigned long usedByteLen = 0;
1157 UniChar uniStr[512];
1158 unsigned long cfResult;
1160 cfResult = CFStringEncodingBytesToUnicode(scriptEncoding,
1168 if (cfResult == 0) {
1169 cfResult = CFStringEncodingUnicodeToBytes(kCFStringEncodingUTF8,
1174 (char*)outUTF8Buffer,
1175 outUTF8BufferLength - 1,
1177 outUTF8Buffer[usedByteLen] = '\0';
1184 ConvertUTF8ToEncoding(const char* inUTF8Buf,
1185 int inUTF8BufLength,
1186 char* outCStrBuffer,
1187 int outCStrBufferLength,
1188 unsigned long scriptEncoding,
1189 unsigned long flags)
1191 unsigned long unicodeChars;
1192 unsigned long srcCharsUsed;
1193 unsigned long usedByteLen = 0;
1194 UniChar uniStr[256];
1195 unsigned long cfResult;
1197 cfResult = CFStringEncodingBytesToUnicode(kCFStringEncodingUTF8,
1205 if (cfResult == 0) {
1206 cfResult = CFStringEncodingUnicodeToBytes(scriptEncoding,
1211 (char*)outCStrBuffer,
1212 outCStrBufferLength - 1,
1214 outCStrBuffer[usedByteLen] = '\0';
1224 ConvertEncodingByIconv(const char *src, char *dst, int dstsize,
1225 const char *srcEnc, const char *dstEnc)
1228 static char szTmpBuf[2048];
1234 dst_p = &szTmpBuf[0];
1235 iLen = (size_t)sizeof(szTmpBuf)-1;
1236 src_p = (char *)src;
1237 sLen = (size_t)strlen(src);
1238 memset(szTmpBuf, 0, sizeof(szTmpBuf));
1239 memset(dst, 0, dstsize);
1241 ic = iconv_open(dstEnc, srcEnc);
1242 if (ic == (iconv_t)-1) {
1243 error("iconv_open() failure");
1247 if (iconv(ic, &src_p, &sLen, &dst_p, &iLen) == (size_t)-1) {
1248 error("iconv() failure");
1253 strncpy(dst, szTmpBuf, dstsize);
1259 #endif /* defined(__APPLE__) */
1262 sjis_to_utf8(char *dst, const char *src, size_t dstsize)
1264 #if defined(__APPLE__)
1266 if (ConvertEncodingToUTF8(src, dst, dstsize,
1267 kCFStringEncodingDOSJapanese,
1268 kCFStringEncodingUseHFSPlusCanonical) == 0)
1271 if (ConvertEncodingByIconv(src, dst, dstsize, "SJIS", "UTF-8") != -1)
1274 error("not support utf-8 conversion");
1278 if (dstsize < 1) return dst;
1280 return strncpy(dst, src, dstsize-1);
1284 utf8_to_sjis(char *dst, const char *src, size_t dstsize)
1286 #if defined(__APPLE__)
1290 srclen = strlen(src);
1291 if (ConvertUTF8ToEncoding(src, srclen, dst, dstsize,
1292 kCFStringEncodingDOSJapanese,
1293 kCFStringEncodingUseHFSPlusCanonical) == 0)
1296 if (ConvertEncodingByIconv(src, dst, dstsize, "UTF-8", "SJIS") != -1)
1299 error("not support utf-8 conversion");
1303 if (dstsize < 1) return dst;
1305 return strncpy(dst, src, dstsize-1);
1309 * SJIS <-> EUC ÊÑ´¹´Ø¿ô
1310 * ¡ÖÆüËܸì¾ðÊó½èÍý¡× ¥½¥Õ¥È¥Ð¥ó¥¯(³ô)
1311 * ¤è¤êÈ´¿è(by Koji Arai)
1314 euc2sjis(int *p1, int *p2)
1316 unsigned char c1 = *p1 & 0x7f;
1317 unsigned char c2 = *p2 & 0x7f;
1318 int rowoff = c1 < 0x5f ? 0x70 : 0xb0;
1319 int celoff = c1 % 2 ? (c2 > 0x5f ? 0x20 : 0x1f) : 0x7e;
1320 *p1 = ((c1 + 1) >> 1) + rowoff;
1321 *p2 += celoff - 0x80;
1325 sjis2euc(int *p1, int *p2)
1327 unsigned char c1 = *p1;
1328 unsigned char c2 = *p2;
1329 int adjust = c2 < 0x9f;
1330 int rowoff = c1 < 0xa0 ? 0x70 : 0xb0;
1331 int celoff = adjust ? (c2 > 0x7f ? 0x20 : 0x1f) : 0x7e;
1332 *p1 = ((c1 - rowoff) << 1) - adjust;
1338 #endif /* MULTIBYTE_FILENAME */
1340 /* Local Variables: */
1343 /* compile-command:"gcc -c header.c" */
1345 /* vi: set tabstop=4: */