/* 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 #include #include #include #include #define SFXFLAG "??Special Flag for unzipsfx hack ??" #ifdef QDOS # include # define ZMODE (X_OK|R_OK) # define rev_long(x) (x) # define XFLAG 0x4afb #else # define ZMODE (R_OK) # define getchid(p1) p1 # include 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; }