home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************
- 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);
- }
-