OSDN Git Service

9f4d95c2b324d606c82fd61de150af33e274df3e
[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.14e bug fixed                                                1999.05.27  T.Okamoto       */
13 /* ------------------------------------------------------------------------ */
14 #include "lha.h"
15
16 /* ------------------------------------------------------------------------ */
17 static char    *get_ptr;
18 /* ------------------------------------------------------------------------ */
19 int
20 calc_sum(p, len)
21         register char  *p;
22         register int    len;
23 {
24         register int    sum;
25
26         for (sum = 0; len; len--)
27                 sum += *p++;
28
29         return sum & 0xff;
30 }
31
32 /* ------------------------------------------------------------------------ */
33 static unsigned short
34 get_word()
35 {
36         int             b0, b1;
37
38         b0 = get_byte();
39         b1 = get_byte();
40         return (b1 << 8) + b0;
41 }
42
43 /* ------------------------------------------------------------------------ */
44 static void
45 put_word(v)
46         unsigned int    v;
47 {
48         put_byte(v);
49         put_byte(v >> 8);
50 }
51
52 /* ------------------------------------------------------------------------ */
53 static long
54 get_longword()
55 {
56         long            b0, b1, b2, b3;
57
58         b0 = get_byte();
59         b1 = get_byte();
60         b2 = get_byte();
61         b3 = get_byte();
62         return (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
63 }
64
65 /* ------------------------------------------------------------------------ */
66 static void
67 put_longword(v)
68         long            v;
69 {
70         put_byte(v);
71         put_byte(v >> 8);
72         put_byte(v >> 16);
73         put_byte(v >> 24);
74 }
75
76 /* ------------------------------------------------------------------------ */
77 static void
78 msdos_to_unix_filename(name, len)
79         register char  *name;
80         register int    len;
81 {
82         register int    i;
83
84 #define X0201_KANA_P(c)\
85         (0xa0 < (unsigned char)(c) && (unsigned char)(c) < 0xe0)
86
87 #ifdef MULTIBYTE_CHAR
88 #ifdef SUPPORT_X0201
89         for (i = 0; i < len; i++) {
90                 /* modified by Koji Arai */
91                 if (X0201_KANA_P(name[i])) {
92                         int j;
93                         for (j = len; j >= i; j--) {
94                                 name[j+1] = name[j]; /* no check over */
95                         }
96                         name[i] = 0x8e;
97                         i++;
98                         len++;
99                 } else
100                 if (MULTIBYTE_FIRST_P(name[i]) &&
101                     MULTIBYTE_SECOND_P(name[i + 1])) {
102                         int c1, c2;
103                         c1 = name[i]; c2 = name[i+1];
104                         sjis2euc(&c1, &c2);
105                         name[i] = c1; name[i+1] = c2;
106                         i++;
107                 }
108                 else if (name[i] == '\\')
109                         name[i] = '/';
110                 else if (isupper(name[i]))
111                         name[i] = tolower(name[i]);
112         }
113 #else
114         for (i = 0; i < len; i++) {
115                 if (MULTIBYTE_FIRST_P(name[i]) &&
116                     MULTIBYTE_SECOND_P(name[i + 1]))
117                         i++;
118                 else if (name[i] == '\\')
119                         name[i] = '/';
120                 else if (isupper(name[i]))
121                         name[i] = tolower(name[i]);
122         }
123 #endif /* SUPPORT_X0201 */
124 #else
125         for (i = 0; i < len; i++) {
126                 if (name[i] == '\\')
127                         name[i] = '/';
128                 else if (isupper(name[i]))
129                         name[i] = tolower(name[i]);
130         }
131 #endif
132 }
133
134 /* ------------------------------------------------------------------------ */
135 static void
136 generic_to_unix_filename(name, len)
137         register char  *name;
138         register int    len;
139 {
140         register int    i;
141         boolean         lower_case_used = FALSE;
142
143 #ifdef MULTIBYTE_CHAR
144 #ifdef SUPPORT_X0201
145         for (i = 0; i < len; i++) {
146                 /* modified by Koji Arai */
147                 if (X0201_KANA_P(name[i])) {
148                         int j;
149                         for (j = len; j >= i; j--) {
150                                 name[j+1] = name[j]; /* no check over */
151                         }
152                         name[i] = 0x8e;
153                         i++;
154                         len++;
155                 } else
156
157                 if (MULTIBYTE_FIRST_P(name[i]) &&
158                     MULTIBYTE_SECOND_P(name[i + 1]))
159                         i++;
160                 else if (islower(name[i])) {
161                         lower_case_used = TRUE;
162                         break;
163                 }
164         }
165 #else
166         for (i = 0; i < len; i++) {
167                 if (MULTIBYTE_FIRST_P(name[i]) &&
168                     MULTIBYTE_SECOND_P(name[i + 1]))
169                         i++;
170                 else if (islower(name[i])) {
171                         lower_case_used = TRUE;
172                         break;
173                 }
174         }
175 #endif /* SUPPORT_X0201 */
176         for (i = 0; i < len; i++) {
177                 if (MULTIBYTE_FIRST_P(name[i]) &&
178                     MULTIBYTE_SECOND_P(name[i + 1]))
179                         i++;
180                 else if (name[i] == '\\')
181                         name[i] = '/';
182                 else if (!lower_case_used && isupper(name[i]))
183                         name[i] = tolower(name[i]);
184         }
185 #else
186         for (i = 0; i < len; i++)
187                 if (islower(name[i])) {
188                         lower_case_used = TRUE;
189                         break;
190                 }
191         for (i = 0; i < len; i++) {
192                 if (name[i] == '\\')
193                         name[i] = '/';
194                 else if (!lower_case_used && isupper(name[i]))
195                         name[i] = tolower(name[i]);
196         }
197 #endif
198 }
199
200 /* ------------------------------------------------------------------------ */
201 static void
202 macos_to_unix_filename(name, len)
203         register char  *name;
204         register int    len;
205 {
206         register int    i;
207
208 /* modified by Koji Arai */
209 #ifdef SUPPORT_X0201
210         for (i = 0; i < len; i ++) {
211                 /* modified by Koji Arai */
212                 if (X0201_KANA_P(name[i])) {
213                         int j;
214                         for (j = len; j >= i; j--) {
215                                 name[j+1] = name[j]; /* no check over */
216                         }
217                         name[i] = 0x8e;
218                         i++;
219                         len++;
220                 } else
221
222                 if (MULTIBYTE_FIRST_P (name[i]) &&
223                         MULTIBYTE_SECOND_P (name[i+1])) {
224                         int c1, c2;
225                         c1 = name[i]; c2 = name[i+1];
226                         sjis2euc(&c1, &c2);
227                         name[i] = c1; name[i+1] = c2;
228                         i ++;
229                 }
230                 else if (name[i] == ':')
231                         name[i] = '/';
232                 else if (name[i] == '/')
233                         name[i] = ':';
234 /*
235                 else if (isupper (name[i]))
236                         name[i] = tolower (name[i]);
237 */
238         }
239 #else
240         for (i = 0; i < len; i++) {
241                 if (name[i] == ':')
242                         name[i] = '/';
243                 else if (name[i] == '/')
244                         name[i] = ':';
245         }
246 #endif /* SUPPORT_X0201 */
247 }
248
249 /* ------------------------------------------------------------------------ */
250 static void
251 unix_to_generic_filename(name, len)
252         register char  *name;
253         register int    len;
254 {
255         register int    i;
256
257         for (i = 0; i < len; i++) {
258                 if (name[i] == '/')
259                         name[i] = '\\';
260                 else if (islower(name[i]))
261                         name[i] = toupper(name[i]);
262         }
263 }
264
265 /* ------------------------------------------------------------------------ */
266 /*                                                                                                                                                      */
267 /* Generic stamp format:                                                                                                        */
268 /*                                                                                                                                                      */
269 /* 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16                                                      */
270 /* |<-------- year ------->|<- month ->|<-- day -->|                                            */
271 /*                                                                                                                                                      */
272 /* 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0                                                      */
273 /* |<--- hour --->|<---- minute --->|<- second*2 ->|                                            */
274 /*                                                                                                                                                      */
275 /* ------------------------------------------------------------------------ */
276
277 /*
278  * NOTE : If you don't have `gettimeofday(2)', or your gettimeofday(2)
279  * returns bogus timezone information, try FTIME, MKTIME, TIMELOCAL or TZSET.
280  */
281
282 /* choose one */
283 #if defined(HAVE_MKTIME)
284 #ifdef HAVE_TIMELOCAL
285 #undef HAVE_TIMELOCAL
286 #endif
287 #endif                          /* defined(HAVE_MKTIME) */
288
289 #if defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL)
290 #ifdef HAVE_TZSET
291 #undef HAVE_TZSET
292 #endif
293 #endif                          /* defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL) */
294
295 #if defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL) || defined(HAVE_TZSET)
296 #ifdef HAVE_FTIME
297 #undef HAVE_FTIME
298 #endif
299 #endif
300
301 #if defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL) || defined(HAVE_TZSET) || defined(HAVE_FTIME)
302 #ifdef HAVE_GETTIMEOFDAY
303 #undef HAVE_GETTIMEOFDAY
304 #endif
305 #else
306 #ifndef HAVE_GETTIMEOFDAY
307 #define HAVE_GETTIMEOFDAY               /* use gettimeofday() */
308 #endif
309 #endif
310
311 #ifdef HAVE_FTIME
312 #include <sys/timeb.h>
313 #endif
314
315 /*
316  * You may define as : #define TIMEZONE_HOOK            \ extern long
317  * timezone ;   \ extern void tzset();
318  */
319 #ifdef TIMEZONE_HOOK
320 TIMEZONE_HOOK
321 /* Which do you like better, `TIMEZONE_HOOK' or `TIMEZONE_HOOK;' ? */
322 #endif
323
324 #if defined(HAVE_TZSET) && defined(_MINIX)
325 extern long     timezone;               /* not defined in time.h */
326 #endif
327
328 /* ------------------------------------------------------------------------ */
329 #if defined(HAVE_FTIME) || defined(HAVE_GETTIMEOFDAY) || defined(HAVE_TZSET)
330 static long
331 gettz()
332 #ifdef HAVE_TZSET
333 {
334         tzset();
335         return timezone;
336 }
337 #endif
338
339 /* ------------------------------------------------------------------------ */
340 #if !defined(HAVE_TZSET) && defined(HAVE_FTIME)
341 {
342         struct timeb    buf;
343
344         ftime(&buf);
345         return buf.timezone * 60L;
346 }
347 #endif
348
349 /* ------------------------------------------------------------------------ */
350 #if !defined(HAVE_TZSET) && !defined(HAVE_FTIME)        /* maybe defined(HAVE_GETTIMEOFDAY) */
351 {
352 #ifdef HAVE_TM_GMTOFF
353         time_t tt;
354
355         time(&tt);
356         return -localtime(&tt)->tm_gmtoff;
357 #else /* HAVE_TM_GMTOFF */
358         struct timeval  tp;
359         struct timezone tzp;
360         gettimeofday(&tp, &tzp);/* specific to 4.3BSD */
361         /*
362          * return (tzp.tz_minuteswest * 60L + (tzp.tz_dsttime != 0 ? 60L *
363          * 60L : 0));
364          */
365         return (tzp.tz_minuteswest * 60L);
366 #endif /* HAVE_TM_GMTOFF */
367 }
368 #endif
369 #endif                          /* defined(HAVE_FTIME) || defined(HAVE_GETTIMEOFDAY) ||
370                                  * defined(HAVE_TZSET) */
371
372 /* ------------------------------------------------------------------------ */
373 #ifdef NOT_USED
374 static struct tm *
375 msdos_to_unix_stamp_tm(a)
376         long            a;
377 {
378         static struct tm t;
379
380         t.tm_sec = (a & 0x1f) * 2;
381         t.tm_min = (a >> 5) & 0x3f;
382         t.tm_hour = (a >> 11) & 0x1f;
383         t.tm_mday = (a >> 16) & 0x1f;
384         t.tm_mon = ((a >> 16 + 5) & 0x0f) - 1;
385         t.tm_year = ((a >> 16 + 9) & 0x7f) + 80;
386         return &t;
387 }
388 #endif
389
390 /* ------------------------------------------------------------------------ */
391 static          time_t
392 generic_to_unix_stamp(t)
393         long            t;
394 #if defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL)
395 {
396         struct tm       dostm;
397
398         /*
399          * special case:  if MSDOS format date and time were zero, then we
400          * set time to be zero here too.
401          */
402         if (t == 0)
403                 return (time_t) 0;
404
405         dostm.tm_sec = (t & 0x1f) * 2;
406         dostm.tm_min = t >> 5 & 0x3f;
407         dostm.tm_hour = t >> 11 & 0x1f;
408         dostm.tm_mday = t >> 16 & 0x1f;
409         dostm.tm_mon = (t >> 16 + 5 & 0x0f) - 1;        /* 0..11 */
410         dostm.tm_year = (t >> 16 + 9 & 0x7f) + 80;
411 #if 0
412         dostm.tm_isdst = 0;     /* correct? */
413 #endif
414         dostm.tm_isdst = -1;    /* correct? */
415 #ifdef HAVE_MKTIME
416         return (time_t) mktime(&dostm);
417 #else                           /* maybe defined(HAVE_TIMELOCAL) */
418         return (time_t) timelocal(&dostm);
419 #endif
420 }
421
422 #else                           /* defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL) */
423 {
424         int             year, month, day, hour, min, sec;
425         long            longtime;
426         static unsigned int dsboy[12] = {0, 31, 59, 90, 120, 151,
427         181, 212, 243, 273, 304, 334};
428         unsigned int    days;
429
430         /*
431          * special case:  if MSDOS format date and time were zero, then we
432          * set time to be zero here too.
433          */
434         if (t == 0)
435                 return (time_t) 0;
436
437         year = ((int) (t >> 16 + 9) & 0x7f) + 1980;
438         month = (int) (t >> 16 + 5) & 0x0f;     /* 1..12 means Jan..Dec */
439         day = (int) (t >> 16) & 0x1f;   /* 1..31 means 1st,...31st */
440
441         hour = ((int) t >> 11) & 0x1f;
442         min = ((int) t >> 5) & 0x3f;
443         sec = ((int) t & 0x1f) * 2;
444
445         /* Calculate days since 1970.01.01 */
446         days = (365 * (year - 1970) +   /* days due to whole years */
447                 (year - 1970 + 1) / 4 + /* days due to leap years */
448                 dsboy[month - 1] +      /* days since beginning of this year */
449                 day - 1);       /* days since beginning of month */
450
451         if ((year % 4 == 0) &&
452                 (year % 100 != 0 || year % 400 == 0) &&         /* 1999.5.24 t.oka */
453             (month >= 3))       /* if this is a leap year and month */
454                 days++;         /* is March or later, add a day */
455
456         /* Knowing the days, we can find seconds */
457         longtime = (((days * 24) + hour) * 60 + min) * 60 + sec;
458         longtime += gettz();    /* adjust for timezone */
459
460         /* LONGTIME is now the time in seconds, since 1970/01/01 00:00:00.  */
461         return (time_t) longtime;
462 }
463 #endif                          /* defined(HAVE_MKTIME) || defined(HAVE_TIMELOCAL) */
464
465 /* ------------------------------------------------------------------------ */
466 static long
467 unix_to_generic_stamp(t)
468         time_t          t;
469 {
470         struct tm      *tm = localtime(&t);
471
472         return ((((long) (tm->tm_year - 80)) << 25) +
473                 (((long) (tm->tm_mon + 1)) << 21) +
474                 (((long) tm->tm_mday) << 16) +
475                 (long) ((tm->tm_hour << 11) +
476                         (tm->tm_min << 5) +
477                         (tm->tm_sec / 2)));
478 }
479
480 /* ------------------------------------------------------------------------ */
481 /* build header functions                                                                                                       */
482 /* ------------------------------------------------------------------------ */
483 boolean
484 get_header(fp, hdr)
485         FILE           *fp;
486         register LzHeader *hdr;
487 {
488         int             header_size;
489         int             name_length;
490         char            data[LZHEADER_STRAGE];
491         char            dirname[FILENAME_LENGTH];
492         int             dir_length = 0;
493         int             checksum;
494         int             i;
495         char           *ptr;
496         int                             extend_size;
497         int                             dmy;
498
499         bzero(hdr, sizeof(LzHeader));
500
501         if (((header_size = getc(fp)) == EOF) || (header_size == 0)) {
502                 return FALSE;   /* finish */
503         }
504
505         if (fread(data + I_HEADER_CHECKSUM,
506                   sizeof(char), header_size - 1, fp) < header_size - 1) {
507                 fatal_error("Invalid header (LHarc file ?)");
508                 return FALSE;   /* finish */
509         }
510         setup_get(data + I_HEADER_LEVEL);
511         hdr->header_level = get_byte();
512         if (hdr->header_level != 2 &&
513             fread(data + header_size, sizeof(char), 2, fp) < 2) {
514                 fatal_error("Invalid header (LHarc file ?)");
515                 return FALSE;   /* finish */
516         }
517
518         if (hdr->header_level >= 3) {
519                 fatal_error("Unknown level header");
520                 return FALSE;
521         }
522
523         setup_get(data + I_HEADER_CHECKSUM);
524         checksum = get_byte();
525
526         hdr->header_size = header_size;
527         bcopy(data + I_METHOD, hdr->method, METHOD_TYPE_STRAGE);
528         setup_get(data + I_PACKED_SIZE);
529         hdr->packed_size = get_longword();
530         hdr->original_size = get_longword();
531         hdr->last_modified_stamp = get_longword();
532         hdr->attribute = get_byte();
533
534         if ((hdr->header_level = get_byte()) != 2) {
535                 if (calc_sum(data + I_METHOD, header_size) != checksum)
536                         warning("Checksum error (LHarc file?)", "");
537                 name_length = get_byte();
538                 for (i = 0; i < name_length; i++)
539                         hdr->name[i] = (char) get_byte();
540                 hdr->name[name_length] = '\0';
541         }
542         else {
543                 hdr->unix_last_modified_stamp = hdr->last_modified_stamp;
544                 name_length = 0;
545         }
546
547         /* defaults for other type */
548         hdr->unix_mode = UNIX_FILE_REGULAR | UNIX_RW_RW_RW;
549         hdr->unix_gid = 0;
550         hdr->unix_uid = 0;
551
552
553         if (hdr->header_level == 0) {
554                 extend_size = header_size - name_length -22;
555                 if (extend_size < 0) {
556                         if (extend_size == -2) {
557                                 hdr->extend_type = EXTEND_GENERIC;
558                                 hdr->has_crc = FALSE;
559                         } else {
560                                 fatal_error("Unkonwn header (lha file?)");
561                                 return FALSE;
562                         }
563                 } else {
564                         hdr->has_crc = TRUE;
565                         hdr->crc = get_word();
566                 }
567
568                 if (extend_size >= 1) {
569                         hdr->extend_type = get_byte();
570                         extend_size--;
571                 }
572                 if (hdr->extend_type == EXTEND_UNIX) {
573                         if (extend_size >= 11) {
574                                 hdr->minor_version = get_byte();
575                                 hdr->unix_last_modified_stamp = (time_t) get_longword();
576                                 hdr->unix_mode = get_word();
577                                 hdr->unix_uid = get_word();
578                                 hdr->unix_gid = get_word();
579                                 extend_size -= 11;
580                         } else {
581                                 hdr->extend_type = EXTEND_GENERIC;
582                         }
583                 }
584                 while (extend_size-- > 0)
585                         dmy = get_byte();
586                 if (hdr->extend_type == EXTEND_UNIX)
587                         return TRUE;
588         } else if (hdr->header_level == 1) {
589                 hdr->has_crc = TRUE;
590                 extend_size = header_size - name_length-25;
591                 hdr->crc = get_word();
592                 hdr->extend_type = get_byte();
593                 while (extend_size-- > 0)
594                         dmy = get_byte();
595         } else { /* level 2 */
596                 hdr->has_crc = TRUE;
597                 hdr->crc = get_word();
598                 hdr->extend_type = get_byte();
599         }               
600
601         if (hdr->header_level > 0) {
602                 /* Extend Header */
603                 if (hdr->header_level != 2)
604                         setup_get(data + hdr->header_size);
605                 ptr = get_ptr;
606                 while ((header_size = get_word()) != 0) {
607                         if (hdr->header_level != 2 &&
608                         ((data + LZHEADER_STRAGE - get_ptr < header_size) ||
609                          fread(get_ptr, sizeof(char), header_size, fp) < header_size)) {
610                                 fatal_error("Invalid header (LHa file ?)");
611                                 return FALSE;
612                         }
613                         switch (get_byte()) {
614                         case 0:
615                                 /*
616                                  * header crc
617                                  */
618                                 setup_get(get_ptr + header_size - 3);
619                                 break;
620                         case 1:
621                                 /*
622                                  * filename
623                                  */
624                                 for (i = 0; i < header_size - 3; i++)
625                                         hdr->name[i] = (char) get_byte();
626                                 hdr->name[header_size - 3] = '\0';
627                                 name_length = header_size - 3; /* modified by Koji Arai */
628                                 break;
629                         case 2:
630                                 /*
631                                  * directory
632                                  */
633                                 for (i = 0; i < header_size - 3; i++)
634                                         dirname[i] = (char) get_byte();
635                                 dirname[header_size - 3] = '\0';
636                                 convdelim(dirname, DELIM);
637                                 dir_length = header_size - 3;
638                                 break;
639                         case 0x40:
640                                 /*
641                                  * MS-DOS attribute
642                                  */
643                                 if (hdr->extend_type == EXTEND_MSDOS ||
644                                     hdr->extend_type == EXTEND_HUMAN ||
645                                     hdr->extend_type == EXTEND_GENERIC)
646                                         hdr->attribute = get_word();
647                                 break;
648                         case 0x50:
649                                 /*
650                                  * UNIX permission
651                                  */
652                                 if (hdr->extend_type == EXTEND_UNIX)
653                                         hdr->unix_mode = get_word();
654                                 break;
655                         case 0x51:
656                                 /*
657                                  * UNIX gid and uid
658                                  */
659                                 if (hdr->extend_type == EXTEND_UNIX) {
660                                         hdr->unix_gid = get_word();
661                                         hdr->unix_uid = get_word();
662                                 }
663                                 break;
664                         case 0x52:
665                                 /*
666                                  * UNIX group name
667                                  */
668                                 setup_get(get_ptr + header_size - 3);
669                                 break;
670                         case 0x53:
671                                 /*
672                                  * UNIX user name
673                                  */
674                                 setup_get(get_ptr + header_size - 3);
675                                 break;
676                         case 0x54:
677                                 /*
678                                  * UNIX last modified time
679                                  */
680                                 if (hdr->extend_type == EXTEND_UNIX)
681                                         hdr->unix_last_modified_stamp = (time_t) get_longword();
682                                 break;
683                         default:
684                                 /*
685                                  * other headers
686                                  */
687                                 setup_get(get_ptr + header_size - 3);
688                                 break;
689                         }
690                 }
691                 if (hdr->header_level != 2 && get_ptr - ptr != 2) {
692                         hdr->packed_size -= get_ptr - ptr - 2;
693                         hdr->header_size += get_ptr - ptr - 2;
694                 }
695         }
696         if (dir_length) {
697                 strcat(dirname, hdr->name);
698                 strcpy(hdr->name, dirname);
699                 name_length += dir_length;
700         }
701
702         switch (hdr->extend_type) {
703         case EXTEND_MSDOS:
704                 msdos_to_unix_filename(hdr->name, name_length);
705         case EXTEND_HUMAN:
706                 if (hdr->header_level == 2)
707                         hdr->unix_last_modified_stamp = hdr->last_modified_stamp;
708                 else
709                         hdr->unix_last_modified_stamp =
710                                 generic_to_unix_stamp(hdr->last_modified_stamp);
711                 break;
712
713 #ifdef OSK
714         case EXTEND_OS68K:
715         case EXTEND_XOSK:
716 #endif
717         case EXTEND_UNIX:
718                 break;
719
720         case EXTEND_MACOS:
721                 macos_to_unix_filename(hdr->name, name_length);
722                 hdr->unix_last_modified_stamp =
723                         generic_to_unix_stamp(hdr->last_modified_stamp);
724                 break;
725
726         default:
727                 generic_to_unix_filename(hdr->name, name_length);
728                 if (hdr->header_level == 2)
729                         hdr->unix_last_modified_stamp = hdr->last_modified_stamp;
730                 else
731                         hdr->unix_last_modified_stamp =
732                                 generic_to_unix_stamp(hdr->last_modified_stamp);
733         }
734
735 #if 0
736         printf("header level=%d\n", hdr->header_level); fflush(stdout);
737 #endif
738
739         return TRUE;
740 }
741
742 /* ------------------------------------------------------------------------ */
743 void
744 init_header(name, v_stat, hdr)
745         char           *name;
746         struct stat    *v_stat;
747         LzHeader       *hdr;
748 {
749         int             len;
750
751         if (compress_method == LZHUFF5_METHOD_NUM)  /* Changed N.Watazaki */
752                 bcopy(LZHUFF5_METHOD, hdr->method, METHOD_TYPE_STRAGE);
753         else if (compress_method)
754                 bcopy(LZHUFF1_METHOD, hdr->method, METHOD_TYPE_STRAGE);
755         else
756                 bcopy(LZHUFF0_METHOD, hdr->method, METHOD_TYPE_STRAGE);
757
758         hdr->packed_size = 0;
759         hdr->original_size = v_stat->st_size;
760         hdr->last_modified_stamp = unix_to_generic_stamp(v_stat->st_mtime);
761         hdr->attribute = GENERIC_ATTRIBUTE;
762         hdr->header_level = header_level;
763         strcpy(hdr->name, name);
764         len = strlen(name);
765         hdr->crc = 0x0000;
766         hdr->extend_type = EXTEND_UNIX;
767         hdr->unix_last_modified_stamp = v_stat->st_mtime;
768         /* since 00:00:00 JAN.1.1970 */
769 #ifdef NOT_COMPATIBLE_MODE
770         /* Please need your modification in this space. */
771 #else
772         hdr->unix_mode = v_stat->st_mode;
773 #endif
774
775         hdr->unix_uid = v_stat->st_uid;
776         hdr->unix_gid = v_stat->st_gid;
777
778         if (is_directory(v_stat)) {
779                 bcopy(LZHDIRS_METHOD, hdr->method, METHOD_TYPE_STRAGE);
780                 hdr->attribute = GENERIC_DIRECTORY_ATTRIBUTE;
781                 hdr->original_size = 0;
782                 if (len > 0 && hdr->name[len - 1] != '/')
783                         strcpy(&hdr->name[len++], "/");
784         }
785
786 #ifdef S_IFLNK  
787         if (is_symlink(v_stat)) {
788                 char    lkname[257];
789                 int             len;    
790                 bcopy(LZHDIRS_METHOD, hdr->method, METHOD_TYPE_STRAGE);
791                 hdr->attribute = GENERIC_DIRECTORY_ATTRIBUTE;
792                 hdr->original_size = 0;
793                 len = readlink(name, lkname, 256);
794                 lkname[len] = (char)'\0';
795                 sprintf(hdr->name, "%s|%s", hdr->name, lkname);
796         }
797 #endif
798         if (generic_format)
799                 unix_to_generic_filename(hdr->name, len);
800 }
801
802 /* ------------------------------------------------------------------------ */
803 /* Write unix extended header or generic header. */
804 void
805 write_header(nafp, hdr)
806         FILE           *nafp;
807         LzHeader       *hdr;
808 {
809         int             header_size;
810         int             name_length;
811         char            data[LZHEADER_STRAGE];
812         char           *p;
813         char           *headercrc_ptr;
814
815         bzero(data, LZHEADER_STRAGE);
816         bcopy(hdr->method, data + I_METHOD, METHOD_TYPE_STRAGE);
817         setup_put(data + I_PACKED_SIZE);
818         put_longword(hdr->packed_size);
819         put_longword(hdr->original_size);
820
821         if (hdr->header_level == HEADER_LEVEL2)
822                 put_longword((long) hdr->unix_last_modified_stamp);
823         else
824                 put_longword(hdr->last_modified_stamp);
825
826         switch (hdr->header_level) {
827         case HEADER_LEVEL0:
828                 put_byte(hdr->attribute);
829                 break;
830         case HEADER_LEVEL1:
831         case HEADER_LEVEL2:
832                 put_byte(0x20);
833                 break;
834         }
835
836         put_byte(hdr->header_level);
837
838         convdelim(hdr->name, DELIM2);
839         if (hdr->header_level != HEADER_LEVEL2) {
840                 if (p = (char *) strrchr(hdr->name, DELIM2))
841                         name_length = strlen(++p);
842                 else
843                         name_length = strlen(hdr->name);
844                 put_byte(name_length);
845                 bcopy(p ? p : hdr->name, data + I_NAME, name_length);
846                 setup_put(data + I_NAME + name_length);
847         }
848
849         put_word(hdr->crc);
850         if (header_level == HEADER_LEVEL0) {
851                 if (generic_format) {
852                         header_size = I_GENERIC_HEADER_BOTTOM - 2 + name_length;
853                         data[I_HEADER_SIZE] = header_size;
854                         data[I_HEADER_CHECKSUM] = calc_sum(data + I_METHOD, header_size);
855                 } else {
856                         /* write old-style extend header */
857                         put_byte(EXTEND_UNIX);
858                         put_byte(CURRENT_UNIX_MINOR_VERSION);
859                         put_longword((long) hdr->unix_last_modified_stamp);
860                         put_word(hdr->unix_mode);
861                         put_word(hdr->unix_uid);
862                         put_word(hdr->unix_gid);
863                         header_size = I_UNIX_EXTEND_BOTTOM - 2 + name_length;
864                         data[I_HEADER_SIZE] = header_size;
865                         data[I_HEADER_CHECKSUM] = calc_sum(data + I_METHOD, header_size);
866                 }
867         } else {
868                 /* write extend header. */
869                 char           *ptr;
870
871                 if (generic_format)
872                         put_byte(0x00);
873                 else
874                         put_byte(EXTEND_UNIX);
875
876                 ptr = put_ptr;
877                 if (hdr->header_level == HEADER_LEVEL2) {
878                         /* write common header */
879                         put_word(5);
880                         put_byte(0x00);
881                         headercrc_ptr = put_ptr;
882                         put_word(0x0000);
883                 }
884
885                 if (generic_format) {
886                         header_size = put_ptr - data;   /* +2 for last 0x0000 */
887                 } else {
888                         put_word(5);
889                         if (hdr->header_level == HEADER_LEVEL1)
890                                 header_size = put_ptr - data - 2;
891                         put_byte(0x50); /* permission */
892                         put_word(hdr->unix_mode);
893                         put_word(7);
894                         put_byte(0x51); /* gid and uid */
895                         put_word(hdr->unix_gid);
896                         put_word(hdr->unix_uid);
897
898                         if (p = (char *) strrchr(hdr->name, DELIM2)) {
899                                 int             i;
900
901                                 name_length = p - hdr->name + 1;
902                                 put_word(name_length + 3);
903                                 put_byte(2);    /* dirname */
904                                 for (i = 0; i < name_length; i++)
905                                         put_byte(hdr->name[i]);
906                         }
907                 }               /* if generic .. */
908
909                 if (header_level != HEADER_LEVEL2) {
910                         if (!generic_format) {
911                                 put_word(7);
912                                 put_byte(0x54); /* time stamp */
913                                 put_longword(hdr->unix_last_modified_stamp);
914                         }
915                         hdr->packed_size += put_ptr - ptr;
916                         ptr = put_ptr;
917                         setup_put(data + I_PACKED_SIZE);
918                         put_longword(hdr->packed_size);
919                         put_ptr = ptr;
920                         data[I_HEADER_SIZE] = header_size;
921                         data[I_HEADER_CHECKSUM] = calc_sum(data + I_METHOD, header_size);
922                 } else {                /* header level 2 */
923                         int             i;
924                         if (p = (char *) strrchr(hdr->name, DELIM2))
925                                 name_length = strlen(++p);
926                         else {
927                                 p = hdr->name;
928                                 name_length = strlen(hdr->name);
929                         }
930                         put_word(name_length + 3);
931                         put_byte(1);    /* filename */
932                         for (i = 0; i < name_length; i++)
933                                 put_byte(*p++);
934                 }               /* if he.. != HEAD_LV2 */
935                 header_size = put_ptr - data;
936         }
937
938         if (header_level == HEADER_LEVEL2) {
939                 unsigned short  hcrc;
940                 setup_put(data + I_HEADER_SIZE);
941                 put_word(header_size + 2);
942                 /* common header */
943                 hcrc = calc_header_crc(data, (unsigned int) header_size + 2);
944                 setup_put(headercrc_ptr);
945                 put_word(hcrc);
946         }
947
948         if (fwrite(data, sizeof(char), header_size + 2, nafp) == 0)
949                 fatal_error("Cannot write to temporary file");
950
951         convdelim(hdr->name, DELIM);
952 }
953
954 #ifdef SUPPORT_X0201
955 /*
956  * SJIS <-> EUC ÊÑ´¹´Ø¿ô
957  * ¡ÖÆüËܸì¾ðÊó½èÍý¡×   ¥½¥Õ¥È¥Ð¥ó¥¯(³ô)
958  *      ¤è¤êÈ´¿è(by Koji Arai)
959  */
960 void
961 euc2sjis(int *p1, int *p2)
962 {
963     unsigned char c1 = *p1 & 0x7f;
964     unsigned char c2 = *p2 & 0x7f;
965     int rowoff = c1 < 0x5f ? 0x70 : 0xb0;
966     int celoff = c1 % 2 ? (c2 > 0x5f ? 0x20 : 0x1f) : 0x7e;
967     *p1 = ((c1 + 1) >> 1) + rowoff;
968     *p2 += celoff - 0x80;
969 }
970
971 void
972 sjis2euc(int *p1, int *p2)
973 {
974     unsigned char c1 = *p1;
975     unsigned char c2 = *p2;
976     int adjust = c2 < 0x9f;
977     int rowoff = c1 < 0xa0 ? 0x70 : 0xb0;
978     int celoff = adjust ? (c2 > 0x7f ? 0x20 : 0x1f) : 0x7e;
979     *p1 = ((c1 - rowoff) << 1) - adjust;
980     *p2 -= celoff;
981
982     *p1 |= 0x80;
983     *p2 |= 0x80;
984 }
985 #endif /* SUPPORT_X0201 */
986
987 /* Local Variables: */
988 /* tab-width : 4 */
989 /* End: */