checked in xpdf sources
[swftools.git] / installer / mkarchive.c
blob7dab4e02afad8c0a4f2080caaaa88f10dddcc8a8
1 /* mkarchive.c
3 Part of the rfx installer (Main program).
5 Copyright (c) 2004-2008 Matthias Kramm <kramm@quiss.org>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <unistd.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <memory.h>
27 #include <zlib.h>
28 #define ZLIB_BUFFER_SIZE 16384
30 typedef struct _writer
32 int (*write)(struct _writer*, void*data, int len);
33 void (*finish)(struct _writer*);
34 void *internal;
35 } writer_t;
37 /* ---------------------------- file writer ------------------------------- */
39 typedef struct
41 FILE*fi;
42 } filewrite_t;
43 static int writer_filewrite_write(writer_t*w, void* data, int len)
45 filewrite_t * fw= (filewrite_t*)w->internal;
46 return fwrite(data, len, 1, fw->fi);
48 static void writer_filewrite_finish(writer_t*w)
50 filewrite_t *mr = (filewrite_t*)w->internal;
51 fclose(mr->fi);
52 free(w->internal);
53 memset(w, 0, sizeof(writer_t));
55 writer_t*writer_init_filewriter(char*filename)
57 writer_t*w = malloc(sizeof(writer_t));
58 FILE*fi = fopen(filename, "wb");
59 if(!fi) {
60 perror(filename);
61 return 0;
63 filewrite_t *mr = (filewrite_t *)malloc(sizeof(filewrite_t));
64 mr->fi = fi;
65 memset(w, 0, sizeof(writer_t));
66 w->write = writer_filewrite_write;
67 w->finish = writer_filewrite_finish;
68 w->internal = mr;
69 return w;
72 /* ---------------------------- include file filter ------------------------------- */
74 typedef struct _ifwrite
76 FILE*fi;
77 int bp;
78 int pos;
79 int last;
80 char buf[1024];
81 char*filename;
82 } ifwrite_t;
84 static int writer_ifwrite_write(writer_t*out, void*data, int len)
86 ifwrite_t*i = (ifwrite_t*)out->internal;
87 FILE*fo = i->fi;
88 int t;
89 for(t=0;t<len;t++) {
90 unsigned char c = ((unsigned char*)data)[t];
91 if(i->bp>=80) {
92 fprintf(fo, "\"%s\"\n", i->buf);
93 i->bp = 0;
95 if(c<=32 || c>0x7e || c=='"' || c == '\\' || c == '%'
96 || (i->last && c>='0' && c<='9')
97 || (i->last && c>='a' && c<='f')
98 || (i->last && c>='A' && c<='F')
99 ) {
100 i->bp += sprintf(i->buf+i->bp, "\\x%x",c);
101 i->last = 1;
102 } else {
103 i->buf[i->bp] = c;
104 i->buf[i->bp+1] = 0;
105 i->last = 0;
106 i->bp++;
108 i->pos++;
111 static void writer_ifwrite_finish(writer_t*w)
113 ifwrite_t *i= (ifwrite_t*)w->internal;
114 fprintf(i->fi, "\"%s\"\n", i->buf);
115 fprintf(i->fi, ";\n");
116 fprintf(i->fi, "int crndata_len = %d;\n", i->pos);
117 fclose(i->fi);
118 printf("wrote file %s\n", i->filename);
119 free(w->internal);w->internal = 0;
122 writer_t*writer_init_includewriter(char*filename)
124 writer_t*w = malloc(sizeof(writer_t));
125 FILE*fi = fopen(filename, "wb");
126 memset(w, 0, sizeof(writer_t));
127 w->write = writer_ifwrite_write;
128 w->finish = writer_ifwrite_finish;
129 ifwrite_t*i = (ifwrite_t *)malloc(sizeof(ifwrite_t));
130 i->fi = fi;
131 i->pos = 0;
132 i->bp=0;
133 i->last = 0;
134 i->filename = filename;
135 w->internal = i;
137 fprintf(i->fi, "char* crndata =\n");
138 return w;
142 /* ---------------------------- zlibdeflate writer -------------------------- */
144 struct zlibdeflate_t
146 z_stream zs;
147 writer_t*output;
148 int written;
149 int zwritten;
150 unsigned char writebuffer[ZLIB_BUFFER_SIZE];
153 static void zlib_error(int ret, char* msg, z_stream*zs)
155 fprintf(stderr, "%s: zlib error (%d): last zlib error: %s\n",
156 msg,
157 ret,
158 zs->msg?zs->msg:"unknown");
159 perror("errno:");
160 exit(1);
163 static int writer_zlibdeflate_write(writer_t*writer, void* data, int len)
165 struct zlibdeflate_t*z = (struct zlibdeflate_t*)writer->internal;
166 int ret;
168 if(!z) {
169 fprintf(stderr, "zlib not initialized!\n");
170 return 0;
172 if(!len)
173 return 0;
175 z->zs.next_in = (Bytef *)data;
176 z->zs.avail_in = len;
178 while(1) {
179 ret = deflate(&z->zs, Z_NO_FLUSH);
181 if (ret != Z_OK) zlib_error(ret, "bitio:deflate_deflate", &z->zs);
183 if(z->zs.next_out != z->writebuffer) {
184 z->zwritten += z->zs.next_out - (Bytef*)z->writebuffer;
185 z->output->write(z->output, z->writebuffer, z->zs.next_out - (Bytef*)z->writebuffer);
186 z->zs.next_out = z->writebuffer;
187 z->zs.avail_out = ZLIB_BUFFER_SIZE;
190 if(!z->zs.avail_in) {
191 break;
194 z->written += len;
195 return len;
197 static void writer_zlibdeflate_finish(writer_t*writer)
199 struct zlibdeflate_t*z = (struct zlibdeflate_t*)writer->internal;
200 writer_t*output;
201 int ret;
202 if(!z)
203 return;
204 output= z->output;
205 while(1) {
206 ret = deflate(&z->zs, Z_FINISH);
207 if (ret != Z_OK &&
208 ret != Z_STREAM_END) zlib_error(ret, "bitio:deflate_finish", &z->zs);
210 if(z->zs.next_out != z->writebuffer) {
211 z->zwritten += z->zs.next_out - (Bytef*)z->writebuffer;
212 z->output->write(z->output, z->writebuffer, z->zs.next_out - (Bytef*)z->writebuffer);
213 z->zs.next_out = z->writebuffer;
214 z->zs.avail_out = ZLIB_BUFFER_SIZE;
217 if (ret == Z_STREAM_END) {
218 break;
222 ret = deflateEnd(&z->zs);
223 if (ret != Z_OK) zlib_error(ret, "bitio:deflate_end", &z->zs);
225 if(z->written) {
226 printf("Compression ratio: %.2f%% (%d bytes of input data, %d bytes of output data)\n",
227 z->zwritten*100.0 / z->written,
228 z->written, z->zwritten);
229 } else {
230 printf("Compression ratio: 0%% (0 bytes of input data, %d bytes of output data)\n", z->zwritten);
233 free(writer->internal);
234 memset(writer, 0, sizeof(writer_t));
235 output->finish(output);
237 writer_t*writer_init_zwriter(writer_t*output)
239 writer_t*w = malloc(sizeof(writer_t));
240 struct zlibdeflate_t*z;
241 int ret;
242 memset(w, 0, sizeof(writer_t));
243 z = (struct zlibdeflate_t*)malloc(sizeof(struct zlibdeflate_t));
244 memset(z, 0, sizeof(struct zlibdeflate_t));
245 w->internal = z;
246 w->write = writer_zlibdeflate_write;
247 w->finish = writer_zlibdeflate_finish;
248 z->output = output;
249 memset(&z->zs,0,sizeof(z_stream));
250 z->zs.zalloc = Z_NULL;
251 z->zs.zfree = Z_NULL;
252 z->zs.opaque = Z_NULL;
253 ret = deflateInit(&z->zs, 9);
254 if (ret != Z_OK) zlib_error(ret, "bitio:deflate_init", &z->zs);
255 z->zs.next_out = z->writebuffer;
256 z->zs.avail_out = ZLIB_BUFFER_SIZE;
257 z->written = 0;
258 z->zwritten = 0;
259 return w;
262 /* ------------------------------- main ----------- ------------------------------- */
264 static int compare_filenames(const void*_n1, const void*_n2)
266 const char*s1 = *(const char**)_n1;
267 const char*s2 = *(const char**)_n2;
269 char*e1 = strrchr(s1, '.');
270 char*e2 = strrchr(s2, '.');
271 if(!e1 && !e2)
272 return 0;
273 if(e1 && !e2)
274 return 1;
275 if(!e1 && e2)
276 return -1;
277 int c = strcasecmp(e1+1,e2+1);
278 if(c)
279 return c;
280 return strcasecmp(s1,s2);
283 int main (int argn, char*argv[])
285 int t;
286 char buf[320];
287 int num = 0;
289 int fullsize = 0;
290 for(t=1;t<argn;t++)
292 if(argv[t][0]!='-')
294 FILE*fi=fopen(argv[t],"rb");
295 if(fi) {
296 fseek(fi,0,SEEK_END);
297 long l=ftell(fi);
298 fclose(fi);
299 fullsize += l;
300 num++;
306 #ifdef ZLIB
307 writer_t*include_writer = writer_init_includewriter("crnfiles.c");
308 writer_t*zwriter = writer_init_zwriter(include_writer);
309 #else //LZMA
310 unlink("crnfiles.dat");
311 unlink("crnfiles.7z");
312 unlink("crnfiles.c");
313 writer_t*zwriter = writer_init_filewriter("crnfiles.dat");
314 #endif
315 unsigned char n1=num;
316 unsigned char n2=num>>8;
317 unsigned char n3=num>>16;
318 unsigned char n4=num>>24;
319 zwriter->write(zwriter,&n1,1);
320 zwriter->write(zwriter,&n2,1);
321 zwriter->write(zwriter,&n3,1);
322 zwriter->write(zwriter,&n4,1);
324 qsort(argv+1, argn-1, sizeof(argv[0]), compare_filenames);
326 for(t=1;t<argn;t++)
328 if(argv[t][0]!='-')
330 FILE*fi=fopen(argv[t],"rb");
331 if(fi)
333 fseek(fi,0,SEEK_END);
334 long l=ftell(fi);
335 fseek(fi,0,SEEK_SET);
337 char*buf=(char*)malloc(l);
338 char*id="NUL";
339 struct stat st;
340 fstat(fileno(fi),&st);
341 if(S_ISDIR(st.st_mode)) {id ="DIR";l=0;}
342 else if(strstr(argv[t],".swf")) id="SWF";
343 else if(strstr(argv[t],".gif")) id="PIC";
344 else if(strstr(argv[t],".png")) id="PIC";
345 else if(strstr(argv[t],".jpeg")) id="PIC";
346 else if(strstr(argv[t],".jpg")) id="PIC";
347 else if(strstr(argv[t],".tif")) id="PIC";
348 else if(strstr(argv[t],".ico")) id="PIC";
349 else if(strstr(argv[t],".c")) id="SRC";
350 else if(strstr(argv[t],".cc")) id="SRC";
351 else if(strstr(argv[t],".cpp")) id="SRC";
352 else if(strstr(argv[t],".h")) id="SRC";
353 else if(strstr(argv[t],".class")) id="CLA";
354 else if(strstr(argv[t],".java")) id="SRC";
355 else if(strstr(argv[t],".exe")) id="EXE";
356 else if(strstr(argv[t],".ttf")) id="FON";
357 else if(strstr(argv[t],".pfa")) id="FON";
358 else if(strstr(argv[t],".pfb")) id="FON";
359 else if(strstr(argv[t],".afm")) id="FON";
360 else if(strstr(argv[t],".1")) id="DOC";
361 else if(strstr(argv[t],".doc")) id="DOC";
362 else if(strstr(argv[t],".txt")) id="TXT";
363 else if(strstr(argv[t],".hlp")) id="DOC";
364 else if(strstr(argv[t],".dll")) id="DLL";
366 fread(buf,l,1,fi);
367 zwriter->write(zwriter,id,3);
368 unsigned char b1=l;
369 unsigned char b2=l>>8;
370 unsigned char b3=l>>16;
371 unsigned char b4=l>>24;
372 zwriter->write(zwriter,&b1,1);
373 zwriter->write(zwriter,&b2,1);
374 zwriter->write(zwriter,&b3,1);
375 zwriter->write(zwriter,&b4,1);
376 int sl=strlen(argv[t]);
377 if(sl>255) {
378 fprintf(stderr, "Error: filename %s too long\n", argv[t]);
380 unsigned char b = sl;
381 zwriter->write(zwriter,&b,1); //write filename len
382 zwriter->write(zwriter,argv[t],sl); //write filename
383 zwriter->write(zwriter,buf,l); //write data
384 fprintf(stderr,"[%s] %s: %d bytes written.\n", id, argv[t], l);
385 fclose(fi);
386 free(buf);
388 else
390 fprintf(stderr,"%s not found.\n", argv[t]);
394 char*id_end = "END";
395 zwriter->write(zwriter,id_end,3);
396 zwriter->finish(zwriter);
398 #ifndef ZLIB
399 if(system("do_lzma e crnfiles.dat crnfiles.7z")&0xff00) {
400 perror("do_lzma");
401 exit(1);
403 FILE*fi = fopen("crnfiles.7z", "rb");
404 if(!fi) {
405 perror("crnfiles.7z");
406 exit(1);
408 writer_t*w = writer_init_includewriter("crnfiles.c");
409 while(!feof(fi)) {
410 char buf[4096];
411 int len = fread(buf,1,4096,fi);
412 if(!len)
413 break;
414 w->write(w, buf, len);
416 w->finish(w);
417 fclose(fi);
418 if(unlink("crnfiles.dat")) {
419 perror("crnfiles.dat");
420 exit(1);
422 if(unlink("crnfiles.7z")) {
423 perror("crnfiles.7z");
424 exit(1);
426 #endif
428 fi = fopen("crnfiles.c", "ab+");
429 fprintf(fi, "\nint crn_decompressed_size=%d;\n", fullsize);
430 fclose(fi);
432 return 0;