OSDN Git Service

* src/header.c (get_header): [BUG] Could not read level 2 header
[lha/lha.git] / src / header.c
1 /* ------------------------------------------------------------------------ */
2 /* LHa for UNIX                                                                                                                         */
3 /*                              header.c -- header manipulate functions                                         */
4 /*                                                                                                                                                      */
5 /*              Modified                        Nobutaka Watazaki                                                       */
6 /*                                                                                                                                                      */
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 /* ------------------------------------------------------------------------ */
14 #include "lha.h"
15
16 #if !STRCHR_8BIT_CLEAN
17 /* should use 8 bit clean version */
18 #undef strchr
19 #undef strrchr
20 #define strchr  xstrchr
21 #define strrchr  xstrrchr
22 #endif
23
24 /* ------------------------------------------------------------------------ */
25 static char    *get_ptr;
26
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;
32
33 #ifdef MULTIBYTE_FILENAME
34 int default_system_kanji_code = MULTIBYTE_FILENAME;
35 #else
36 int default_system_kanji_code = NONE;
37 #endif
38
39 /* ------------------------------------------------------------------------ */
40 int
41 calc_sum(p, len)
42         register char  *p;
43         register int    len;
44 {
45         register int    sum;
46
47         for (sum = 0; len; len--)
48                 sum += *p++;
49
50         return sum & 0xff;
51 }
52
53 /* ------------------------------------------------------------------------ */
54 static unsigned short
55 get_word()
56 {
57         int             b0, b1;
58
59         b0 = get_byte();
60         b1 = get_byte();
61         return (b1 << 8) + b0;
62 }
63
64 /* ------------------------------------------------------------------------ */
65 static void
66 put_word(v)
67         unsigned int    v;
68 {
69         put_byte(v);
70         put_byte(v >> 8);
71 }
72
73 /* ------------------------------------------------------------------------ */
74 static long
75 get_longword()
76 {
77         long            b0, b1, b2, b3;
78
79         b0 = get_byte();
80         b1 = get_byte();
81         b2 = get_byte();
82         b3 = get_byte();
83         return (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
84 }
85
86 /* ------------------------------------------------------------------------ */
87 static void
88 put_longword(v)
89         long            v;
90 {
91         put_byte(v);
92         put_byte(v >> 8);
93         put_byte(v >> 16);
94         put_byte(v >> 24);
95 }
96
97 #if 0   /* no use */
98 /* ------------------------------------------------------------------------ */
99 static void
100 msdos_to_unix_filename(name, len)
101         register char  *name;
102         register int    len;
103 {
104         register int    i;
105
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]))
110                         i++;
111                 else if (name[i] == '\\')
112                         name[i] = '/';
113                 else if (!noconvertcase && isupper(name[i]))
114                         name[i] = tolower(name[i]);
115         }
116 #else
117         for (i = 0; i < len; i++) {
118                 if (name[i] == '\\')
119                         name[i] = '/';
120                 else if (!noconvertcase && isupper(name[i]))
121                         name[i] = tolower(name[i]);
122         }
123 #endif
124 }
125
126 /* ------------------------------------------------------------------------ */
127 static void
128 generic_to_unix_filename(name, len)
129         register char  *name;
130         register int    len;
131 {
132         register int    i;
133         boolean         lower_case_used = FALSE;
134
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]))
139                         i++;
140                 else if (islower(name[i])) {
141                         lower_case_used = TRUE;
142                         break;
143                 }
144         }
145         for (i = 0; i < len; i++) {
146                 if (MULTIBYTE_FIRST_P(name[i]) &&
147                     MULTIBYTE_SECOND_P(name[i + 1]))
148                         i++;
149                 else if (name[i] == '\\')
150                         name[i] = '/';
151                 else if (!noconvertcase && !lower_case_used && isupper(name[i]))
152                         name[i] = tolower(name[i]);
153         }
154 #else
155         for (i = 0; i < len; i++)
156                 if (islower(name[i])) {
157                         lower_case_used = TRUE;
158                         break;
159                 }
160         for (i = 0; i < len; i++) {
161                 if (name[i] == '\\')
162                         name[i] = '/';
163                 else if (!noconvertcase && !lower_case_used && isupper(name[i]))
164                         name[i] = tolower(name[i]);
165         }
166 #endif
167 }
168
169 /* ------------------------------------------------------------------------ */
170 static void
171 macos_to_unix_filename(name, len)
172         register char  *name;
173         register int    len;
174 {
175         register int    i;
176
177         for (i = 0; i < len; i++) {
178                 if (name[i] == ':')
179                         name[i] = '/';
180                 else if (name[i] == '/')
181                         name[i] = ':';
182         }
183 }
184
185 /* ------------------------------------------------------------------------ */
186 static void
187 unix_to_generic_filename(name, len)
188         register char  *name;
189         register int    len;
190 {
191         register int    i;
192
193         for (i = 0; i < len; i++) {
194                 if (name[i] == '/')
195                         name[i] = '\\';
196                 else if (islower(name[i]))
197                         name[i] = toupper(name[i]);
198         }
199 }
200 #endif /* 0 */
201
202 /* added by Koji Arai */
203 void
204 convert_filename(name, len, size,
205                  from_code, to_code,
206                  from_delim, to_delim,
207                  case_to)
208         register char  *name;
209         register int    len;
210         register int    size;
211     int from_code, to_code, case_to;
212     char *from_delim, *to_delim;
213
214 {
215         register int    i;
216 #ifdef MULTIBYTE_FILENAME
217     char tmp[FILENAME_LENGTH];
218
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);
225         name[size-1] = 0;
226         len = strlen(name);
227         for (i = 0; i < len; i++)
228             if (name[i] == '/')  name[i] = LHA_PATHSEP;
229         from_code = CODE_UTF8;
230     }
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);
237         name[size-1] = 0;
238         len = strlen(name);
239         for (i = 0; i < len; i++)
240             if (name[i] == '/')  name[i] = LHA_PATHSEP;
241         from_code = CODE_SJIS;
242     }
243 #endif
244
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) {
250                 i++;
251                 continue;
252             }
253
254             /* X0201 KANA */
255             memmove(name + i, name + i + 1, len - i);
256             len--;
257             continue;
258         }
259         if (from_code == CODE_SJIS && X0201_KANA_P(name[i])) {
260             if (to_code != CODE_EUC) {
261                 continue;
262             }
263
264             if (len == size - 1) /* check overflow */
265                 len--;
266             memmove(name+i+1, name+i, len-i);
267             name[i] = 0x8e;
268             i++;
269             len++;
270             continue;
271         }
272                 if (from_code == CODE_EUC && (name[i] & 0x80) && (name[i+1] & 0x80)) {
273                         int c1, c2;
274             if (to_code != CODE_SJIS) {
275                 i++;
276                 continue;
277             }
278
279                         c1 = (unsigned char)name[i];
280             c2 = (unsigned char)name[i+1];
281                         euc2sjis(&c1, &c2);
282                         name[i] = c1;
283             name[i+1] = c2;
284                         i++;
285             continue;
286                 }
287         if (from_code == CODE_SJIS &&
288             SJC_FIRST_P(name[i]) &&
289             SJC_SECOND_P(name[i+1])) {
290                         int c1, c2;
291
292             if (to_code != CODE_EUC) {
293                 i++;
294                 continue;
295             }
296
297                         c1 = (unsigned char)name[i];
298             c2 = (unsigned char)name[i+1];
299                         sjis2euc(&c1, &c2);
300                         name[i] = c1;
301             name[i+1] = c2;
302                         i++;
303             continue;
304         }
305 #endif /* MULTIBYTE_FILENAME */
306         {
307             char *ptr;
308
309             /* transpose from_delim to to_delim */
310
311             if ((ptr = strchr(from_delim, name[i])) != NULL) {
312                 name[i] = to_delim[ptr - from_delim];
313                 continue;
314             }
315         }
316
317                 if (case_to == TO_UPPER && islower(name[i])) {
318                         name[i] = toupper(name[i]);
319             continue;
320         }
321         if (case_to == TO_LOWER && isupper(name[i])) {
322                         name[i] = tolower(name[i]);
323             continue;
324         }
325         }
326 }
327
328 /* ------------------------------------------------------------------------ */
329 /*                                                                                                                                                      */
330 /* Generic stamp format:                                                                                                        */
331 /*                                                                                                                                                      */
332 /* 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16                                                      */
333 /* |<-------- year ------->|<- month ->|<-- day -->|                                            */
334 /*                                                                                                                                                      */
335 /* 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0                                                      */
336 /* |<--- hour --->|<---- minute --->|<- second*2 ->|                                            */
337 /*                                                                                                                                                      */
338 /* ------------------------------------------------------------------------ */
339
340 /*
341  * NOTE : If you don't have `gettimeofday(2)', or your gettimeofday(2)
342  * returns bogus timezone information, try FTIME, MKTIME, TIMELOCAL or TZSET.
343  */
344
345 /* choose one */
346 #if defined(HAVE_MKTIME)
347 #ifdef HAVE_TIMELOCAL
348 #undef HAVE_TIMELOCAL
349 #endif
350 #endif                          /* defined(HAVE_MKTIME) */
351
352 #if defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL)
353 #ifdef HAVE_TZSET
354 #undef HAVE_TZSET
355 #endif
356 #endif                          /* defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL) */
357
358 #if defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL) || defined(HAVE_TZSET)
359 #ifdef HAVE_FTIME
360 #undef HAVE_FTIME
361 #endif
362 #endif
363
364 #if defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL) || defined(HAVE_TZSET) || defined(HAVE_FTIME)
365 #ifdef HAVE_GETTIMEOFDAY
366 #undef HAVE_GETTIMEOFDAY
367 #endif
368 #else
369 #ifndef HAVE_GETTIMEOFDAY
370 #define HAVE_GETTIMEOFDAY               /* use gettimeofday() */
371 #endif
372 #endif
373
374 #ifdef HAVE_FTIME
375 #include <sys/timeb.h>
376 #endif
377
378 /*
379  * You may define as : #define TIMEZONE_HOOK            \ extern long
380  * timezone ;   \ extern void tzset();
381  */
382 #ifdef TIMEZONE_HOOK
383 TIMEZONE_HOOK
384 /* Which do you like better, `TIMEZONE_HOOK' or `TIMEZONE_HOOK;' ? */
385 #endif
386
387 #if defined(HAVE_TZSET) && defined(_MINIX)
388 extern long     timezone;               /* not defined in time.h */
389 #endif
390
391 /* ------------------------------------------------------------------------ */
392 #if defined(HAVE_FTIME) || defined(HAVE_GETTIMEOFDAY) || defined(HAVE_TZSET)
393 static long
394 gettz()
395 #ifdef HAVE_TZSET
396 {
397         tzset();
398         return timezone;
399 }
400 #endif
401
402 /* ------------------------------------------------------------------------ */
403 #if !defined(HAVE_TZSET) && defined(HAVE_FTIME)
404 {
405         struct timeb    buf;
406
407         ftime(&buf);
408         return buf.timezone * 60L;
409 }
410 #endif
411
412 /* ------------------------------------------------------------------------ */
413 #if !defined(HAVE_TZSET) && !defined(HAVE_FTIME)        /* maybe defined(HAVE_GETTIMEOFDAY) */
414 {
415 #ifdef HAVE_STRUCT_TM_TM_GMTOFF
416         time_t tt;
417
418         time(&tt);
419         return -localtime(&tt)->tm_gmtoff;
420 #else /* HAVE_STRUCT_TM_TM_GMTOFF */
421         struct timeval  tp;
422         struct timezone tzp;
423         gettimeofday(&tp, &tzp);/* specific to 4.3BSD */
424         /*
425          * return (tzp.tz_minuteswest * 60L + (tzp.tz_dsttime != 0 ? 60L *
426          * 60L : 0));
427          */
428         return (tzp.tz_minuteswest * 60L);
429 #endif /* HAVE_STRUCT_TM_TM_GMTOFF */
430 }
431 #endif
432 #endif                          /* defined(HAVE_FTIME) || defined(HAVE_GETTIMEOFDAY) ||
433                      * defined(HAVE_TZSET) */
434
435 /* ------------------------------------------------------------------------ */
436 #ifdef NOT_USED
437 static struct tm *
438 msdos_to_unix_stamp_tm(a)
439         long            a;
440 {
441         static struct tm t;
442
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;
449         return &t;
450 }
451 #endif
452
453 /* ------------------------------------------------------------------------ */
454 static          time_t
455 generic_to_unix_stamp(t)
456         long            t;
457 #if defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL)
458 {
459         struct tm       dostm;
460
461         /*
462          * special case:  if MSDOS format date and time were zero, then we
463          * set time to be zero here too.
464          */
465         if (t == 0)
466                 return (time_t) 0;
467
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;
474 #if 0
475         dostm.tm_isdst = 0;     /* correct? */
476 #endif
477         dostm.tm_isdst = -1;    /* correct? */
478 #ifdef HAVE_MKTIME
479         return (time_t) mktime(&dostm);
480 #else                           /* maybe defined(HAVE_TIMELOCAL) */
481         return (time_t) timelocal(&dostm);
482 #endif
483 }
484
485 #else                           /* defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL) */
486 {
487         int             year, month, day, hour, min, sec;
488         long            longtime;
489         static unsigned int dsboy[12] = {0, 31, 59, 90, 120, 151,
490         181, 212, 243, 273, 304, 334};
491         unsigned int    days;
492
493         /*
494          * special case:  if MSDOS format date and time were zero, then we
495          * set time to be zero here too.
496          */
497         if (t == 0)
498                 return (time_t) 0;
499
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 */
503
504         hour = ((int) t >> 11) & 0x1f;
505         min = ((int) t >> 5) & 0x3f;
506         sec = ((int) t & 0x1f) * 2;
507
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 */
513
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 */
518
519         /* Knowing the days, we can find seconds */
520         longtime = (((days * 24) + hour) * 60 + min) * 60 + sec;
521         longtime += gettz();    /* adjust for timezone */
522
523         /* LONGTIME is now the time in seconds, since 1970/01/01 00:00:00.  */
524         return (time_t) longtime;
525 }
526 #endif                          /* defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL) */
527
528 /* ------------------------------------------------------------------------ */
529 static long
530 unix_to_generic_stamp(t)
531         time_t          t;
532 {
533         struct tm      *tm = localtime(&t);
534
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) +
539                         (tm->tm_min << 5) +
540                         (tm->tm_sec / 2)));
541 }
542
543 /* ------------------------------------------------------------------------ */
544 /* build header functions                                                                                                       */
545 /* ------------------------------------------------------------------------ */
546 boolean
547 get_header(fp, hdr)
548         FILE           *fp;
549         register LzHeader *hdr;
550 {
551         int             header_size;
552         int             name_length;
553         char            data[LZHEADER_STRAGE];
554         char            dirname[FILENAME_LENGTH];
555         int             dir_length = 0;
556         int             checksum;
557         int             i;
558         char           *ptr;
559         int                             extend_size;
560         int                             dmy;
561
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
565                                        broken archive. */
566     char *system_delim = "//";
567     int filename_case = NONE;
568
569         memset(hdr, 0, sizeof(LzHeader));
570
571         if (((header_size = getc(fp)) == EOF) || (header_size == 0)) {
572                 return FALSE;   /* finish */
573         }
574
575         if (fread(data + 1, I_NAME_LENGTH - 1, 1, fp) == 0) {
576                 fatal_error("Invalid header (LHarc file ?)");
577                 return FALSE;   /* finish */
578         }
579         setup_get(data + I_HEADER_LEVEL);
580         hdr->header_level = get_byte();
581
582         if (hdr->header_level >= 3) {
583                 error("Unknown level header (level %d)", hdr->header_level);
584                 return FALSE;
585         }
586
587         setup_get(data + I_HEADER_CHECKSUM);
588         checksum = get_byte();
589
590         if (hdr->header_level == 2) {
591                 hdr->header_size = header_size += checksum*256;
592         } else {
593                 hdr->header_size = header_size;
594         }
595
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 */
599     }
600
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 */
605         }
606
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();
613
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';
621         }
622         else {
623                 hdr->unix_last_modified_stamp = hdr->last_modified_stamp;
624                 name_length = 0;
625         }
626
627         /* defaults for other type */
628         hdr->unix_mode = UNIX_FILE_REGULAR | UNIX_RW_RW_RW;
629         hdr->unix_gid = 0;
630         hdr->unix_uid = 0;
631
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;
638                         } else {
639                                 error("Unkonwn header (lha file?)");
640                 exit(1);
641                         }
642                 } else {
643                         hdr->has_crc = TRUE;
644                         hdr->crc = get_word();
645                 }
646
647                 if (extend_size >= 1) {
648                         hdr->extend_type = get_byte();
649                         extend_size--;
650                 }
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();
658                                 extend_size -= 11;
659                         } else {
660                                 hdr->extend_type = EXTEND_GENERIC;
661                         }
662                 }
663                 while (extend_size-- > 0)
664                         dmy = get_byte();
665         } else if (hdr->header_level == 1) {
666                 hdr->has_crc = TRUE;
667                 extend_size = header_size - name_length-25;
668                 hdr->crc = get_word();
669                 hdr->extend_type = get_byte();
670                 while (extend_size-- > 0)
671                         dmy = get_byte();
672         } else { /* level 2 */
673                 hdr->has_crc = TRUE;
674                 hdr->crc = get_word();
675                 hdr->extend_type = get_byte();
676         }               
677
678         if (hdr->header_level > 0) {
679                 /* Extend Header */
680                 if (hdr->header_level != 2)
681                         setup_get(data + hdr->header_size);
682                 ptr = get_ptr;
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 ?)");
688                                 return FALSE;
689                         }
690                         switch (get_byte()) {
691                         case 0:
692                                 /*
693                                  * header crc
694                                  */
695                                 setup_get(get_ptr + header_size - 3);
696                                 break;
697                         case 1:
698                                 /*
699                                  * filename
700                                  */
701                                 for (i = 0; i < header_size-3 && i < sizeof(hdr->name)-1; i++)
702                                         hdr->name[i] = (char) get_byte();
703                                 hdr->name[i] = '\0';
704                                 name_length = i;
705                 for (; i < header_size-3; i++)
706                     get_byte();
707                                 break;
708                         case 2:
709                                 /*
710                                  * directory
711                                  */
712                                 for (i = 0; i < header_size-3 && i < sizeof(dirname)-1; i++)
713                                         dirname[i] = (char) get_byte();
714                                 dirname[i] = '\0';
715                                 dir_length = i;
716                 for (; i < header_size-3; i++)
717                     get_byte();
718                                 break;
719                         case 0x40:
720                                 /*
721                                  * MS-DOS attribute
722                                  */
723                                 if (hdr->extend_type == EXTEND_MSDOS ||
724                                     hdr->extend_type == EXTEND_HUMAN ||
725                                     hdr->extend_type == EXTEND_GENERIC)
726                                         hdr->attribute = get_word();
727                                 break;
728                         case 0x50:
729                                 /*
730                                  * UNIX permission
731                                  */
732                                 if (hdr->extend_type == EXTEND_UNIX)
733                                         hdr->unix_mode = get_word();
734                                 break;
735                         case 0x51:
736                                 /*
737                                  * UNIX gid and uid
738                                  */
739                                 if (hdr->extend_type == EXTEND_UNIX) {
740                                         hdr->unix_gid = get_word();
741                                         hdr->unix_uid = get_word();
742                                 }
743                                 break;
744                         case 0x52:
745                                 /*
746                                  * UNIX group name
747                                  */
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++)
752                     get_byte();
753                                 break;
754                         case 0x53:
755                                 /*
756                                  * UNIX user name
757                                  */
758                 for (i = 0; i < header_size-3 && i < sizeof(hdr->user)-1; i++)
759                     hdr->user[i] = get_byte();
760                 hdr->user[i] = '\0';
761                 for (; i < header_size-3; i++)
762                     get_byte();
763                                 break;
764                         case 0x54:
765                                 /*
766                                  * UNIX last modified time
767                                  */
768                                 if (hdr->extend_type == EXTEND_UNIX)
769                                         hdr->unix_last_modified_stamp = (time_t) get_longword();
770                                 break;
771                         default:
772                                 /*
773                                  * other headers
774                                  */
775                                 setup_get(get_ptr + header_size - 3);
776                                 break;
777                         }
778                 }
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;
782                 }
783         }
784
785         switch (hdr->extend_type) {
786         case EXTEND_MSDOS:
787         filename_case = noconvertcase ? NONE : TO_LOWER;
788
789         /* fall through */
790         case EXTEND_HUMAN:
791                 if (hdr->header_level == 2)
792                         hdr->unix_last_modified_stamp = hdr->last_modified_stamp;
793                 else
794                         hdr->unix_last_modified_stamp =
795                                 generic_to_unix_stamp(hdr->last_modified_stamp);
796                 break;
797
798 #ifdef OSK
799         case EXTEND_OS68K:
800         case EXTEND_XOSK:
801 #endif
802         case EXTEND_UNIX:
803         filename_case = NONE;
804
805                 break;
806
807         case EXTEND_MACOS:
808         archive_delim = "\377/:\\";
809                           /* `\' is for level 0 header and broken archive. */
810         system_delim = "/://";
811         filename_case = NONE;
812
813                 hdr->unix_last_modified_stamp =
814                         generic_to_unix_stamp(hdr->last_modified_stamp, sizeof(hdr->name));
815                 break;
816
817         default:
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. */
822
823                 if (hdr->header_level == 2)
824                         hdr->unix_last_modified_stamp = hdr->last_modified_stamp;
825                 else
826                         hdr->unix_last_modified_stamp =
827                                 generic_to_unix_stamp(hdr->last_modified_stamp);
828         }
829
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;
841
842         if (dir_length) {
843                 strcat(dirname, hdr->name);
844                 strcpy(hdr->name, dirname);
845                 name_length += dir_length;
846         }
847
848     convert_filename(hdr->name, name_length, sizeof(hdr->name),
849                      archive_kanji_code,
850                      system_kanji_code,
851                      archive_delim, system_delim, filename_case);
852
853         return TRUE;
854 }
855
856 /* ------------------------------------------------------------------------ */
857 void
858 init_header(name, v_stat, hdr)
859         char           *name;
860         struct stat    *v_stat;
861         LzHeader       *hdr;
862 {
863         int             len;
864
865     memset(hdr, 0, sizeof(LzHeader));
866
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);
871         else
872                 memcpy(hdr->method, LZHUFF0_METHOD, METHOD_TYPE_STRAGE);
873
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);
880         len = strlen(name);
881         hdr->crc = 0x0000;
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. */
887 #else
888         hdr->unix_mode = v_stat->st_mode;
889 #endif
890
891         hdr->unix_uid = v_stat->st_uid;
892         hdr->unix_gid = v_stat->st_gid;
893
894 #if INCLUDE_OWNER_NAME_IN_HEADER
895 #if HAVE_GETPWUID
896     {
897         struct passwd *ent = getpwuid(hdr->unix_uid);
898
899         if (ent) {
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;
903         }
904     }
905 #endif
906 #if HAVE_GETGRGID
907     {
908         struct group *ent = getgrgid(hdr->unix_gid);
909
910         if (ent) {
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;
914         }
915     }
916 #endif
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++], "/");
924         }
925
926 #ifdef S_IFLNK  
927         if (is_symlink(v_stat)) {
928                 char    lkname[FILENAME_LENGTH];
929                 int             len;    
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);
937         }
938 #endif
939 }
940
941 /* ------------------------------------------------------------------------ */
942 /* Write unix extended header or generic header. */
943 void
944 write_header(nafp, hdr)
945         FILE           *nafp;
946         LzHeader       *hdr;
947 {
948         int             header_size;
949         int             name_length;
950         char            data[LZHEADER_STRAGE];
951         char           *p;
952         char           *headercrc_ptr;
953
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];
960
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;
965
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);
971
972         if (hdr->header_level == HEADER_LEVEL2)
973                 put_longword((long) hdr->unix_last_modified_stamp);
974         else
975                 put_longword(hdr->last_modified_stamp);
976
977         switch (hdr->header_level) {
978         case HEADER_LEVEL0:
979                 put_byte(hdr->attribute);
980                 break;
981         case HEADER_LEVEL1:
982         case HEADER_LEVEL2:
983                 put_byte(0x20);
984                 break;
985         }
986
987         put_byte(hdr->header_level);
988
989     if (generic_format)
990         filename_case = TO_UPPER;
991
992         if (hdr->header_level == HEADER_LEVEL0) {
993         archive_delim = "\\";
994     }
995
996     strncpy(lzname, hdr->name, sizeof(lzname));
997     convert_filename(lzname, strlen(lzname), sizeof(lzname),
998                      system_kanji_code,
999                      archive_kanji_code,
1000                      system_delim, archive_delim, filename_case);
1001
1002         if (hdr->header_level != HEADER_LEVEL2) {
1003         int limit;
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)
1008             p = lzname;
1009         else
1010             ++p;
1011         name_length = strlen(p);
1012
1013         limit = 255 - I_UNIX_EXTEND_BOTTOM + 2;
1014         if (header_level == 0) {
1015             if (generic_format)
1016                 limit = 255 - I_GENERIC_HEADER_BOTTOM + 2;
1017
1018             if (name_length > limit) {
1019                 warning("the length of pathname \"%s\" is too long.", p);
1020                 name_length = limit;
1021             }
1022         }
1023
1024         if (header_level == 1) {
1025             put_byte(0);
1026         }
1027         else {
1028             put_byte(name_length);
1029             memcpy(data + I_NAME, p, name_length);
1030             setup_put(data + I_NAME + name_length);
1031         }
1032         }
1033
1034         put_word(hdr->crc);
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);
1040                 } else {
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);
1051                 }
1052         } else {
1053                 /* write extend header. */
1054                 char           *ptr;
1055
1056                 if (generic_format)
1057                         put_byte(0x00);
1058                 else
1059                         put_byte(EXTEND_UNIX);
1060
1061                 ptr = put_ptr;
1062                 if (hdr->header_level == HEADER_LEVEL2) {
1063                         /* write common header */
1064                         put_word(5);
1065                         put_byte(0x00);
1066                         headercrc_ptr = put_ptr;
1067                         put_word(0x0000);
1068                 }
1069
1070                 if (generic_format) {
1071                         header_size = put_ptr - data;   /* +2 for last 0x0000 */
1072                 } else {
1073                         put_word(5);
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);
1078                         put_word(7);
1079                         put_byte(0x51); /* gid and uid */
1080                         put_word(hdr->unix_gid);
1081                         put_word(hdr->unix_uid);
1082
1083             {
1084                 int i, len = strlen(hdr->group);
1085                 if (len > 0) {
1086                     put_word(len + 3);
1087                     put_byte(0x52);     /* group name */
1088                     for (i = 0; i < len; i++)
1089                         put_byte(hdr->group[i]);
1090                 }
1091
1092                 len = strlen(hdr->user);
1093                 if (len > 0) {
1094                     put_word(len + 3);
1095                     put_byte(0x53);     /* user name */
1096                     for (i = 0; i < len; i++)
1097                         put_byte(hdr->user[i]);
1098                 }
1099             }
1100
1101             if (hdr->header_level == 1) {
1102                 int i;
1103                 if (p = strrchr(lzname, LHA_PATHSEP))
1104                     name_length = strlen(++p);
1105                 else {
1106                     p = lzname;
1107                     name_length = strlen(lzname);
1108                 }
1109                 put_word(name_length + 3);
1110                 put_byte(1);    /* filename */
1111                 for (i = 0; i < name_length; i++)
1112                     put_byte(*p++);
1113             }
1114
1115                         if (p = strrchr(lzname, LHA_PATHSEP)) {
1116                                 int             i;
1117
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]);
1123                         }
1124                 }               /* if generic .. */
1125
1126                 if (header_level != HEADER_LEVEL2) {
1127                         if (!generic_format) {
1128                                 put_word(7);
1129                                 put_byte(0x54); /* time stamp */
1130                                 put_longword(hdr->unix_last_modified_stamp);
1131                         }
1132                         hdr->packed_size += put_ptr - ptr;
1133                         ptr = put_ptr;
1134                         setup_put(data + I_PACKED_SIZE);
1135                         put_longword(hdr->packed_size);
1136                         put_ptr = ptr;
1137                         data[I_HEADER_SIZE] = header_size;
1138                         data[I_HEADER_CHECKSUM] = calc_sum(data + I_METHOD, header_size);
1139                 } else {                /* header level 2 */
1140                         int             i;
1141                         if (p = strrchr(lzname, LHA_PATHSEP))
1142                                 name_length = strlen(++p);
1143                         else {
1144                                 p = lzname;
1145                                 name_length = strlen(lzname);
1146                         }
1147                         put_word(name_length + 3);
1148                         put_byte(1);    /* filename */
1149                         for (i = 0; i < name_length; i++)
1150                                 put_byte(*p++);
1151                 }               /* if he.. != HEAD_LV2 */
1152                 header_size = put_ptr - data;
1153         }
1154
1155         if (header_level == HEADER_LEVEL2) {
1156                 unsigned short  hcrc;
1157                 setup_put(data + I_HEADER_SIZE);
1158                 put_word(header_size + 2);
1159                 /* common header */
1160                 hcrc = calc_header_crc(data, (unsigned int) header_size + 2);
1161                 setup_put(headercrc_ptr);
1162                 put_word(hcrc);
1163         }
1164
1165         if (fwrite(data, header_size + 2, 1, nafp) == 0)
1166                 fatal_error("Cannot write to temporary file");
1167 }
1168
1169 #if MULTIBYTE_FILENAME
1170
1171 #if defined(__APPLE__)
1172
1173 #include <CoreFoundation/CFString.h>
1174 #include <CoreFoundation/CFStringEncodingExt.h>
1175
1176 /* this is not need for Mac OS X v 10.2 later */
1177 enum {
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),
1189 };
1190
1191 static int
1192 ConvertEncodingToUTF8(const char* inCStr,
1193                       char* outUTF8Buffer,
1194                       int outUTF8BufferLength,
1195                       unsigned long scriptEncoding,
1196                       unsigned long flags)
1197 {
1198     unsigned long unicodeChars;
1199     unsigned long srcCharsUsed;
1200     unsigned long usedByteLen = 0;
1201     UniChar uniStr[512];
1202     unsigned long cfResult;
1203
1204     cfResult = CFStringEncodingBytesToUnicode(scriptEncoding,
1205                                               flags,
1206                                               (char *)inCStr,
1207                                               strlen(inCStr),
1208                                               &srcCharsUsed,
1209                                               uniStr,
1210                                               512,
1211                                               &unicodeChars);
1212     if (cfResult == 0) {
1213         cfResult = CFStringEncodingUnicodeToBytes(kCFStringEncodingUTF8,
1214                                                   flags,
1215                                                   uniStr,
1216                                                   unicodeChars,
1217                                                   &srcCharsUsed,
1218                                                   (char*)outUTF8Buffer,
1219                                                   outUTF8BufferLength - 1,
1220                                                   &usedByteLen);
1221         outUTF8Buffer[usedByteLen] = '\0';
1222     }
1223
1224     return cfResult;
1225 }
1226
1227 static int
1228 ConvertUTF8ToEncoding(const char* inUTF8Buf,
1229                       int inUTF8BufLength,
1230                       char* outCStrBuffer,
1231                       int outCStrBufferLength,
1232                       unsigned long scriptEncoding,
1233                       unsigned long flags)
1234 {
1235     unsigned long unicodeChars;
1236     unsigned long srcCharsUsed;
1237     unsigned long usedByteLen = 0;
1238     UniChar uniStr[256];
1239     unsigned long cfResult;
1240
1241     cfResult = CFStringEncodingBytesToUnicode(kCFStringEncodingUTF8,
1242                                               flags,
1243                                               (char*)inUTF8Buf,
1244                                               inUTF8BufLength,
1245                                               &srcCharsUsed,
1246                                               uniStr,
1247                                               255,
1248                                               &unicodeChars);
1249     if (cfResult == 0) {
1250         cfResult = CFStringEncodingUnicodeToBytes(scriptEncoding,
1251                                                   flags,
1252                                                   uniStr,
1253                                                   unicodeChars,
1254                                                   &srcCharsUsed,
1255                                                   (char*)outCStrBuffer,
1256                                                   outCStrBufferLength - 1,
1257                                                   &usedByteLen);
1258         outCStrBuffer[usedByteLen] = '\0';
1259     }
1260
1261     return cfResult;
1262 }
1263
1264 #elif HAVE_ICONV
1265 #include <iconv.h>
1266
1267 static int
1268 ConvertEncodingByIconv(const char *src, char *dst, int dstsize,
1269                        const char *srcEnc, const char *dstEnc)
1270 {
1271     iconv_t ic;
1272     static char szTmpBuf[2048];
1273     char *src_p;
1274     char *dst_p;
1275     size_t sLen;
1276     size_t iLen;
1277
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);
1284
1285     ic = iconv_open(dstEnc, srcEnc);
1286     if (ic == (iconv_t)-1) {
1287         error("iconv_open() failure");
1288         return -1;
1289     }
1290
1291     if (iconv(ic, &src_p, &sLen, &dst_p, &iLen) == (size_t)-1) {
1292         error("iconv() failure");
1293         iconv_close(ic);
1294         return -1;
1295     }
1296
1297     strncpy(dst, szTmpBuf, dstsize);
1298
1299     iconv_close(ic);
1300
1301     return 0;
1302 }
1303 #endif /* defined(__APPLE__) */
1304
1305 char *
1306 sjis_to_utf8(char *dst, const char *src, size_t dstsize)
1307 {
1308 #if defined(__APPLE__)
1309   dst[0] = '\0';
1310   if (ConvertEncodingToUTF8(src, dst, dstsize,
1311                             kCFStringEncodingDOSJapanese,
1312                             kCFStringEncodingUseHFSPlusCanonical) == 0)
1313       return dst;
1314 #elif HAVE_ICONV
1315   if (ConvertEncodingByIconv(src, dst, dstsize, "SJIS", "UTF-8") != -1)
1316       return dst;
1317 #else
1318   error("not support utf-8 conversion");
1319 #endif
1320
1321   /* not supported */
1322   if (dstsize < 1) return dst;
1323   dst[dstsize-1] = 0;
1324   return strncpy(dst, src, dstsize-1);
1325 }
1326
1327 char *
1328 utf8_to_sjis(char *dst, const char *src, size_t dstsize)
1329 {
1330 #if defined(__APPLE__)
1331   int srclen;
1332
1333   dst[0] = '\0';
1334   srclen = strlen(src);
1335   if (ConvertUTF8ToEncoding(src, srclen, dst, dstsize,
1336                             kCFStringEncodingDOSJapanese,
1337                             kCFStringEncodingUseHFSPlusCanonical) == 0)
1338       return dst;
1339 #elif HAVE_ICONV
1340   if (ConvertEncodingByIconv(src, dst, dstsize, "UTF-8", "SJIS") != -1)
1341       return dst;
1342 #else
1343   error("not support utf-8 conversion");
1344 #endif
1345
1346   /* not supported */
1347   if (dstsize < 1) return dst;
1348   dst[dstsize-1] = 0;
1349   return strncpy(dst, src, dstsize-1);
1350 }
1351
1352 /*
1353  * SJIS <-> EUC ÊÑ´¹´Ø¿ô
1354  * ¡ÖÆüËܸì¾ðÊó½èÍý¡×   ¥½¥Õ¥È¥Ð¥ó¥¯(³ô)
1355  *      ¤è¤êÈ´¿è(by Koji Arai)
1356  */
1357 void
1358 euc2sjis(int *p1, int *p2)
1359 {
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;
1366 }
1367
1368 void
1369 sjis2euc(int *p1, int *p2)
1370 {
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;
1377     *p2 -= celoff;
1378
1379     *p1 |= 0x80;
1380     *p2 |= 0x80;
1381 }
1382 #endif /* MULTIBYTE_FILENAME */
1383
1384 /* Local Variables: */
1385 /* mode:c */
1386 /* tab-width:4 */
1387 /* compile-command:"gcc -c header.c" */
1388 /* End: */
1389 /* vi: set tabstop=4: */