unzip/qdos/makesfx.c

256 lines
6.8 KiB
C

/*
Copyright (c) 1990-2000 Info-ZIP. All rights reserved.
See the accompanying file LICENSE, version 2000-Apr-09 or later
(the contents of which are also included in unzip.h) for terms of use.
If, for some reason, all these files are missing, the Info-ZIP license
also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
*/
/*
* makesfx - Makes a QDOS sfx zip file
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* created by Jonathan Hudson, 04/09/95
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#define SFXFLAG "??Special Flag for unzipsfx hack ??"
#ifdef QDOS
# include <qdos.h>
# define ZMODE (X_OK|R_OK)
# define rev_long(x) (x)
# define XFLAG 0x4afb
#else
# define ZMODE (R_OK)
# define getchid(p1) p1
# include <sys/stat.h>
long rev_long(long l);
# define XFLAG 0xfb4a
typedef struct
{
long id;
long dlen;
} NTC;
struct qdirect {
long d_length __attribute__ ((packed)); /* file length */
unsigned char d_access __attribute__ ((packed)); /* file access type */
unsigned char d_type __attribute__ ((packed)); /* file type */
long d_datalen __attribute__ ((packed)); /* data length */
long d_reserved __attribute__ ((packed));/* Unused */
short d_szname __attribute__ ((packed)); /* size of name */
char d_name[36] __attribute__ ((packed));/* name area */
long d_update __attribute__ ((packed)); /* last update */
long d_refdate __attribute__ ((packed));
long d_backup __attribute__ ((packed)); /* EOD */
} ;
int fs_headr (int fd, long t, struct qdirect *qs, short size)
{
NTC ntc;
int r = -1;
struct stat s;
fstat(fd, &s);
qs->d_length = s.st_size;
lseek(fd, -8, SEEK_END);
read(fd, &ntc, 8);
if(ntc.id == *(long *)"XTcc")
{
qs->d_datalen = ntc.dlen; /* This is big endian */
qs->d_type = 1;
r = 0;
}
lseek(fd, 0, 0);
return 42; /* why not ??? */
}
typedef unsigned char uch;
long rev_long (long l)
{
uch cc[4];
cc[0] = (uch)(l >> 24);
cc[1] = (uch)((l >> 16) & 0xff);
cc[2] = (uch)((l >> 8) & 0xff);
cc[3] = (uch)(l & 0xff);
return *(long *)cc;
}
#endif
#define RBUFSIZ 4096
void usage(void)
{
fputs("makesfx -o outfile -z zipfile -xunzipsfx -sstubfile\n", stderr);
exit(0);
}
int main (int ac, char **av)
{
int fd, fo;
static char local_sig[4] = "PK\003\004";
char *p, tmp[4];
short ok = 0;
char *of = NULL;
char *xf = NULL;
char *zf = NULL;
char *sf = NULL;
int c;
while((c = getopt(ac, av, "o:z:x:s:h")) != EOF)
{
switch(c)
{
case 'o':
of = optarg;
break;
case 'z':
zf = optarg;
break;
case 'x':
xf = optarg;
break;
case 's':
sf = optarg;
break;
case 'h':
usage();
break;
}
}
if(zf && xf && of && sf)
{
if((fd = open(zf, O_RDONLY)) > 0)
{
if((read(fd, tmp, 4) == 4))
{
if(*(long *)tmp == *(long *)local_sig)
{
ok = 1;
}
}
close(fd);
}
if(!ok)
{
fprintf(stderr,
"Huum, %s doesn't look like a ZIP file to me\n", zf);
exit(0);
}
if(strstr(xf, "unzipsfx"))
{
if(access(xf, ZMODE))
{
fprintf(stderr, "Sorry, don't like the look of %s\n", xf);
exit(0);
}
}
if((fo = open(of, O_CREAT|O_TRUNC|O_RDWR, 0666)) != -1)
{
struct qdirect sd,xd;
int n;
int dsoff = 0;
int nfoff = 0;
int zlen = 0;
if((fd = open(sf, O_RDONLY)) != -1)
{
if(fs_headr(getchid(fd), -1, &sd, sizeof(sd)) > 0)
{
unsigned short *q;
p = malloc(sd.d_length);
n = read(fd, p, sd.d_length);
for(q = (unsigned short *)p;
q != (unsigned short *)(p+sd.d_length); q++)
{
if(*q == XFLAG && *(q+1) == XFLAG)
{
dsoff = (int)q-(int)p;
break;
}
}
write(fo, p, n);
close(fd);
}
}
if(dsoff == 0)
{
puts("Fails");
exit(0);
}
if((fd = open(xf, O_RDONLY)) != -1)
{
char *q;
if(fs_headr(getchid(fd), -1, &xd, sizeof(xd)) > 0)
{
p = realloc(p, xd.d_length);
n = read(fd, p, xd.d_length);
{
for(q = p; q < p+xd.d_length ; q++)
{
if(*q == '?')
{
if(memcmp(q, SFXFLAG, sizeof(SFXFLAG)-1) == 0)
{
nfoff = (int)(q-p);
break;
}
}
}
}
write(fo, p, n);
close(fd);
if((fd = open(zf, O_RDONLY)) > 0)
{
p = realloc(p, RBUFSIZ);
while((n = read(fd, p, RBUFSIZ)) > 0)
{
write(fo, p, n);
zlen += n;
}
close(fd);
}
lseek(fo, dsoff+4, SEEK_SET);
n = rev_long((sd.d_length-dsoff));
write(fo, &n, sizeof(long));
n = rev_long(xd.d_length);
write(fo, &n, sizeof(long));
write(fo, &xd.d_datalen, sizeof(long));
n = rev_long(nfoff);
write(fo, &n, sizeof(long));
n = rev_long(zlen);
write(fo, &n, sizeof(long));
close(fo);
}
else
{
close(fd);
fputs("Can't read unzipsfx header", stderr);
exit(0);
}
}
free(p);
}
}
else
usage();
return 0;
}