1 /*
2   Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.
3 
4   See the accompanying file LICENSE, version 2000-Apr-09 or later
5   (the contents of which are also included in unzip.h) for terms of use.
6   If, for some reason, all these files are missing, the Info-ZIP license
7   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
8 */
9 /*
10  * makesfx - Makes a QDOS sfx zip file
11  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12  * created by Jonathan Hudson, 04/09/95
13  */
14 
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <unistd.h>
19 #include <fcntl.h>
20 
21 #define SFXFLAG "??Special Flag for unzipsfx hack  ??"
22 
23 #ifdef QDOS
24 # include <qdos.h>
25 # define ZMODE (X_OK|R_OK)
26 # define rev_long(x) (x)
27 # define XFLAG 0x4afb
28 #else
29 # define ZMODE (R_OK)
30 # define getchid(p1) p1
31 # include <sys/stat.h>
32   long rev_long(long l);
33 # define XFLAG 0xfb4a
34 
35 typedef struct
36 {
37     long id;
38     long dlen;
39 } NTC;
40 
41 struct qdirect  {
42     long            d_length __attribute__ ((packed));  /* file length */
43     unsigned char   d_access __attribute__ ((packed));  /* file access type */
44     unsigned char   d_type __attribute__ ((packed));    /* file type */
45     long            d_datalen __attribute__ ((packed)); /* data length */
46     long            d_reserved __attribute__ ((packed));/* Unused */
47     short           d_szname __attribute__ ((packed));  /* size of name */
48     char            d_name[36] __attribute__ ((packed));/* name area */
49     long            d_update __attribute__ ((packed));  /* last update */
50     long            d_refdate __attribute__ ((packed));
51     long            d_backup __attribute__ ((packed));   /* EOD */
52 } ;
53 
fs_headr(int fd,long t,struct qdirect * qs,short size)54 int fs_headr (int fd, long t, struct qdirect *qs, short size)
55 {
56     NTC ntc;
57     int r = -1;
58     struct stat s;
59 
60     fstat(fd, &s);
61     qs->d_length = s.st_size;
62     lseek(fd, -8, SEEK_END);
63     read(fd, &ntc, 8);
64     if(ntc.id == *(long *)"XTcc")
65     {
66         qs->d_datalen = ntc.dlen;    /* This is big endian */
67         qs->d_type = 1;
68         r = 0;
69     }
70     lseek(fd, 0, 0);
71     return 42;                       /* why not ??? */
72 }
73 
74 typedef unsigned char uch;
75 
rev_long(long l)76 long rev_long (long l)
77 {
78     uch cc[4];
79     cc[0] = (uch)(l >> 24);
80     cc[1] = (uch)((l >> 16) & 0xff);
81     cc[2] = (uch)((l >> 8) & 0xff);
82     cc[3] = (uch)(l & 0xff);
83     return *(long *)cc;
84 }
85 
86 #endif
87 
88 #define RBUFSIZ 4096
89 
usage(void)90 void usage(void)
91 {
92     fputs("makesfx -o outfile -z zipfile -xunzipsfx -sstubfile\n", stderr);
93     exit(0);
94 }
95 
main(int ac,char ** av)96 int main (int ac, char **av)
97 {
98     int fd, fo;
99     static char local_sig[4] = "PK\003\004";
100     char *p, tmp[4];
101     short ok = 0;
102     char *of = NULL;
103     char *xf = NULL;
104     char *zf = NULL;
105     char *sf = NULL;
106     int c;
107 
108     while((c = getopt(ac, av, "o:z:x:s:h")) != EOF)
109     {
110         switch(c)
111         {
112             case 'o':
113                 of = optarg;
114                 break;
115             case 'z':
116                 zf = optarg;
117                 break;
118             case 'x':
119                 xf = optarg;
120                 break;
121             case 's':
122                 sf = optarg;
123                 break;
124             case 'h':
125                 usage();
126                 break;
127         }
128     }
129 
130 
131     if(zf && xf && of && sf)
132     {
133         if((fd = open(zf, O_RDONLY)) > 0)
134         {
135             if((read(fd, tmp, 4) == 4))
136             {
137                 if(*(long *)tmp == *(long *)local_sig)
138                 {
139                     ok = 1;
140                 }
141             }
142             close(fd);
143         }
144         if(!ok)
145         {
146             fprintf(stderr,
147                     "Huum, %s doesn't look like a ZIP file to me\n", zf);
148             exit(0);
149         }
150 
151         if(strstr(xf, "unzipsfx"))
152         {
153             if(access(xf, ZMODE))
154             {
155                 fprintf(stderr, "Sorry, don't like the look of %s\n", xf);
156                 exit(0);
157             }
158         }
159 
160         if((fo = open(of, O_CREAT|O_TRUNC|O_RDWR, 0666)) != -1)
161         {
162             struct qdirect sd,xd;
163             int n;
164             int dsoff = 0;
165             int nfoff = 0;
166             int zlen = 0;
167 
168             if((fd = open(sf, O_RDONLY)) != -1)
169             {
170                 if(fs_headr(getchid(fd), -1, &sd, sizeof(sd)) > 0)
171                 {
172                     unsigned short *q;
173                     p = malloc(sd.d_length);
174                     n = read(fd, p, sd.d_length);
175                     for(q = (unsigned short *)p;
176                         q != (unsigned short *)(p+sd.d_length); q++)
177                     {
178                         if(*q == XFLAG && *(q+1) == XFLAG)
179                         {
180                             dsoff = (int)q-(int)p;
181                             break;
182                         }
183                     }
184                     write(fo, p, n);
185                     close(fd);
186                 }
187             }
188 
189             if(dsoff == 0)
190             {
191                 puts("Fails");
192 
193                 exit(0);
194             }
195 
196             if((fd = open(xf, O_RDONLY)) != -1)
197             {
198                 char *q;
199                 if(fs_headr(getchid(fd), -1, &xd, sizeof(xd)) > 0)
200                 {
201                     p = realloc(p, xd.d_length);
202                     n = read(fd, p, xd.d_length);
203                     {
204                         for(q = p; q < p+xd.d_length ; q++)
205                         {
206                             if(*q == '?')
207                             {
208                                 if(memcmp(q, SFXFLAG, sizeof(SFXFLAG)-1) == 0)
209                                 {
210                                     nfoff = (int)(q-p);
211                                     break;
212                                 }
213                             }
214                         }
215                     }
216                     write(fo, p, n);
217                     close(fd);
218 
219                     if((fd = open(zf, O_RDONLY)) > 0)
220                     {
221                         p = realloc(p, RBUFSIZ);
222                         while((n = read(fd, p, RBUFSIZ)) > 0)
223                         {
224                             write(fo, p, n);
225                             zlen += n;
226                         }
227                         close(fd);
228                     }
229                     lseek(fo, dsoff+4, SEEK_SET);
230                     n = rev_long((sd.d_length-dsoff));
231                     write(fo, &n, sizeof(long));
232                     n = rev_long(xd.d_length);
233                     write(fo, &n, sizeof(long));
234                     write(fo, &xd.d_datalen, sizeof(long));
235                     n = rev_long(nfoff);
236                     write(fo, &n, sizeof(long));
237                     n = rev_long(zlen);
238                     write(fo, &n, sizeof(long));
239                     close(fo);
240                 }
241                 else
242                 {
243                     close(fd);
244                     fputs("Can't read unzipsfx header", stderr);
245                     exit(0);
246                 }
247             }
248             free(p);
249         }
250     }
251     else
252         usage();
253 
254     return 0;
255 }
256