home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DOS/V Power Report 1997 December
/
VPR9712A.ISO
/
OLS
/
OS2
/
LHA2P205
/
LHA2P205.LZH
/
lha2-2.05pre
/
source.lzh
/
src
/
header.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-02-25
|
32KB
|
1,240 lines
/*
* header.c
* Copyright (C) 1988-1994, Haruyasu YOSHIZAKI
* Copyright (C) 1991-1996, Satoshi HIRAMATSU
*
* $Log$
*/
#include <sys/types.h>
#include <stdio.h>
#include <io.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include "typedef.h"
#include "port2.h"
#include "lh.h"
#include "intrface.h"
#include "errmes.h"
#include "header.h"
HEADER hpb;
#define HDR_READ_SIZE 21 /* 初回読み込み時の読み込みサイズ */
/* ヘッダのサイズ */
#define HDRsize(a) (byte *)((a) + 0)
/* ヘッダのサイズ */
#define HDRsize2(a) (hword *)((a) + 0)
/* チェックサム */
#define HDRsum(a) (byte *)((a) + 1)
/* 圧縮法 */
#define HDRmethod(a) (byte *)((a) + 2)
/* 圧縮後のサイズ */
#define HDRpacked(a) (word *)((a) + 7)
/* 元のサイズ */
#define HDRoriginal(a) (word *)((a) + 11)
/* 最終更新日時 */
#define HDRmtime(a) (hword *)((a) + 15)
/* MS-DOSファイル属性 */
#define HDRattribute(a) (byte *)((a) + 19)
/* ヘッダレベル */
#define HDRlevel(a) (byte *)((a) + 20)
/* ファイル名長 */
#define HDRnamelen(a) (byte *)((a) + 21)
/* CRC-16 */
#define HDRcrc(a) (hword *)((a) + 21)
/* ファイル名 */
#define HDRname(a) (byte *)((a) + 22)
/* 作成OS識別子 */
#define HDRcreator(a) (byte *)((a) + 23)
/* 先頭拡張ヘッダサイズ(2bytes) */
#define HDRnext(a) (hword *)((a) + 24)
/* 全ヘッダサイズ(Level3のみ) */
#define HDRsize3(a) (word *)((a) + 24)
/* 先頭拡張ヘッダサイズ(Level3のみ) */
#define HDRnext3(a) (word *)((a) + 28)
#ifdef LITTLE_ENDIAN
#define GetHWord(p) (0xffff & (*(hword *)(p)))
#define GetWord(p) (*(word *)(p))
#define SetHWord(p,q) (*(hword *)(p) = (0xffff & (uint)(q)))
#define SetWord(p,q) (*(word *)(p) = (q))
#else
#ifdef BIG_ENDIAN
#define GetHWord(p) (*(p) + ((hword)*((p) + 1) << 8))
#define GetWord(p) (GetHWord(p) + ((word)GetHWord((p) + 2) << 16))
#define SetHWord(p,q) \
{ \
register hword a = q; \
*(p)[0] = 0xff & (uint)a; \
*(p)[1] = 0xff & ((uint)a >> 8); \
}
#define SetWord(p,q) \
{ \
register word a = q; \
(p)[0] = 0xff & (uint)a; \
(p)[1] = 0xff & ((uint)a >> 8); \
(p)[2] = 0xff & ((uint)a >> 16); \
(p)[3] = 0xff & ((uint)a >> 24); \
}
#endif
#endif
/* compression method strings */
char methods[11][5] =
{
"-lh0-", "-lh1-", "-lh2-", "-lh3-", "-lh4-",
"-lh5-", "-lzs-", "-lz5-", "-lz4-", "-lhd-", "\0\0\0\0\0"
};
/*
* nextpos --- save/load next header position
*/
#define NEXTPOS_SET 0
#define NEXTPOS_GET 1
static off_t
nextpos(sw, pos)
bool sw;
off_t pos;
{
static off_t current;
if(sw == NEXTPOS_SET)
current = pos;
else if(sw == NEXTPOS_GET)
return current;
else
return -1;
return 0;
}
/*
* calcsum --- caculate header check-sum
*/
static byte
calcsum(base)
register byte *base;
{
register byte *end, sum = 0;
end = base + *HDRsize(base) + 2; /* set end point */
base += 2; /* skip 2bytes */
do
sum += *base++;
while(base < end);
return sum;
}
/*
* getext --- read extend header
*/
static off_t
getext(fp, headersize, header, wordsize, hcrc)
FILE *fp;
off_t headersize;
HEADER *header;
size_t wordsize;
hword *hcrc;
{
register off_t rsize;
off_t read;
byte *buffer;
rsize = headersize - wordsize;
if((ulong)headersize > (ulong)READ_MAX)
return crcfread(fp, rsize, hcrc);
buffer = (byte *)e_malloc(rsize);
if((read = fread(buffer, 1, rsize, fp)) < rsize)
{
free(buffer);
return 0;
}
switch(0xff & (uint)*buffer)
{
case 0x00: /* common */
header->crcpos = TRUE; /* for level-1 header */
header->headercrc = GetHWord(buffer + 1);
if((headersize >= 6) || (headersize >= 8)) /* additional information */
header->info = (int)*(buffer + 3);
SetHWord(buffer + 1, 0);
*hcrc = calccrc(buffer, rsize, *hcrc);
free(buffer);
return read;
case 0x01: /* filename */
*hcrc = calccrc(buffer, rsize, *hcrc);
memmove(buffer, buffer + 1, --rsize);
if(header->filename)
free(header->filename);
header->filename = buffer;
header->filename[rsize] = '\0';
header->namelen = rsize;
return read;
case 0x02: /* directory name */
*hcrc = calccrc(buffer, rsize, *hcrc);
memmove(buffer, buffer + 1, --rsize);
header->pathname = buffer;
header->pathname[rsize] = '\0';
header->pathlen = rsize;
return read;
case 0x3f: /* comment */
break;
case 0x40: /* MS-DOS dependent */
if((header->creator == CREATOR_OS2)
|| (header->creator == CREATOR_MSDOS))/* implementer dependent */
header->attr = (uint)GetHWord(buffer + 1);
break;
#ifdef __SUPPORT_PERMISSION__
case 0x50: /* permission */
header->mode = (word)GetHWord(buffer + 1);
break;
#endif
#ifdef __SUPPORT_UID_GID__
case 0x51: /* UID and GID */
header->gid = (word)GetHWord(buffer + 1);
header->uid = (word)GetHWord(buffer + 3);
break;
#endif
#ifdef __SUPPORT_MTIME__
case 0x54: /* for UNIX */
header->mtime = (time_t)GetWord(buffer + 1);
break;
#endif
case 0x7f: /* information */
header->mode = GetHWord(buffer + 1);
#ifdef __SUPPORT_UID_GID__
header->gid = GetHWord(buffer + 5);
header->uid = GetHWord(buffer + 7);
#endif
#ifdef __SUPPORT_CTIME_ATIME__
header->ctime = GetWord(buffer + 9);
header->atime = GetWord(buffer + 13);
#endif
break;
#ifdef __SUPPORT_EA__
case 0x7e: /* EA */
#ifdef __OS2__ /* Sample implementation */
*hcrc = calccrc(buffer, rsize, *hcrc);
if(header->creator == CREATOR_OS2) /* implementer dependent */
{
register uint os = (uint)*(buffer + 2);
if((os == 4) && !memcmp(buffer + 3, "OS/2", 4))
{
if(*(buffer + 1) == __TYPE_EA__)
{
if((uint)*(buffer + 3 + os) >= (uint)0x02)
{
memmove(buffer, buffer + 3 + os, rsize - 3 - os);
header->ea = (FEA2LIST *)buffer;
return read;
}
}
}
}
free(buffer);
return read;
#else
break;
#endif
#endif
#ifdef __SUPPORT_KAPSEL__
case 0x7d: /* MacBinary like kapsel */
header->kapselheadersize = GetWord(buffer + 1);
header->filesize = GetWord(buffer + 5);
break;
#endif
default:
break;
}
*hcrc = calccrc(buffer, rsize, *hcrc);
free(buffer);
return read;
}
/*
* level0r --- read level-0 header
*/
static off_t
level0r(fp, baseheader, header)
FILE *fp;
byte *baseheader;
HEADER *header;
{
size_t read, hsize;
char *p;
header->headersize = (word)*HDRsize(baseheader) + 2;
if((hsize = header->headersize - HDR_READ_SIZE) <= 0)
return 0;
if((read = fread(baseheader + HDR_READ_SIZE, 1, hsize, fp)) - hsize)
return 0;
header->dostime.u = GetWord(HDRmtime(baseheader));
header->mtime = dos2unix(&(header->dostime.s));
#ifdef __SUPPORT_CTIME_ATIME__
header->ctime = header->atime = header->mtime;
#endif
if(calcsum(baseheader) != *HDRsum(baseheader))
{
if(*baseheader == 0x1a)
return read; /* for LArc & XMODEM */
return 0; /* Checksum error */
}
if(read < 3) /* ファイル名長が0でも可 */
return 0; /* illegal */
header->pathlen = (int)*HDRnamelen(baseheader);
header->filecrc =
GetHWord(HDRnamelen(baseheader) + (uint)header->pathlen + 1);
header->pathname = (char *)e_malloc(header->pathlen + 1);
memcpy(header->pathname, HDRname(baseheader), header->pathlen);
header->pathname[header->pathlen] = '\0';
convdelim(header->pathname, DELIM);
if(p = strrchr(header->pathname, DELIM))
{
if(*++p)
{
header->namelen = strlen(p);
header->filename = (char *)e_malloc(header->namelen + 1);
strcpy(header->filename, p);
}
*p = '\0';
header->pathlen = strlen(header->pathname);
}
return (off_t)read;
}
/*
* level1r --- read level-1 header
*/
static off_t
level1r(fp, baseheader, header)
FILE *fp;
byte *baseheader;
HEADER *header;
{
off_t read, hsize, next;
register byte *address;
byte buffer[sizeof(hword)];
hword hcrc;
word basesize;
basesize = header->headersize = (word)*HDRsize(baseheader) + 2;
if((hsize = header->headersize - HDR_READ_SIZE) < 6)
return 0;
if((read = fread(baseheader + HDR_READ_SIZE, 1, hsize, fp)) - hsize)
return 0;
if(calcsum(baseheader) != *HDRsum(baseheader))
return 0; /* Checksum error */
header->dostime.u = GetWord(HDRmtime(baseheader));
header->mtime = dos2unix(&(header->dostime.s));
#ifdef __SUPPORT_CTIME_ATIME__
header->ctime = header->atime = header->mtime;
#endif
header->namelen = (int)*HDRnamelen(baseheader);
address = HDRnamelen(baseheader) + (uint)header->namelen + 1;
header->filecrc = GetHWord(address);
header->creator = *(address + 2);
if(header->namelen)
{
header->filename = (char *)e_malloc(header->namelen + 1);
strncpy(header->filename, HDRname(baseheader), header->namelen);
header->filename[header->namelen] = '\0';
header->filename = convdelim(header->filename, DELIM);
}
/* calculate header-CRC */
header->crcpos = FALSE;
hcrc = calccrc(baseheader, header->headersize, 0);
/* read next extend header size */
next = (size_t)GetHWord(address + 3);
while(next)
{
header->headersize += next;
if(!(hsize = getext(fp, next, header, sizeof(hword), &hcrc)))
return 0;
read += hsize;
if(fread(buffer, 1, sizeof(hword), fp) != sizeof(hword))
return 0;
read += sizeof(hword);
next = (off_t)GetHWord(buffer);
/* calculate header-CRC */
hcrc = calccrc(buffer, sizeof(hword), hcrc);
}
/* check header-CRC */
if(header->crcpos)
if(header->headercrc != hcrc)
return (off_t)0;
/* adjust packed size */
header->packed -= (header->headersize - basesize);
return (off_t)read;
}
/*
* level2r --- read level-2 header
*/
static off_t
level2r(fp, baseheader, header)
FILE *fp;
byte *baseheader;
HEADER *header;
{
off_t read, hsize, next;
byte buffer[sizeof(hword)];
hword hcrc;
if((read = fread(baseheader + HDR_READ_SIZE, 1, 5, fp)) - 5)
return 0;
header->headersize = (word)GetHWord(HDRsize2(baseheader));
header->mtime = GetWord(HDRmtime(baseheader));
#ifdef __SUPPORT_CTIME_ATIME__
header->ctime = header->atime = header->mtime;
#endif
header->filecrc = GetHWord(HDRcrc(baseheader));
header->creator = *HDRcreator(baseheader);
/* calculate header-CRC */
hcrc = calccrc(baseheader, HDR_READ_SIZE + 5, 0);
/* read next extend header size */
next = (off_t)GetHWord(HDRnext(baseheader));
while(next)
{
if(!(hsize = getext(fp, next, header, sizeof(hword), &hcrc)))
return 0;
read += hsize;
if(fread(buffer, 1, sizeof(hword), fp) != sizeof(hword))
return 0;
read += sizeof(hword);
next = (off_t)GetHWord(buffer);
/* calculate header-CRC */
hcrc = calccrc(buffer, sizeof(hword), hcrc);
}
if(header->headersize == read + HDR_READ_SIZE + 1)
{
read += fread(&(header->dummy), 1, 1, fp);
hcrc = calccrc(&(header->dummy), 1, hcrc);
}
/* check header-CRC */
if(header->headercrc != hcrc)
return (off_t)0;
return (off_t)read;
}
/*
* level3r --- read level-3 header
*/
static off_t
level3r(fp, baseheader, header)
FILE *fp;
byte *baseheader;
HEADER *header;
{
off_t read, hsize, next;
byte buffer[sizeof(word)];
hword hcrc;
if((read = fread(baseheader + HDR_READ_SIZE, 1, 11, fp)) - 11)
return 0;
header->mtime = GetWord(HDRmtime(baseheader));
#ifdef __SUPPORT_CTIME_ATIME__
header->ctime = header->atime = header->mtime;
#endif
header->filecrc = GetHWord(HDRcrc(baseheader));
header->creator = *HDRcreator(baseheader);
header->headersize = GetWord(HDRsize3(baseheader));
/* calculate header-CRC */
hcrc = calccrc(baseheader, HDR_READ_SIZE + 11, 0);
/* read next extend header size */
next = (off_t)GetWord(HDRnext3(baseheader));
while(next)
{
if(!(hsize = getext(fp, (off_t)next, header, sizeof(word), &hcrc)))
return 0;
read += hsize;
if(fread(buffer, 1, sizeof(word), fp) != sizeof(word))
return 0;
read += sizeof(word);
next = (off_t)GetWord(buffer);
/* calculate header-CRC */
hcrc = calccrc(buffer, sizeof(word), hcrc);
}
/* check header-CRC */
if(header->headercrc != hcrc)
return (off_t)0;
return (off_t)read;
}
/*
* gethdr --- get information from LHA header.
*/
char *
gethdr(fp, header)
FILE *fp;
HEADER *header;
{
static byte buffer[257];
byte *baseheader = &buffer[0];
off_t read;
int method;
static off_t (*decodeheader[4])() = {level0r, level1r, level2r, level3r};
fseek(fp, nextpos(NEXTPOS_GET, 0), SEEK_SET);
/* read common part */
if((read = fread(baseheader, 1, HDR_READ_SIZE, fp)) - HDR_READ_SIZE)
return (char *)NULL;
/* common part */
memcpy(header->method, HDRmethod(baseheader), 5);
memcpy(methods[SENTINEL], header->method, 5);
for(method = 0; memcmp(header->method, methods[method], 5); method++)
;
if(method == SENTINEL)
return (char *)NULL; /* unsupported method */
header->packed = header->skip = GetWord(HDRpacked(baseheader));
header->original = GetWord(HDRoriginal(baseheader));
header->attr = (uint)*HDRattribute(baseheader);
header->level = (uint)*HDRlevel(baseheader);
if(header->level > (uint)3)
return (char *)NULL; /* unsupported header level */
/* initialize */
header->pathlen = 0;
header->namelen = 0;
header->pathname = (char *)NULL;
header->filename = (char *)NULL;
#ifdef __SUPPORT_EA__
#ifdef __OS2__
header->ea = (FEA2LIST *)NULL;
#endif
#endif
#ifdef __SUPPORT_CTIME_ATIME__
header->ctime = header->atime = 0;
#endif
/* switch header level */
if((read += (*decodeheader[header->level])(fp, baseheader, header))
== HDR_READ_SIZE)
return (char *)NULL; /* unrecognized header */
/* make pathname */
if(header->pathlen && header->namelen)
{
register char *p;
p = (char *)e_malloc(header->pathlen + header->namelen + 1);
strcpy(p, header->pathname);
free(header->pathname);
header->pathname = p;
strcat(p, header->filename);
header->pathlen += header->namelen; /* adjust */
}
else if(header->namelen)
{
header->pathname = header->filename;
header->pathlen = header->namelen;
}
else if(header->pathlen)
{
/* for level0 header */
header->filename = header->pathname;
header->namelen = header->pathlen;
}
convdelim(header->pathname, DELIM);
/* set next header position */
header->offset = read;
nextpos(NEXTPOS_SET, nextpos(NEXTPOS_GET, 0) + read + header->packed);
/* return path name */
return header->pathname;
}
/*
* inithdr --- initialize LHA header
*/
bool
inithdr(fp)
FILE *fp;
{
nextpos(NEXTPOS_SET, 0); /* initialize */
rewind(fp);
if(!fgetc(fp))
return TRUE; /* illegal header */
fgetc(fp);
if((fgetc(fp) == (int)'-') && (fgetc(fp) == (int)'l'))
{
fgetc(fp);
fgetc(fp);
if(fgetc(fp) == (int)'-')
return FALSE; /* perhaps legal header */
}
return TRUE; /* illegal header */
}
/*
* makeext --- make extend header for level-1, level-2 base header
*/
static bool
makeext(baseheader, header)
HEADERLINK *baseheader;
HEADER *header;
{
register byte *address;
register int need = 0;
/* filename */
if(header->needfname)
{
baseheader->next = (HEADERLINK *)e_malloc(sizeof(HEADERLINK));
baseheader = baseheader->next;
baseheader->size = 3 + header->namelen;
address = baseheader->header = (byte *)e_malloc(baseheader->size);
*address++ = 0x01;
memcpy(address, header->filename, header->namelen);
address += header->namelen;
SetHWord(address, 0);
++need;
}
/* directoryname */
if(header->pathname != header->filename)
{
baseheader->next = (HEADERLINK *)e_malloc(sizeof(HEADERLINK));
baseheader = baseheader->next;
baseheader->size = 3 + header->pathlen - header->namelen;
address = baseheader->header = (byte *)e_malloc(baseheader->size);
*address++ = 0x02;
convdelim(header->pathname, DELIM2);
memcpy(address, header->pathname, baseheader->size - 3);
convdelim(header->pathname, DELIM);
address += baseheader->size - 3;
SetHWord(address, 0);
++need;
}
/* comment (unsupport) */
/* MS-DOS dependent */
if(header->attr != 0x20)
{
baseheader->next = (HEADERLINK *)e_malloc(sizeof(HEADERLINK));
baseheader = baseheader->next;
baseheader->size = 5;
address = baseheader->header = (byte *)e_malloc(baseheader->size);
*address++ = 0x40;
SetHWord(address, header->attr);
address += 2;
SetHWord(address, 0);
++need;
}
#ifdef __SUPPORT_PERMISSION__
/* UNIX dependent */
baseheader->next = (HEADERLINK *)e_malloc(sizeof(HEADERLINK));
baseheader = baseheader->next;
baseheader->size = 5;
address = baseheader->header = (byte *)e_malloc(baseheader->size);
*address++ = 0x50;
SetHWord(address, header->mode);
address += 2;
SetHWord(address, 0);
++need;
#endif
#ifdef __SUPPORT_UID_GID__
/* UNIX dependent */
baseheader->next = (HEADERLINK *)e_malloc(sizeof(HEADERLINK));
baseheader = baseheader->next;
baseheader->size = 7;
address = baseheader->header = (byte *)e_malloc(baseheader->size);
*address++ = 0x51;
#ifndef __OS2__
SetHWord(address, header->gid);
#else
SetHWord(address, gid); /* __OS2__ */
#endif
address += 2;
#ifndef __OS2__
SetHWord(address, header->uid);
#else
SetHWord(address, uid); /* __OS2__ */
#endif
address += 2;
SetHWord(address, 0);
++need;
#endif
#ifdef __SUPPORT_MTIME__
/* UNIX dependent */
if(header->level == 1)
{
baseheader->next = (HEADERLINK *)e_malloc(sizeof(HEADERLINK));
baseheader = baseheader->next;
baseheader->size = 7;
address = baseheader->header = (byte *)e_malloc(baseheader->size);
*address++ = 0x54;
SetWord(address, header->mtime);
address += 2;
SetHWord(address, 0);
++need;
}
#endif
/* common */
if(((uint)header->level > 1) || need)
{
baseheader->next = (HEADERLINK *)e_malloc(sizeof(HEADERLINK));
baseheader = baseheader->next;
baseheader->size = 5 + (header->info ? 1 : 0);
address = baseheader->header = (byte *)e_malloc(baseheader->size);
header->crcpos = TRUE;
*address++ = 0x00;
SetHWord(address, 0);
address += 2;
if(header->info)
*address++ = header->info;
SetHWord(address, 0);
}
baseheader->next = (HEADERLINK *)NULL;
return FALSE;
}
/*
* makeext3 --- make extend header for level-3 base header
*/
static bool
makeext3(baseheader, header)
HEADERLINK *baseheader;
HEADER *header;
{
register byte *address;
register hword unixmode;
/* common */
baseheader->next = (HEADERLINK *)e_malloc(sizeof(HEADERLINK));
baseheader = baseheader->next;
baseheader->size = 7 + (header->info ? 1 : 0);
address = baseheader->header = (byte *)e_malloc(baseheader->size);
header->crcpos = TRUE; /* offset of header-CRC */
*address++ = 0x00;
SetHWord(address, 0);
address += 2;
if(header->info)
*address++ = header->info;
SetWord(address, 0);
/* filename */
baseheader->next = (HEADERLINK *)e_malloc(sizeof(HEADERLINK));
baseheader = baseheader->next;
baseheader->size = 5 + header->namelen;
SetWord(address, baseheader->size);
address = baseheader->header = (byte *)e_malloc(baseheader->size);
*address++ = 0x01;
memcpy(address, header->filename, header->namelen);
address += header->namelen;
SetWord(address, 0);
/* directoryname */
if(header->pathname != header->filename)
{
baseheader->next = (HEADERLINK *)e_malloc(sizeof(HEADERLINK));
baseheader = baseheader->next;
baseheader->size = 5 + header->pathlen - header->namelen;
SetWord(address, baseheader->size);
address = baseheader->header = (byte *)e_malloc(baseheader->size);
*address++ = 0x02;
convdelim(header->pathname, DELIM2);
memcpy(address, header->pathname, baseheader->size - 5);
convdelim(header->pathname, DELIM);
address += baseheader->size - 5;
SetWord(address, 0);
}
/* comment (unsupport) */
/* Attribute header */
baseheader->next = (HEADERLINK *)e_malloc(sizeof(HEADERLINK));
baseheader = baseheader->next;
baseheader->size = 21;
SetWord(address, baseheader->size);
address = baseheader->header = (byte *)e_malloc(baseheader->size);
*address++ = 0x7f;
/* set MS-DOS dependent attribute */
SetHWord(address, header->mode);
address += 2;
/* set UNIX dependent permission */
unixmode = 0;
if(header->mode & _A_RDONLY)
unixmode |= 0000440; /* -r--r----- */
else
unixmode |= 0000660; /* -rw-rw---- */
if(header->mode & _A_SUBDIR)
unixmode |= 0040550; /* dr-xr-x--- */
if(header->mode & (_A_HIDDEN | _A_SYSTEM))
unixmode &= 0177700; /* ????------ */
SetHWord(address, unixmode);
address += 2;
#ifdef __SUPPORT_UID_GID__
#ifndef __OS2__
SetHWord(address, header->gid);
#else
SetHWord(address, gid); /* __OS2__ */
#endif
address += 2;
#ifndef __OS2__
SetHWord(address, header->uid);
#else
SetHWord(address, uid); /* __OS2__ */
#endif
address += 2;
#else
SetHWord(address, 0);
address += 2;
SetHWord(address, 0);
address += 2;
#endif
#ifdef __SUPPORT_CTIME_ATIME__
SetWord(address, header->ctime);
address += 4;
SetWord(address, header->atime);
address += 4;
#else
SetWord(address, header->mtime);
address += 4;
SetWord(address, header->mtime);
address += 4;
#endif
SetWord(address, 0);
#ifdef __SUPPORT_EA__
#ifdef __OS2__
/* EA header sample implememtation */
if(header->ea)
{
baseheader->next = (HEADERLINK *)e_malloc(sizeof(HEADERLINK));
baseheader = baseheader->next;
baseheader->size = 7 + strlen(EA_CREATOR_OS2) + header->ea->cbList;
SetWord(address, baseheader->size);
address = baseheader->header = (byte *)e_malloc(baseheader->size);
*address++ = 0x7e;
*address++ = __TYPE_EA__;
*address++ = 0xff & strlen(EA_CREATOR_OS2);
memcpy(address, EA_CREATOR_OS2, strlen(EA_CREATOR_OS2));
address += strlen(EA_CREATOR_OS2);
memcpy(address, header->ea, header->ea->cbList);
address += header->ea->cbList;
SetWord(address, 0);
}
#endif
#endif
#ifdef __SUPPORT_KAPSEL__
/* KAPSEL */
if(header->filesize)
{
baseheader->next = (HEADERLINK *)e_malloc(sizeof(HEADERLINK));
baseheader = baseheader->next;
baseheader->size = 13;
SetWord(address, baseheader->size);
address = baseheader->header = (byte *)e_malloc(baseheader->size);
*address++ = 0x7d;
SetWord(address, header->kapselheadersize);
address += 4;
SetWord(address, header->filesize);
address += 4;
SetWord(address, 0);
}
#endif
baseheader->next = (HEADERLINK *)NULL;
return FALSE;
}
/*
* level0w --- write level-0 header
*/
static bool
level0w(baseheader, header)
HEADERLINK *baseheader;
HEADER *header;
{
register byte *address;
/* check path length */
if((uint)header->pathlen > (uint)233) /* 0xff - 0x16 */
return TRUE;
address = HDRnamelen(baseheader->header);
*address++ = 0xff & (uint)header->pathlen;
strcpy(address, header->pathname);
convdelim(address, '\\');
baseheader->size = header->headersize = *HDRsize(baseheader->header) =
0x16 + (uint)header->pathlen;
baseheader->size += 2;
address += (uint)header->pathlen;
*HDRattribute(baseheader->header) = (byte)(0xff & (uint)header->attr);
header->dostime.s = *unix2dos(header->mtime);
SetWord(HDRmtime(baseheader->header), header->dostime.u);
SetHWord(address, header->filecrc);
return FALSE;
}
/*
* level1w --- write level-1 header
*/
static bool
level1w(baseheader, header)
HEADERLINK *baseheader;
HEADER *header;
{
register byte *address;
register HEADERLINK *tsize = baseheader;
/* check path length */
address = HDRnamelen(baseheader->header);
if((uint)header->namelen > (uint)230) /* 0xff - 0x19 */
{
/* use extend header */
*address++ = 0;
header->needfname = TRUE;
}
else
{
strcpy(address + 1, header->filename);
*address++ = 0xff & (uint)header->namelen;
}
baseheader->size = *HDRsize(baseheader->header) =
0x19 + (uint)header->namelen;
address += (uint)header->namelen;
header->dostime.s = *unix2dos(header->mtime);
SetWord(HDRmtime(baseheader->header), header->dostime.u);
SetHWord(address, header->filecrc);
*(address + 2) = CREATOR_OS2;
/* make extend header */
if(makeext(baseheader, header))
return TRUE;
if(baseheader->next)
SetHWord(address + 3, baseheader->next->size);
else
SetHWord(address + 3, 0);
/* calculate total header size */
baseheader->size += 2;
while(tsize = tsize->next)
{
header->headersize += tsize->size;
if(tsize->next)
SetHWord(tsize->header + tsize->size - 2, tsize->next->size);
}
return FALSE;
}
/*
* level2w --- write level-2 header
*/
static bool
level2w(baseheader, header)
HEADERLINK *baseheader;
HEADER *header;
{
register HEADERLINK *tsize = baseheader;
SetWord(HDRmtime(baseheader->header), header->mtime);
*HDRcreator(baseheader->header) = CREATOR_OS2;
SetHWord(HDRcrc(baseheader->header), header->filecrc);
/* make extend header */
header->needfname = TRUE;
if(makeext(baseheader, header))
return TRUE;
SetHWord(HDRnext(baseheader->header), baseheader->next->size);
/* calculate total header size */
baseheader->size = header->headersize = 0x1a; /* base header size */
while(tsize = tsize->next)
{
header->headersize += tsize->size;
if(tsize->next)
SetHWord(tsize->header + tsize->size - 2, tsize->next->size);
}
if(header->headersize & 0xffff0000)
return TRUE; /* excced 64K */
SetHWord(HDRsize2(baseheader->header), header->headersize);
return FALSE;
}
/*
* level3w --- write level-3 header
*/
static bool
level3w(baseheader, header)
HEADERLINK *baseheader;
HEADER *header;
{
register HEADERLINK *tsize = baseheader;
SetHWord(HDRsize2(baseheader->header), 0x0004);
SetWord(HDRmtime(baseheader->header), header->mtime);
*HDRcreator(baseheader->header) = CREATOR_OS2;
SetHWord(HDRcrc(baseheader->header), header->filecrc);
/* make extend header */
if(makeext3(baseheader, header))
return TRUE;
SetWord(HDRnext3(baseheader->header), baseheader->next->size);
/* calculate total header size */
baseheader->size = header->headersize = 0x20; /* base header size */
while(tsize = tsize->next)
header->headersize += tsize->size;
SetWord(HDRsize3(baseheader->header), header->headersize);
return FALSE;
}
/*
* makehdr --- make LHA header
*/
HEADERLINK *
makehdr(header)
HEADER *header;
{
static HEADERLINK baseheader;
static byte buffer[257];
static bool (*encodeheader[4])() = {level0w, level1w, level2w, level3w};
/* initialize */
baseheader.header = &buffer[0];
header->needfname = FALSE;
header->crcpos = FALSE;
/* common part */
memcpy(HDRmethod(baseheader.header), header->method, 5);
header->skip = header->packed;
header->headersize = 0;
SetWord(HDRpacked(baseheader.header), header->packed);
SetWord(HDRoriginal(baseheader.header), header->original);
*HDRattribute(baseheader.header) = 0x20;
*HDRlevel(baseheader.header) = 0xff & header->level;
if(header->level > (uint)3)
return (HEADERLINK *)NULL;
/* switch header level */
if((*encodeheader[header->level])(&baseheader, header))
return (HEADERLINK *)NULL;
return &baseheader;
}
/*
* writehdr --- write header to disk
*/
bool
writehdr(fp, baseheader, header)
FILE *fp;
HEADERLINK *baseheader;
HEADER *header;
{
header->dummy = 0xff;
header->currentpos = ftell(fp);
if(!(header->headersize & 0xff) && (header->level == 2))
{
header->dummy = 0x00;
header->headersize++;
SetHWord(HDRsize2(baseheader->header), header->headersize);
}
do
{
if(!fwrite(baseheader->header, baseheader->size, 1, fp))
return TRUE;
}
while(baseheader = baseheader->next);
if(!header->dummy)
if(!fwrite(&(header->dummy), 1, 1, fp))
return TRUE;
return FALSE;
}
/*
* copyhdr --- copy header
*/
bool
copyhdr(fps, fpd, header)
FILE *fps;
FILE *fpd;
HEADER *header;
{
off_t src = ftell(fps);
byte *buffer;
fseek(fps, src - header->offset, SEEK_SET);
header->currentpos = ftell(fpd);
buffer = (byte *)e_malloc(header->offset);
fread(buffer, 1, header->offset, fps);
fwrite(buffer, 1, header->offset, fpd);
free(buffer);
if(ftell(fps) != src)
{
fseek(fps, src, SEEK_SET);
return TRUE;
}
return FALSE;
}
/*
* adjusthdr --- adjust header
*/
bool
adjusthdr(fp, baseheader, header)
FILE *fp;
HEADERLINK *baseheader;
HEADER *header;
{
byte *address;
HEADERLINK *save = (HEADERLINK *)NULL, *prev;
hword hcrc;
off_t wcrcpos = 0;
off_t current = ftell(fp);
fseek(fp, header->currentpos, SEEK_SET);
if(header->level == 1)
{
header->skip = header->headersize + header->packed;
SetWord(HDRpacked(baseheader->header), header->skip);
}
else
SetWord(HDRpacked(baseheader->header), header->packed);
address = HDRnamelen(baseheader->header);
if((uint)header->level <= (uint)1)
address += (0xff & (uint)*address) + 1;
SetHWord(address, header->filecrc);
memcpy(HDRmethod(baseheader->header), header->method, 5);
if((uint)header->level <= (uint)1)
*HDRsum(baseheader->header) = calcsum(baseheader->header);
fwrite(baseheader->header, baseheader->size, 1, fp);
if(header->crcpos)
{
hcrc = calccrc(baseheader->header, baseheader->size, 0);
baseheader = baseheader->next;
do
{
hcrc = calccrc(baseheader->header, baseheader->size, hcrc);
prev = baseheader;
baseheader = baseheader->next;
if(*(prev->header) == 0x00) /* common header */
save = prev;
else
{
if(!save)
wcrcpos += prev->size;
free(prev);
}
}
while(baseheader);
if(!header->dummy)
hcrc = calccrc(&(header->dummy), 1, hcrc);
SetHWord(save->header + 1, hcrc);
fseek(fp, wcrcpos, SEEK_CUR);
fwrite(save->header, save->size, 1, fp);
free(save);
}
fseek(fp, current, SEEK_SET);
return TRUE;
}