home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World 1997 November
/
PCWorld_1997-11_cd.bin
/
software
/
sharware
/
utility
/
PACKERS
/
LZH
/
LHASRC.EXE
/
HEADER.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-02-13
|
9KB
|
393 lines
/***********************************************************
header.c -- handle headers
***********************************************************/
#define MSDOS
#define MYDOS 'M'
#include <stdio.h>
#include <io.h>
#include <dos.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include "lh.h"
#include "intrface.h"
#include "errmes.h"
#define HDRwork (uchar *)(work + 0)
#define HDRsize (uchar *)(work + 0)
#define HDRwhole (uchar *)(work + 0)
#define HDRsum (uchar *)(work + 1)
#define HDRmethod (uchar *)(work + 2)
#define HDRpacked (uchar *)(work + 7)
#define HDRoriginal (uchar *)(work + 11)
#define HDRtime (uchar *)(work + 15)
#define HDRattr (uchar *)(work + 19)
#define HDRlevel (uchar *)(work + 20)
#define HDRfnlen (uchar *)(work + 21)
#define HDRfname (uchar *)(work + 22)
#define HDRdos (uchar *)(work + 23)
#define HDRextsize (uchar *)(work + 24)
struct head hpb;
char methodID[6] = "\0\0\0\0\0\0";
static ulong nextpos;
#ifdef MSDOS
#define Convint(p) (*(int *)(p))
#define Convlong(p) (*(long *)(p))
#else
#define Convint(p) (*(p) + ((unsigned)*((p) + 1) << 8))
#define Convlong(p) (Convint(p) + ((ulong)Convint((p) + 2) << 16))
#endif
#ifdef MSDOS
#define Setint(p, q) (*(uint *)(p)=q)
#define Setlong(p, q) (*(ulong *)(p)=q)
#else
#define Setint(p, q) {uint a = q; (p)[0] = a; (p)[1] = a >> 8;}
#define Setlong(p, q) {ulong a = q; \
(p)[0] = a; (p)[1] = a >> 8; \
(p)[2] = a >> 16; (p)[3] = a >> 24;}
#define MAXNAMELEN 128
#endif
ulong inithdr(void)
{
long pos;
int c, err;
char *p;
pos = 0;
while ((c = getc(file1)) >= 0) {
pos++;
if (c == '-') {
getc(file1); getc(file1); getc(file1);
if (getc(file1) == '-') {
nextpos = pos - 3;
p = gethdr(&err);
if (p) {
free(p);
nextpos = pos - 3;
return nextpos;
}
}
fseek(file1, pos, SEEK_SET);
}
}
nextpos = pos;
return nextpos;
}
/*******************************
calculate check-sum of header
*******************************/
static char calcsum(void *h)
{
char *p, *q, i;
p = (char *)h + 2;
q = p + *(uchar *)h;
for (i = 0; p < q; p++)
i += *p;
return i;
}
static void extheader(char *exthdr, int size)
{
uchar *p;
p = exthdr + 1;
switch (*exthdr) {
case 0:
hpb.headcrc = Convint(p);
hpb.crcpos = p;
if (size > 5)
hpb.info = *(p + 2);
break;
case 1:
hpb.filename = p;
hpb.filenlen = size - 3;
break;
case 2:
hpb.pathname = p;
hpb.dirnlen = size - 3;
break;
case 0x40:
if (hpb.dos == MYDOS) {
hpb.attr = Convint(p);
}
break;
}
}
#define readarc(a,b) fread(a, 1, b, file1)
char *gethdr(int *err)
/***
*err = 0 : normal end of header
= 1 : not a header
****/
{
char *p;
int namelen, extsize;
int i;
*err = 0;
hpb.crcpos = NULL;
*HDRsize = *HDRlevel = 0;
fseek(file1, nextpos, SEEK_SET);
if (readarc(HDRwork, 21) != 21 || *HDRsize == 0) return NULL;
hpb.headersize = (int)*HDRsize + 2;
strncpy(hpb.method, HDRmethod, 5);
hpb.packed = hpb.skip = Convlong(HDRpacked);
hpb.original = Convlong(HDRoriginal);
hpb.level = *HDRlevel;
hpb.attr = *HDRattr;
hpb.dirnlen = 0;
switch(hpb.level) {
case 0:
case 1:
hpb.dostime.u = Convlong(HDRtime);
hpb.utc = dos2unix(&hpb.dostime.s);
if (hpb.headersize < 22) return NULL;
readarc(HDRwork + 21, hpb.headersize - 21);
if (calcsum(HDRwork) != *HDRsum) {
if (*HDRwork == 0x1a) return NULL; /* for LArc & XMODEM */
*err = 1;
return NULL;
}
namelen = *HDRfnlen;
hpb.filenlen = namelen;
hpb.filename = hpb.pathname = HDRfname;
i = hpb.headersize - namelen;
if (i >= 24) {
hpb.filecrc = Convint(HDRfname + namelen);
} else {
hpb.level = -1;
}
if (i >= 25) {
hpb.dos = *(HDRfname + namelen + 2);
}
nextpos = ftell(file1) + hpb.skip;
if (hpb.level <= 0) {
strncpy(hpb.pathname = e_malloc(namelen + 1), HDRfname, namelen);
hpb.pathname[namelen] = '\0';
hpb.filename = convdelim(hpb.pathname, DELIM);
return hpb.pathname;
}
p = HDRwork + *HDRsize;
while ((extsize = Convint(p)) != 0) {
readarc(p + 2, extsize);
extheader(p + 2, extsize);
p += extsize;
}
i = p + 2 - HDRwork;
hpb.packed -= i - hpb.headersize;
hpb.headersize = i;
break;
case 2:
readarc(HDRwork + 21, (hpb.headersize = Convint(HDRwhole)) - 21);
hpb.utc = Convlong(HDRtime);
hpb.dos = *HDRdos;
p = HDRextsize;
while ((extsize = Convint(p)) != 0) {
extheader(p + 2, extsize);
p += extsize;
}
hpb.filecrc = Convint(HDRfnlen);
nextpos = ftell(file1) + hpb.skip;
if (hpb.crcpos == NULL) {
*err = 1;
return NULL;
}
break;
default:
if (*HDRsize != 0x1a) *err = 1;
return NULL;
}
if (hpb.crcpos) {
Setint(hpb.crcpos, 0);
crc = 0;
if (calccrc(HDRwork, hpb.headersize) != hpb.headcrc) {
*err = 1;
return NULL;
}
Setint(hpb.crcpos, hpb.headcrc);
}
namelen = hpb.dirnlen + hpb.filenlen;
p = e_malloc(namelen + 1);
hpb.pathname = strncpy(p, hpb.pathname, hpb.dirnlen);
hpb.filename = strncpy(p + hpb.dirnlen, hpb.filename, hpb.filenlen);
*(p + namelen) = '\0';
convdelim(hpb.pathname, DELIM);
return hpb.pathname;
}
void makehdr(void)
{
int namelen;
uchar *p, *q;
hpb.crcpos = NULL;
memcpy(HDRmethod, hpb.method, 5);
Setlong(HDRpacked, hpb.skip = hpb.packed);
Setlong(HDRoriginal, hpb.original);
*HDRattr = 0x20;
*HDRlevel = hpb.level;
q = hpb.filename;
if (hpb.level == 0) q = hpb.pathname;
namelen = strlen(q);
p = HDRfnlen;
if (hpb.level != 2) {
#ifndef MSDOS
if (namelen > MAXNAMELEN) {
*p++ = 0;
} else
#endif
{
*p++ = namelen;
strcpy(p, q);
if (hpb.level == 0) convdelim(p, pathdelim);
p += namelen;
}
hpb.dostime.s = *unix2dos(hpb.utc);
Setlong(HDRtime, hpb.dostime.u);
} else {
Setlong(HDRtime, hpb.utc);
}
Setint(p, hpb.filecrc); /* filecrc (for SFX) */
p += 2;
if (hpb.level == 0) {
*HDRsize = p - HDRmethod;
hpb.headersize = p - HDRwork;
*HDRattr = hpb.attr;
*HDRsum = calcsum(HDRwork);
return;
}
*p = MYDOS; p++;
*HDRsize = p - HDRwork;
/*
| filename header |
| 2 ext-header size |
|----------------------|
| 1 0x01 |
| ? filename |
|----------------------|
*/
if (hpb.level == 2
#ifndef MSDOS
|| namelen > MAXNAMELEN
#endif
) {
hpb.filenlen = strlen(hpb.filename);
Setint(p, hpb.filenlen + 3); p += 2;
*p++ = 1;
memcpy(p, hpb.filename, hpb.filenlen); p += hpb.filenlen;
}
/*
| dirname header |
| 2 ext-header size |
|----------------------|
| 1 0x02 |
| ? dirname |
|----------------------|
*/
if (hpb.pathname != hpb.filename) {
hpb.dirnlen = hpb.filename - hpb.pathname;
Setint(p, hpb.dirnlen + 3); p += 2;
*p++ = 2;
convdelim(hpb.pathname, DELIM2);
memcpy(p, hpb.pathname, hpb.dirnlen); p += hpb.dirnlen;
convdelim(hpb.pathname, DELIM);
}
#ifdef MSDOS
/*
| attribute header |
| 2 ext-header size |
|----------------------|
| 1 0x40 |
| 2 attribute |
|----------------------|
*/
if (hpb.attr != 0x20) {
Setint(p, 5); p += 2;
*p++ = 0x40; /* ext-header type */
Setint(p, hpb.attr); p += 2;
}
#endif
/*
| common header |
| 2 ext-header size |
|----------------------|
| 1 0x00 |
| 2 header crc |
| ( 1 information ) |
|----------------------|
*/
if (p != HDRwork + *HDRsize || hpb.info) {
q = p; p += 2;
*p++ = 0; /* ext-header type */
hpb.crcpos = p;
Setint(p, 0); p += 2; /* dummy crc */
if (hpb.info) {
*p++ = hpb.info;
}
Setint(q, p - q);
}
/* ext-header end */
Setint(p, 0); p += 2;
hpb.headersize = p - HDRwork;
if (hpb.level == 2) {
if ((hpb.headersize & 0xff) == 0) {
hpb.headersize++;
*p = '\0';
}
Setint(HDRsize, hpb.headersize);
}
}
void writehdr(void)
{
hpb.currentpos = ftell(file2);
if (fwrite(HDRwork, hpb.headersize, 1, file2) == 0)
error(WTERR, filename2);
}
void adjusthdr(void)
{
long lastpos;
uchar *p;
lastpos = ftell(file2);
fseek(file2, hpb.currentpos, SEEK_SET);
if (hpb.level == 1) {
hpb.skip = hpb.headersize - *HDRsize - 2 + hpb.packed;
Setlong(HDRpacked, hpb.skip);
} else {
Setlong(HDRpacked, hpb.packed);
}
p = HDRfnlen;
if (hpb.level != 2) p += *p + 1;
Setint(p, hpb.filecrc);
memcpy(HDRmethod, hpb.method, 5);
if (hpb.level != 2) *HDRsum = calcsum(HDRwork);
if (hpb.crcpos) {
crc = 0;
Setint(hpb.crcpos, 0);
Setint(hpb.crcpos, calccrc(HDRwork, hpb.headersize));
}
fwrite(HDRwork, hpb.headersize, 1, file2);
fseek(file2, lastpos, SEEK_SET);
}