small fixes
[swftools.git] / installer / mkarchive.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <unistd.h>
4 #include <sys/stat.h>
5 #include <fcntl.h>
6 #include <memory.h>
7 #include <zlib.h>
8 #define ZLIB_BUFFER_SIZE 16384
9
10 typedef struct _writer
11 {
12     int (*write)(struct _writer*, void*data, int len);
13     void (*finish)(struct _writer*);
14     void *internal;
15 } writer_t;
16
17 /* ---------------------------- file writer ------------------------------- */
18
19 typedef struct
20 {
21     FILE*fi;
22 } filewrite_t;
23 static int writer_filewrite_write(writer_t*w, void* data, int len) 
24 {
25     filewrite_t * fw= (filewrite_t*)w->internal;
26     return fwrite(data, len, 1, fw->fi);
27 }
28 static void writer_filewrite_finish(writer_t*w)
29 {
30     filewrite_t *mr = (filewrite_t*)w->internal;
31     fclose(mr->fi);
32     free(w->internal);
33     memset(w, 0, sizeof(writer_t));
34 }
35 writer_t*writer_init_filewriter(char*filename)
36 {
37     writer_t*w = malloc(sizeof(writer_t));
38     FILE*fi = fopen(filename, "wb");
39     filewrite_t *mr = (filewrite_t *)malloc(sizeof(filewrite_t));
40     mr->fi = fi;
41     memset(w, 0, sizeof(writer_t));
42     w->write = writer_filewrite_write;
43     w->finish = writer_filewrite_finish;
44     w->internal = mr;
45     return w;
46 }
47
48 /* ---------------------------- include file filter ------------------------------- */
49
50 typedef struct _ifwrite
51 {
52     FILE*fi;
53     int bp;
54     int pos;
55     int last;
56     char buf[1024];
57     char*filename;
58 } ifwrite_t;
59
60 static int writer_ifwrite_write(writer_t*out, void*data, int len)
61 {
62     ifwrite_t*i = (ifwrite_t*)out->internal;
63     FILE*fo = i->fi;
64     int t;
65     for(t=0;t<len;t++) {
66         unsigned char c = ((unsigned char*)data)[t];
67         if(i->bp>=80) {
68             fprintf(fo, "\"%s\"\n", i->buf);
69             i->bp = 0;
70         }
71         if(c<=32 || c>0x7e || c=='"' || c == '\\' || c == '%'
72         || (i->last && c>='0' && c<='9') 
73         || (i->last && c>='a' && c<='f')
74         || (i->last && c>='A' && c<='F')
75         ) {
76             i->bp += sprintf(i->buf+i->bp, "\\x%x",c);
77             i->last = 1;
78         } else {
79             i->buf[i->bp] = c;
80             i->buf[i->bp+1] = 0;
81             i->last = 0;
82             i->bp++;
83         }
84         i->pos++;
85     }
86 }
87 static void writer_ifwrite_finish(writer_t*w)
88 {
89     ifwrite_t *i= (ifwrite_t*)w->internal;
90     fprintf(i->fi, "\"%s\"\n", i->buf);
91     fprintf(i->fi, ";\n");
92     fprintf(i->fi, "int crndata_len = %d;\n", i->pos);
93     fclose(i->fi);
94     printf("wrote file %s\n", i->filename);
95     free(w->internal);w->internal = 0;
96 }
97
98 writer_t*writer_init_includewriter(char*filename)
99 {
100     writer_t*w = malloc(sizeof(writer_t));
101     FILE*fi = fopen(filename, "wb");
102     memset(w, 0, sizeof(writer_t));
103     w->write = writer_ifwrite_write;
104     w->finish = writer_ifwrite_finish;
105     ifwrite_t*i = (ifwrite_t *)malloc(sizeof(ifwrite_t));
106     i->fi = fi;
107     i->pos = 0;
108     i->bp=0;
109     i->last = 0;
110     i->filename = filename;
111     w->internal = i;
112     
113     fprintf(i->fi, "char* crndata =\n");
114     return w;
115
116 }
117
118 /* ---------------------------- zlibdeflate writer -------------------------- */
119
120 struct zlibdeflate_t
121 {
122     z_stream zs;
123     writer_t*output;
124     int written;
125     int zwritten;
126     unsigned char writebuffer[ZLIB_BUFFER_SIZE];
127 };
128
129 static void zlib_error(int ret, char* msg, z_stream*zs)
130 {
131     fprintf(stderr, "%s: zlib error (%d): last zlib error: %s\n",
132           msg,
133           ret,
134           zs->msg?zs->msg:"unknown");
135     perror("errno:");
136     exit(1);
137 }
138
139 static int writer_zlibdeflate_write(writer_t*writer, void* data, int len) 
140 {
141     struct zlibdeflate_t*z = (struct zlibdeflate_t*)writer->internal;
142     int ret;
143
144     if(!z) {
145         fprintf(stderr, "zlib not initialized!\n");
146         return 0;
147     }
148     if(!len)
149         return 0;
150     
151     z->zs.next_in = (Bytef *)data;
152     z->zs.avail_in = len;
153
154     while(1) {
155         ret = deflate(&z->zs, Z_NO_FLUSH);
156         
157         if (ret != Z_OK) zlib_error(ret, "bitio:deflate_deflate", &z->zs);
158
159         if(z->zs.next_out != z->writebuffer) {
160             z->zwritten += z->zs.next_out - (Bytef*)z->writebuffer;
161             z->output->write(z->output, z->writebuffer, z->zs.next_out - (Bytef*)z->writebuffer);
162             z->zs.next_out = z->writebuffer;
163             z->zs.avail_out = ZLIB_BUFFER_SIZE;
164         }
165
166         if(!z->zs.avail_in) {
167             break;
168         }
169     }
170     z->written += len;
171     return len;
172 }
173 static void writer_zlibdeflate_finish(writer_t*writer)
174 {
175     struct zlibdeflate_t*z = (struct zlibdeflate_t*)writer->internal;
176     writer_t*output;
177     int ret;
178     if(!z)
179         return;
180     output= z->output;
181     while(1) {
182         ret = deflate(&z->zs, Z_FINISH);
183         if (ret != Z_OK &&
184             ret != Z_STREAM_END) zlib_error(ret, "bitio:deflate_finish", &z->zs);
185
186         if(z->zs.next_out != z->writebuffer) {
187             z->zwritten += z->zs.next_out - (Bytef*)z->writebuffer;
188             z->output->write(z->output, z->writebuffer, z->zs.next_out - (Bytef*)z->writebuffer);
189             z->zs.next_out = z->writebuffer;
190             z->zs.avail_out = ZLIB_BUFFER_SIZE;
191         }
192
193         if (ret == Z_STREAM_END) {
194             break;
195
196         }
197     }
198     ret = deflateEnd(&z->zs);
199     if (ret != Z_OK) zlib_error(ret, "bitio:deflate_end", &z->zs);
200
201     if(z->written) {
202         printf("Compression ratio: %.2f%% (%d bytes of input data, %d bytes of output data)\n", 
203                 z->zwritten*100.0 / z->written,
204                 z->written, z->zwritten);
205     } else {
206         printf("Compression ratio: 0%% (0 bytes of input data, %d bytes of output data)\n", z->zwritten);
207     }
208
209     free(writer->internal);
210     memset(writer, 0, sizeof(writer_t));
211     output->finish(output); 
212 }
213 writer_t*writer_init_zwriter(writer_t*output)
214 {
215     writer_t*w = malloc(sizeof(writer_t));
216     struct zlibdeflate_t*z;
217     int ret;
218     memset(w, 0, sizeof(writer_t));
219     z = (struct zlibdeflate_t*)malloc(sizeof(struct zlibdeflate_t));
220     memset(z, 0, sizeof(struct zlibdeflate_t));
221     w->internal = z;
222     w->write = writer_zlibdeflate_write;
223     w->finish = writer_zlibdeflate_finish;
224     z->output = output;
225     memset(&z->zs,0,sizeof(z_stream));
226     z->zs.zalloc = Z_NULL;
227     z->zs.zfree  = Z_NULL;
228     z->zs.opaque = Z_NULL;
229     ret = deflateInit(&z->zs, 9);
230     if (ret != Z_OK) zlib_error(ret, "bitio:deflate_init", &z->zs);
231     z->zs.next_out = z->writebuffer;
232     z->zs.avail_out = ZLIB_BUFFER_SIZE;
233     z->written = 0;
234     z->zwritten = 0;
235     return w;
236 }
237
238 /* ------------------------------- main ----------- ------------------------------- */
239
240 static int compare_filenames(const void*_n1, const void*_n2)
241 {
242     const char*s1 = *(const char**)_n1;
243     const char*s2 = *(const char**)_n2;
244
245     char*e1 = strrchr(s1, '.');
246     char*e2 = strrchr(s2, '.');
247     if(!e1 && !e2)
248         return 0;
249     if(e1 && !e2)
250         return 1;
251     if(!e1 && e2)
252         return -1;
253     int c = strcasecmp(e1+1,e2+1);
254     if(c)
255         return c;
256     return strcasecmp(s1,s2);
257 }
258
259 int main (int argn, char*argv[])
260 {
261     int t;
262     char buf[320];
263     int num = 0;
264
265     int fullsize = 0;
266     for(t=1;t<argn;t++)
267     {
268         if(argv[t][0]!='-')
269         {
270             FILE*fi=fopen(argv[t],"rb");
271             if(fi) {
272                 fseek(fi,0,SEEK_END);
273                 long l=ftell(fi);
274                 fclose(fi);
275                 fullsize += l;
276                 num++;
277             }
278         }
279     }
280
281
282 #ifdef ZLIB
283     writer_t*include_writer = writer_init_includewriter("crnfiles.c");
284     writer_t*zwriter = writer_init_zwriter(include_writer);
285 #else //LZMA
286     unlink("crnfiles.dat");
287     unlink("crnfiles.7z");
288     unlink("crnfiles.c");
289     writer_t*zwriter = writer_init_filewriter("crnfiles.dat");
290 #endif
291     unsigned char n1=num;
292     unsigned char n2=num>>8;
293     unsigned char n3=num>>16;
294     unsigned char n4=num>>24;
295     zwriter->write(zwriter,&n1,1);
296     zwriter->write(zwriter,&n2,1);
297     zwriter->write(zwriter,&n3,1);
298     zwriter->write(zwriter,&n4,1);
299
300     qsort(argv+1, argn-1, sizeof(argv[0]), compare_filenames);
301
302     for(t=1;t<argn;t++)
303     {
304             if(argv[t][0]!='-')
305             {
306                     FILE*fi=fopen(argv[t],"rb");
307                     if(fi)
308                     {
309                             fseek(fi,0,SEEK_END);
310                             long l=ftell(fi);
311                             fseek(fi,0,SEEK_SET);
312
313                             char*buf=(char*)malloc(l);
314                             char*id="NUL";
315                             struct stat st;
316                             fstat(fileno(fi),&st);
317                             if(S_ISDIR(st.st_mode)) {id ="DIR";l=0;}
318                             else if(strstr(argv[t],".swf")) id="SWF";
319                             else if(strstr(argv[t],".gif")) id="PIC";
320                             else if(strstr(argv[t],".png")) id="PIC";
321                             else if(strstr(argv[t],".jpeg")) id="PIC";
322                             else if(strstr(argv[t],".jpg")) id="PIC";
323                             else if(strstr(argv[t],".tif")) id="PIC";
324                             else if(strstr(argv[t],".c")) id="SRC";
325                             else if(strstr(argv[t],".cc")) id="SRC";
326                             else if(strstr(argv[t],".cpp")) id="SRC";
327                             else if(strstr(argv[t],".h")) id="SRC";
328                             else if(strstr(argv[t],".class")) id="CLA";
329                             else if(strstr(argv[t],".java")) id="SRC";
330                             else if(strstr(argv[t],".exe")) id="EXE";
331                             else if(strstr(argv[t],".ttf")) id="FON";
332                             else if(strstr(argv[t],".pfa")) id="FON";
333                             else if(strstr(argv[t],".pfb")) id="FON";
334                             else if(strstr(argv[t],".afm")) id="FON";
335                             else if(strstr(argv[t],".1")) id="DOC";
336                             else if(strstr(argv[t],".doc")) id="DOC";
337                             else if(strstr(argv[t],".hlp")) id="DOC";
338                             else if(strstr(argv[t],".dll")) id="DLL";
339
340                             fread(buf,l,1,fi);
341                             zwriter->write(zwriter,id,3);
342                             unsigned char b1=l;
343                             unsigned char b2=l>>8;
344                             unsigned char b3=l>>16;
345                             unsigned char b4=l>>24;
346                             zwriter->write(zwriter,&b1,1);
347                             zwriter->write(zwriter,&b2,1);
348                             zwriter->write(zwriter,&b3,1);
349                             zwriter->write(zwriter,&b4,1);
350                             int sl=strlen(argv[t]);
351                             if(sl>255) {
352                                 fprintf(stderr, "Error: filename %s too long\n", argv[t]);
353                             }
354                             unsigned char b = sl;
355                             zwriter->write(zwriter,&b,1); //write filename len
356                             zwriter->write(zwriter,argv[t],sl); //write filename
357                             zwriter->write(zwriter,buf,l); //write data
358                             fprintf(stderr,"[%s] %s: %d bytes written.\n", id, argv[t], l);
359                             fclose(fi);
360                             free(buf);
361                     }
362                     else
363                     {
364                             fprintf(stderr,"%s not found.\n", argv[t]);
365                     }
366             }
367     }
368     char*id_end = "END";
369     zwriter->write(zwriter,id_end,3);
370     zwriter->finish(zwriter);
371
372 #ifndef ZLIB
373     if(system("do_lzma e crnfiles.dat crnfiles.7z")&0xff00) {
374         perror("do_lzma");
375         exit(1);
376     }
377     FILE*fi = fopen("crnfiles.7z", "rb");
378     if(!fi) {
379         perror("crnfiles.7z");
380         exit(1);
381     }
382     writer_t*w = writer_init_includewriter("crnfiles.c");
383     while(!feof(fi)) {
384         char buf[4096];
385         int len = fread(buf,1,4096,fi);
386         if(!len)
387             break;
388         w->write(w, buf, len);
389     }
390     w->finish(w);
391     fclose(fi);
392     if(unlink("crnfiles.dat")) {
393         perror("crnfiles.dat");
394         exit(1);
395     }
396     if(unlink("crnfiles.7z")) {
397         perror("crnfiles.7z");
398         exit(1);
399     }
400 #endif
401
402     fi = fopen("crnfiles.c", "ab+");
403     fprintf(fi, "\nint crn_decompressed_size=%d;\n", fullsize);
404     fclose(fi);
405
406     return 0;
407 }
408