"SfR Fresh" - the SfR Freeware/Shareware Archive

Member "lha-114i/src/header.c" of archive lha-114i.tar.gz:


As a special service "SfR Fresh" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. That can be also achieved for any archive member file by clicking within an archive contents listing on the first character of the file(path) respectively on the according byte size field.
    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 /* ------------------------------------------------------------------------ */
   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 #ifdef MULTIBYTE_CHAR
   85 	for (i = 0; i < len; i++) {
   86 		if (MULTIBYTE_FIRST_P(name[i]) &&
   87 		    MULTIBYTE_SECOND_P(name[i + 1]))
   88 			i++;
   89 		else if (name[i] == '\\')
   90 			name[i] = '/';
   91 		else if (!noconvertcase && isupper(name[i]))
   92 			name[i] = tolower(name[i]);
   93 	}
   94 #else
   95 	for (i = 0; i < len; i++) {
   96 		if (name[i] == '\\')
   97 			name[i] = '/';
   98 		else if (!noconvertcase && isupper(name[i]))
   99 			name[i] = tolower(name[i]);
  100 	}
  101 #endif
  102 }
  103 
  104 /* ------------------------------------------------------------------------ */
  105 static void
  106 generic_to_unix_filename(name, len)
  107 	register char  *name;
  108 	register int    len;
  109 {
  110 	register int    i;
  111 	boolean         lower_case_used = FALSE;
  112 
  113 #ifdef MULTIBYTE_CHAR
  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 (islower(name[i])) {
  119 			lower_case_used = TRUE;
  120 			break;
  121 		}
  122 	}
  123 	for (i = 0; i < len; i++) {
  124 		if (MULTIBYTE_FIRST_P(name[i]) &&
  125 		    MULTIBYTE_SECOND_P(name[i + 1]))
  126 			i++;
  127 		else if (name[i] == '\\')
  128 			name[i] = '/';
  129 		else if (!noconvertcase && !lower_case_used && isupper(name[i]))
  130 			name[i] = tolower(name[i]);
  131 	}
  132 #else
  133 	for (i = 0; i < len; i++)
  134 		if (islower(name[i])) {
  135 			lower_case_used = TRUE;
  136 			break;
  137 		}
  138 	for (i = 0; i < len; i++) {
  139 		if (name[i] == '\\')
  140 			name[i] = '/';
  141 		else if (!noconvertcase && !lower_case_used && isupper(name[i]))
  142 			name[i] = tolower(name[i]);
  143 	}
  144 #endif
  145 }
  146 
  147 /* ------------------------------------------------------------------------ */
  148 static void
  149 macos_to_unix_filename(name, len)
  150 	register char  *name;
  151 	register int    len;
  152 {
  153 	register int    i;
  154 
  155 	for (i = 0; i < len; i++) {
  156 		if (name[i] == ':')
  157 			name[i] = '/';
  158 		else if (name[i] == '/')
  159 			name[i] = ':';
  160 	}
  161 }
  162 
  163 /* ------------------------------------------------------------------------ */
  164 static void
  165 unix_to_generic_filename(name, len)
  166 	register char  *name;
  167 	register int    len;
  168 {
  169 	register int    i;
  170 
  171 	for (i = 0; i < len; i++) {
  172 		if (name[i] == '/')
  173 			name[i] = '\\';
  174 		else if (islower(name[i]))
  175 			name[i] = toupper(name[i]);
  176 	}
  177 }
  178 
  179 /* ------------------------------------------------------------------------ */
  180 /*																			*/
  181 /* Generic stamp format:						 							*/
  182 /*																			*/
  183 /* 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16							*/
  184 /* |<-------- year ------->|<- month ->|<-- day -->|						*/
  185 /*																			*/
  186 /* 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0							*/
  187 /* |<--- hour --->|<---- minute --->|<- second*2 ->|						*/
  188 /*																			*/
  189 /* ------------------------------------------------------------------------ */
  190 
  191 /*
  192  * NOTE : If you don't have `gettimeofday(2)', or your gettimeofday(2)
  193  * returns bogus timezone information, try FTIME, MKTIME, TIMELOCAL or TZSET.
  194  */
  195 
  196 /* choose one */
  197 #if defined(MKTIME)
  198 #ifdef TIMELOCAL
  199 #undef TIMELOCAL
  200 #endif
  201 #endif				/* defined(MKTIME) */
  202 
  203 #if defined(MKTIME) || defined(TIMELOCAL)
  204 #ifdef TZSET
  205 #undef TZSET
  206 #endif
  207 #endif				/* defined(MKTIME) || defined(TIMELOCAL) */
  208 
  209 #if defined(MKTIME) || defined(TIMELOCAL) || defined(TZSET)
  210 #ifdef FTIME
  211 #undef FTIME
  212 #endif
  213 #endif
  214 
  215 #if defined(MKTIME) || defined(TIMELOCAL) || defined(TZSET) || defined(FTIME)
  216 #ifdef GETTIMEOFDAY
  217 #undef GETTIMEOFDAY
  218 #endif
  219 #else
  220 #ifndef GETTIMEOFDAY
  221 #define GETTIMEOFDAY		/* use gettimeofday() */
  222 #endif
  223 #endif
  224 
  225 #ifdef FTIME
  226 #include <sys/timeb.h>
  227 #endif
  228 
  229 /*
  230  * You may define as : #define TIMEZONE_HOOK		\ extern long
  231  * timezone ;	\ extern void tzset();
  232  */
  233 #ifdef TIMEZONE_HOOK
  234 TIMEZONE_HOOK
  235 /* Which do you like better, `TIMEZONE_HOOK' or `TIMEZONE_HOOK;' ? */
  236 #endif
  237 
  238 #if defined(TZSET) && defined(_MINIX)
  239 extern long     timezone;		/* not defined in time.h */
  240 #endif
  241 
  242 /* ------------------------------------------------------------------------ */
  243 #if defined(FTIME) || defined(GETTIMEOFDAY) || defined(TZSET)
  244 static long
  245 gettz()
  246 #ifdef TZSET
  247 {
  248 	tzset();
  249 	return timezone;
  250 }
  251 #endif
  252 
  253 /* ------------------------------------------------------------------------ */
  254 #if !defined(TZSET) && defined(FTIME)
  255 {
  256 	struct timeb    buf;
  257 
  258 	ftime(&buf);
  259 	return buf.timezone * 60L;
  260 }
  261 #endif
  262 
  263 /* ------------------------------------------------------------------------ */
  264 #if !defined(TZSET) && !defined(FTIME)	/* maybe defined(GETTIMEOFDAY) */
  265 {
  266 #ifdef HAVE_TM_ZONE
  267 	time_t tt;
  268 
  269 	time(&tt);
  270 	return -localtime(&tt)->tm_gmtoff;
  271 #else /* HAVE_TM_ZONE */
  272 	struct timeval  tp;
  273 	struct timezone tzp;
  274 	gettimeofday(&tp, &tzp);/* specific to 4.3BSD */
  275 	/*
  276 	 * return (tzp.tz_minuteswest * 60L + (tzp.tz_dsttime != 0 ? 60L *
  277 	 * 60L : 0));
  278 	 */
  279 	return (tzp.tz_minuteswest * 60L);
  280 #endif /* HAVE_TM_ZONE */
  281 }
  282 #endif
  283 #endif				/* defined(FTIME) || defined(GETTIMEOFDAY) ||
  284 				 * defined(TZSET) */
  285 
  286 /* ------------------------------------------------------------------------ */
  287 #ifdef NOT_USED
  288 static struct tm *
  289 msdos_to_unix_stamp_tm(a)
  290 	long            a;
  291 {
  292 	static struct tm t;
  293 
  294 	t.tm_sec = (a & 0x1f) * 2;
  295 	t.tm_min = (a >> 5) & 0x3f;
  296 	t.tm_hour = (a >> 11) & 0x1f;
  297 	t.tm_mday = (a >> 16) & 0x1f;
  298 	t.tm_mon = ((a >> 16 + 5) & 0x0f) - 1;
  299 	t.tm_year = ((a >> 16 + 9) & 0x7f) + 80;
  300 	return &t;
  301 }
  302 #endif
  303 
  304 /* ------------------------------------------------------------------------ */
  305 static          time_t
  306 generic_to_unix_stamp(t)
  307 	long            t;
  308 #if defined(MKTIME) || defined(TIMELOCAL)
  309 {
  310 	struct tm       dostm;
  311 
  312 	/*
  313 	 * special case:  if MSDOS format date and time were zero, then we
  314 	 * set time to be zero here too.
  315 	 */
  316 	if (t == 0)
  317 		return (time_t) 0;
  318 
  319 	dostm.tm_sec = (t & 0x1f) * 2;
  320 	dostm.tm_min = t >> 5 & 0x3f;
  321 	dostm.tm_hour = t >> 11 & 0x1f;
  322 	dostm.tm_mday = t >> 16 & 0x1f;
  323 	dostm.tm_mon = (t >> 16 + 5 & 0x0f) - 1;	/* 0..11 */
  324 	dostm.tm_year = (t >> 16 + 9 & 0x7f) + 80;
  325 #if 0
  326 	dostm.tm_isdst = 0;	/* correct? */
  327 #endif
  328 	dostm.tm_isdst = -1;    /* correct? */
  329 #ifdef MKTIME
  330 	return (time_t) mktime(&dostm);
  331 #else				/* maybe defined(TIMELOCAL) */
  332 	return (time_t) timelocal(&dostm);
  333 #endif
  334 }
  335 
  336 #else				/* defined(MKTIME) || defined(TIMELOCAL) */
  337 {
  338 	int             year, month, day, hour, min, sec;
  339 	long            longtime;
  340 	static unsigned int dsboy[12] = {0, 31, 59, 90, 120, 151,
  341 	181, 212, 243, 273, 304, 334};
  342 	unsigned int    days;
  343 
  344 	/*
  345 	 * special case:  if MSDOS format date and time were zero, then we
  346 	 * set time to be zero here too.
  347 	 */
  348 	if (t == 0)
  349 		return (time_t) 0;
  350 
  351 	year = ((int) (t >> 16 + 9) & 0x7f) + 1980;
  352 	month = (int) (t >> 16 + 5) & 0x0f;	/* 1..12 means Jan..Dec */
  353 	day = (int) (t >> 16) & 0x1f;	/* 1..31 means 1st,...31st */
  354 
  355 	hour = ((int) t >> 11) & 0x1f;
  356 	min = ((int) t >> 5) & 0x3f;
  357 	sec = ((int) t & 0x1f) * 2;
  358 
  359 	/* Calculate days since 1970.01.01 */
  360 	days = (365 * (year - 1970) +	/* days due to whole years */
  361 		(year - 1970 + 1) / 4 +	/* days due to leap years */
  362 		dsboy[month - 1] +	/* days since beginning of this year */
  363 		day - 1);	/* days since beginning of month */
  364 
  365 	if ((year % 4 == 0) &&
  366 		(year % 100 != 0 || year % 400 == 0) &&		/* 1999.5.24 t.oka */
  367 	    (month >= 3))	/* if this is a leap year and month */
  368 		days++;		/* is March or later, add a day */
  369 
  370 	/* Knowing the days, we can find seconds */
  371 	longtime = (((days * 24) + hour) * 60 + min) * 60 + sec;
  372 	longtime += gettz();	/* adjust for timezone */
  373 
  374 	/* LONGTIME is now the time in seconds, since 1970/01/01 00:00:00.  */
  375 	return (time_t) longtime;
  376 }
  377 #endif				/* defined(MKTIME) || defined(TIMELOCAL) */
  378 
  379 /* ------------------------------------------------------------------------ */
  380 static long
  381 unix_to_generic_stamp(t)
  382 	time_t          t;
  383 {
  384 	struct tm      *tm = localtime(&t);
  385 
  386 	return ((((long) (tm->tm_year - 80)) << 25) +
  387 		(((long) (tm->tm_mon + 1)) << 21) +
  388 		(((long) tm->tm_mday) << 16) +
  389 		(long) ((tm->tm_hour << 11) +
  390 			(tm->tm_min << 5) +
  391 			(tm->tm_sec / 2)));
  392 }
  393 
  394 /* ------------------------------------------------------------------------ */
  395 /* build header functions													*/
  396 /* ------------------------------------------------------------------------ */
  397 boolean
  398 get_header(fp, hdr)
  399 	FILE           *fp;
  400 	register LzHeader *hdr;
  401 {
  402 	int             header_size;
  403 	int             name_length;
  404 	char            data[LZHEADER_STRAGE];
  405 	char            dirname[FILENAME_LENGTH];
  406 	int             dir_length = 0;
  407 	int             checksum;
  408 	int             i;
  409 	char           *ptr;
  410 	int				extend_size;
  411 	int				dmy;
  412 
  413 	bzero(hdr, sizeof(LzHeader));
  414 
  415 	if (((header_size = getc(fp)) == EOF) || (header_size == 0)) {
  416 		return FALSE;	/* finish */
  417 	}
  418 
  419 	if (fread(data + I_HEADER_CHECKSUM,
  420 		  sizeof(char), header_size - 1, fp) < header_size - 1) {
  421 		fatal_error("Invalid header (LHarc file ?)");
  422 		return FALSE;	/* finish */
  423 	}
  424 	setup_get(data + I_HEADER_LEVEL);
  425 	hdr->header_level = get_byte();
  426 	if (hdr->header_level != 2 &&
  427 	    fread(data + header_size, sizeof(char), 2, fp) < 2) {
  428 		fatal_error("Invalid header (LHarc file ?)");
  429 		return FALSE;	/* finish */
  430 	}
  431 
  432 	if (hdr->header_level >= 3) {
  433 		fatal_error("Unknown level header");
  434 		return FALSE;
  435 	}
  436 
  437 	setup_get(data + I_HEADER_CHECKSUM);
  438 	checksum = get_byte();
  439 
  440 	if (hdr->header_level == 2) {
  441 		hdr->header_size = header_size + checksum*256;
  442 	} else {
  443 		hdr->header_size = header_size;
  444 	}
  445 	bcopy(data + I_METHOD, hdr->method, METHOD_TYPE_STRAGE);
  446 	setup_get(data + I_PACKED_SIZE);
  447 	hdr->packed_size = get_longword();
  448 	hdr->original_size = get_longword();
  449 	hdr->last_modified_stamp = get_longword();
  450 	hdr->attribute = get_byte();
  451 
  452 	if ((hdr->header_level = get_byte()) != 2) {
  453 		if (calc_sum(data + I_METHOD, header_size) != checksum)
  454 			warning("Checksum error (LHarc file?)", "");
  455 		name_length = get_byte();
  456 		for (i = 0; i < name_length; i++)
  457 			hdr->name[i] = (char) get_byte();
  458 		hdr->name[name_length] = '\0';
  459 	}
  460 	else {
  461 		hdr->unix_last_modified_stamp = hdr->last_modified_stamp;
  462 		name_length = 0;
  463 	}
  464 
  465 	/* defaults for other type */
  466 	hdr->unix_mode = UNIX_FILE_REGULAR | UNIX_RW_RW_RW;
  467 	hdr->unix_gid = 0;
  468 	hdr->unix_uid = 0;
  469 
  470 	if (hdr->header_level == 0) {
  471 		extend_size = header_size - name_length -22;
  472 		if (extend_size < 0) {
  473 			if (extend_size == -2) {
  474 				hdr->extend_type = EXTEND_GENERIC;
  475 				hdr->has_crc = FALSE;
  476 			} else {
  477 				fatal_error("Unkonwn header (lha file?)");
  478 				return FALSE;
  479 			}
  480 		} else {
  481 			hdr->has_crc = TRUE;
  482 			hdr->crc = get_word();
  483 		}
  484 
  485 		if (extend_size >= 1) {
  486 			hdr->extend_type = get_byte();
  487 			extend_size--;
  488 		}
  489 		if (hdr->extend_type == EXTEND_UNIX) {
  490 			if (extend_size >= 11) {
  491 				hdr->minor_version = get_byte();
  492 				hdr->unix_last_modified_stamp = (time_t) get_longword();
  493 				hdr->unix_mode = get_word();
  494 				hdr->unix_uid = get_word();
  495 				hdr->unix_gid = get_word();
  496 				extend_size -= 11;
  497 			} else {
  498 				hdr->extend_type = EXTEND_GENERIC;
  499 			}
  500 		}
  501 		while (extend_size-- > 0)
  502 			dmy = get_byte();
  503 		if (hdr->extend_type == EXTEND_UNIX)
  504 			return TRUE;
  505 	} else if (hdr->header_level == 1) {
  506 		hdr->has_crc = TRUE;
  507 		extend_size = header_size - name_length-25;
  508 		hdr->crc = get_word();
  509 		hdr->extend_type = get_byte();
  510 		while (extend_size-- > 0)
  511 			dmy = get_byte();
  512 	} else { /* level 2 */
  513 		hdr->has_crc = TRUE;
  514 		hdr->crc = get_word();
  515 		hdr->extend_type = get_byte();
  516 	}
  517 
  518 	if (hdr->header_level > 0) {
  519 		/* Extend Header */
  520 		if (hdr->header_level != 2)
  521 			setup_get(data + hdr->header_size);
  522 		ptr = get_ptr;
  523 		while ((header_size = get_word()) != 0) {
  524 			if (hdr->header_level != 2 &&
  525 			((data + LZHEADER_STRAGE - get_ptr < header_size) ||
  526 			 fread(get_ptr, sizeof(char), header_size, fp) < header_size)) {
  527 				fatal_error("Invalid header (LHa file ?)");
  528 				return FALSE;
  529 			}
  530 			switch (get_byte()) {
  531 			case 0:
  532 				/*
  533 				 * header crc
  534 				 */
  535 				setup_get(get_ptr + header_size - 3);
  536 				break;
  537 			case 1:
  538 				/*
  539 				 * filename
  540 				 */
  541 				for (i = 0; i < header_size - 3; i++)
  542 					hdr->name[i] = (char) get_byte();
  543 				hdr->name[header_size - 3] = '\0';
  544 				name_length = header_size - 3;
  545 				break;
  546 			case 2:
  547 				/*
  548 				 * directory
  549 				 */
  550 				for (i = 0; i < header_size - 3; i++)
  551 					dirname[i] = (char) get_byte();
  552 				dirname[header_size - 3] = '\0';
  553 				convdelim(dirname, DELIM);
  554 				dir_length = header_size - 3;
  555 				break;
  556 			case 0x40:
  557 				/*
  558 				 * MS-DOS attribute
  559 				 */
  560 				if (hdr->extend_type == EXTEND_MSDOS ||
  561 				    hdr->extend_type == EXTEND_HUMAN ||
  562 				    hdr->extend_type == EXTEND_GENERIC)
  563 					hdr->attribute = get_word();
  564 				break;
  565 			case 0x50:
  566 				/*
  567 				 * UNIX permission
  568 				 */
  569 				if (hdr->extend_type == EXTEND_UNIX)
  570 					hdr->unix_mode = get_word();
  571 				break;
  572 			case 0x51:
  573 				/*
  574 				 * UNIX gid and uid
  575 				 */
  576 				if (hdr->extend_type == EXTEND_UNIX) {
  577 					hdr->unix_gid = get_word();
  578 					hdr->unix_uid = get_word();
  579 				}
  580 				break;
  581 			case 0x52:
  582 				/*
  583 				 * UNIX group name
  584 				 */
  585 				setup_get(get_ptr + header_size - 3);
  586 				break;
  587 			case 0x53:
  588 				/*
  589 				 * UNIX user name
  590 				 */
  591 				setup_get(get_ptr + header_size - 3);
  592 				break;
  593 			case 0x54:
  594 				/*
  595 				 * UNIX last modified time
  596 				 */
  597 				if (hdr->extend_type == EXTEND_UNIX)
  598 					hdr->unix_last_modified_stamp = (time_t) get_longword();
  599 				break;
  600 			default:
  601 				/*
  602 				 * other headers
  603 				 */
  604 				setup_get(get_ptr + header_size - 3);
  605 				break;
  606 			}
  607 		}
  608 		if (hdr->header_level != 2 && get_ptr - ptr != 2) {
  609 			hdr->packed_size -= get_ptr - ptr - 2;
  610 			hdr->header_size += get_ptr - ptr - 2;
  611 		}
  612 	}
  613 
  614 	switch (hdr->extend_type) {
  615 	case EXTEND_MSDOS:
  616 		msdos_to_unix_filename(hdr->name, name_length);
  617 		msdos_to_unix_filename(dirname, dir_length);
  618 	case EXTEND_HUMAN:
  619 		if (hdr->header_level == 2)
  620 			hdr->unix_last_modified_stamp = hdr->last_modified_stamp;
  621 		else
  622 			hdr->unix_last_modified_stamp =
  623 				generic_to_unix_stamp(hdr->last_modified_stamp);
  624 		break;
  625 
  626 #ifdef OSK
  627 	case EXTEND_OS68K:
  628 	case EXTEND_XOSK:
  629 #endif
  630 	case EXTEND_UNIX:
  631 		break;
  632 
  633 	case EXTEND_MACOS:
  634 		macos_to_unix_filename(hdr->name, name_length);
  635 		/* macos_to_unix_filename(dirname, dir_length); */
  636 		hdr->unix_last_modified_stamp =
  637 			generic_to_unix_stamp(hdr->last_modified_stamp);
  638 		break;
  639 
  640 	default:
  641 		generic_to_unix_filename(hdr->name, name_length);
  642 		generic_to_unix_filename(dirname, dir_length);
  643 		if (hdr->header_level == 2)
  644 			hdr->unix_last_modified_stamp = hdr->last_modified_stamp;
  645 		else
  646 			hdr->unix_last_modified_stamp =
  647 				generic_to_unix_stamp(hdr->last_modified_stamp);
  648 	}
  649 
  650 	if (dir_length) {
  651 		strcat(dirname, hdr->name);
  652 		strcpy(hdr->name, dirname);
  653 		name_length += dir_length;
  654 	}
  655 
  656 	return TRUE;
  657 }
  658 
  659 /* ------------------------------------------------------------------------ */
  660 void
  661 init_header(name, v_stat, hdr)
  662 	char           *name;
  663 	struct stat    *v_stat;
  664 	LzHeader       *hdr;
  665 {
  666 	int             len;
  667 
  668 	if (compress_method == LZHUFF5_METHOD_NUM)  /* Changed N.Watazaki */
  669 		bcopy(LZHUFF5_METHOD, hdr->method, METHOD_TYPE_STRAGE);
  670 	else if (compress_method)
  671 		bcopy(LZHUFF1_METHOD, hdr->method, METHOD_TYPE_STRAGE);
  672 	else
  673 		bcopy(LZHUFF0_METHOD, hdr->method, METHOD_TYPE_STRAGE);
  674 
  675 	hdr->packed_size = 0;
  676 	hdr->original_size = v_stat->st_size;
  677 	hdr->last_modified_stamp = unix_to_generic_stamp(v_stat->st_mtime);
  678 	hdr->attribute = GENERIC_ATTRIBUTE;
  679 	hdr->header_level = header_level;
  680 	strcpy(hdr->name, name);
  681 	len = strlen(name);
  682 	hdr->crc = 0x0000;
  683 	hdr->extend_type = EXTEND_UNIX;
  684 	hdr->unix_last_modified_stamp = v_stat->st_mtime;
  685 	/* since 00:00:00 JAN.1.1970 */
  686 #ifdef NOT_COMPATIBLE_MODE
  687 	/* Please need your modification in this space. */
  688 #else
  689 	hdr->unix_mode = v_stat->st_mode;
  690 #endif
  691 
  692 	hdr->unix_uid = v_stat->st_uid;
  693 	hdr->unix_gid = v_stat->st_gid;
  694 
  695 	if (is_directory(v_stat)) {
  696 		bcopy(LZHDIRS_METHOD, hdr->method, METHOD_TYPE_STRAGE);
  697 		hdr->attribute = GENERIC_DIRECTORY_ATTRIBUTE;
  698 		hdr->original_size = 0;
  699 		if (len > 0 && hdr->name[len - 1] != '/')
  700 			strcpy(&hdr->name[len++], "/");
  701 	}
  702 
  703 #ifdef S_IFLNK
  704 	if (is_symlink(v_stat)) {
  705 		char	lkname[257];
  706 		int		len;
  707 		bcopy(LZHDIRS_METHOD, hdr->method, METHOD_TYPE_STRAGE);
  708 		hdr->attribute = GENERIC_DIRECTORY_ATTRIBUTE;
  709 		hdr->original_size = 0;
  710 		len = readlink(name, lkname, 256);
  711 		lkname[len] = (char)'\0';
  712 		sprintf(hdr->name, "%s|%s", hdr->name, lkname);
  713 	}
  714 #endif
  715 	if (generic_format)
  716 		unix_to_generic_filename(hdr->name, len);
  717 }
  718 
  719 /* ------------------------------------------------------------------------ */
  720 /* Write unix extended header or generic header. */
  721 void
  722 write_header(nafp, hdr)
  723 	FILE           *nafp;
  724 	LzHeader       *hdr;
  725 {
  726 	int             header_size;
  727 	int             name_length;
  728 	char            data[LZHEADER_STRAGE];
  729 	char           *p;
  730 	char           *headercrc_ptr;
  731 
  732 	bzero(data, LZHEADER_STRAGE);
  733 	bcopy(hdr->method, data + I_METHOD, METHOD_TYPE_STRAGE);
  734 	setup_put(data + I_PACKED_SIZE);
  735 	put_longword(hdr->packed_size);
  736 	put_longword(hdr->original_size);
  737 
  738 	if (hdr->header_level == HEADER_LEVEL2)
  739 		put_longword((long) hdr->unix_last_modified_stamp);
  740 	else
  741 		put_longword(hdr->last_modified_stamp);
  742 
  743 	switch (hdr->header_level) {
  744 	case HEADER_LEVEL0:
  745 		put_byte(hdr->attribute);
  746 		break;
  747 	case HEADER_LEVEL1:
  748 	case HEADER_LEVEL2:
  749 		put_byte(0x20);
  750 		break;
  751 	}
  752 
  753 	put_byte(hdr->header_level);
  754 
  755 	convdelim(hdr->name, DELIM2);
  756 	if (hdr->header_level != HEADER_LEVEL2) {
  757 		if (p = (char *) rindex(hdr->name, DELIM2))
  758 			name_length = strlen(++p);
  759 		else
  760 			name_length = strlen(hdr->name);
  761 		put_byte(name_length);
  762 		bcopy(p ? p : hdr->name, data + I_NAME, name_length);
  763 		setup_put(data + I_NAME + name_length);
  764 	}
  765 
  766 	put_word(hdr->crc);
  767 	if (header_level == HEADER_LEVEL0) {
  768 		if (generic_format) {
  769 			header_size = I_GENERIC_HEADER_BOTTOM - 2 + name_length;
  770 			data[I_HEADER_SIZE] = header_size;
  771 			data[I_HEADER_CHECKSUM] = calc_sum(data + I_METHOD, header_size);
  772 		} else {
  773 			/* write old-style extend header */
  774 			put_byte(EXTEND_UNIX);
  775 			put_byte(CURRENT_UNIX_MINOR_VERSION);
  776 			put_longword((long) hdr->unix_last_modified_stamp);
  777 			put_word(hdr->unix_mode);
  778 			put_word(hdr->unix_uid);
  779 			put_word(hdr->unix_gid);
  780 			header_size = I_UNIX_EXTEND_BOTTOM - 2 + name_length;
  781 			data[I_HEADER_SIZE] = header_size;
  782 			data[I_HEADER_CHECKSUM] = calc_sum(data + I_METHOD, header_size);
  783 		}
  784 	} else {
  785 		/* write extend header. */
  786 		char           *ptr;
  787 
  788 		if (generic_format)
  789 			put_byte(0x00);
  790 		else
  791 			put_byte(EXTEND_UNIX);
  792 
  793 		ptr = put_ptr;
  794 		if (hdr->header_level == HEADER_LEVEL2) {
  795 			/* write common header */
  796 			put_word(5);
  797 			put_byte(0x00);
  798 			headercrc_ptr = put_ptr;
  799 			put_word(0x0000);
  800 		}
  801 
  802 		if (generic_format) {
  803 			header_size = put_ptr - data;	/* +2 for last 0x0000 */
  804 		} else {
  805 			put_word(5);
  806 			if (hdr->header_level == HEADER_LEVEL1)
  807 				header_size = put_ptr - data - 2;
  808 			put_byte(0x50);	/* permission */
  809 			put_word(hdr->unix_mode);
  810 			put_word(7);
  811 			put_byte(0x51);	/* gid and uid */
  812 			put_word(hdr->unix_gid);
  813 			put_word(hdr->unix_uid);
  814 
  815 			if (p = (char *) rindex(hdr->name, DELIM2)) {
  816 				int             i;
  817 
  818 				name_length = p - hdr->name + 1;
  819 				put_word(name_length + 3);
  820 				put_byte(2);	/* dirname */
  821 				for (i = 0; i < name_length; i++)
  822 					put_byte(hdr->name[i]);
  823 			}
  824 		}		/* if generic .. */
  825 
  826 		if (header_level != HEADER_LEVEL2) {
  827 			if (!generic_format) {
  828 				put_word(7);
  829 				put_byte(0x54);	/* time stamp */
  830 				put_longword(hdr->unix_last_modified_stamp);
  831 			}
  832 			hdr->packed_size += put_ptr - ptr;
  833 			ptr = put_ptr;
  834 			setup_put(data + I_PACKED_SIZE);
  835 			put_longword(hdr->packed_size);
  836 			put_ptr = ptr;
  837 			data[I_HEADER_SIZE] = header_size;
  838 			data[I_HEADER_CHECKSUM] = calc_sum(data + I_METHOD, header_size);
  839 		} else {		/* header level 2 */
  840 			int             i;
  841 			if (p = (char *) rindex(hdr->name, DELIM2))
  842 				name_length = strlen(++p);
  843 			else {
  844 				p = hdr->name;
  845 				name_length = strlen(hdr->name);
  846 			}
  847 			put_word(name_length + 3);
  848 			put_byte(1);	/* filename */
  849 			for (i = 0; i < name_length; i++)
  850 				put_byte(*p++);
  851 		}		/* if he.. != HEAD_LV2 */
  852 		header_size = put_ptr - data;
  853 	}
  854 
  855 	if (header_level == HEADER_LEVEL2) {
  856 		unsigned short  hcrc;
  857 		setup_put(data + I_HEADER_SIZE);
  858 		put_word(header_size + 2);
  859 		/* common header */
  860 		hcrc = calc_header_crc(data, (unsigned int) header_size + 2);
  861 		setup_put(headercrc_ptr);
  862 		put_word(hcrc);
  863 	}
  864 
  865 	if (fwrite(data, sizeof(char), header_size + 2, nafp) == 0)
  866 		fatal_error("Cannot write to temporary file");
  867 
  868 	convdelim(hdr->name, DELIM);
  869 }
  870 
  871 /* Local Variables: */
  872 /* mode:c */
  873 /* tab-width:4 */
  874 /* compile-command:"gcc -c header.c" */
  875 /* End: */