write filenames as len+string, instead of zero terminated string
[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 /* ---------------------------- include file filter ------------------------------- */
18
19 typedef struct _ifwrite
20 {
21     FILE*fi;
22     int bp;
23     int pos;
24     int last;
25     char buf[1024];
26     char*filename;
27 } ifwrite_t;
28
29 static int writer_ifwrite_write(writer_t*out, void*data, int len)
30 {
31     ifwrite_t*i = (ifwrite_t*)out->internal;
32     FILE*fo = i->fi;
33     int t;
34     for(t=0;t<len;t++) {
35         unsigned char c = ((unsigned char*)data)[t];
36         if(i->bp>=80) {
37             fprintf(fo, "\"%s\"\n", i->buf);
38             i->bp = 0;
39         }
40         if(c<=32 || c>0x7e || c=='"' || c == '\\' || c == '%'
41         || (i->last && c>='0' && c<='9') 
42         || (i->last && c>='a' && c<='f')
43         || (i->last && c>='A' && c<='F')
44         ) {
45             i->bp += sprintf(i->buf+i->bp, "\\x%x",c);
46             i->last = 1;
47         } else {
48             i->buf[i->bp] = c;
49             i->buf[i->bp+1] = 0;
50             i->last = 0;
51             i->bp++;
52         }
53         i->pos++;
54     }
55 }
56 static void writer_ifwrite_finish(writer_t*w)
57 {
58     ifwrite_t *i= (ifwrite_t*)w->internal;
59     fprintf(i->fi, "\"%s\"\n", i->buf);
60     fprintf(i->fi, ";\n");
61     fprintf(i->fi, "int crndata_len = %d;\n", i->pos);
62     fclose(i->fi);
63     printf("wrote file %s\n", i->filename);
64     free(w->internal);w->internal = 0;
65 }
66
67 writer_t*writer_init_includewriter(char*filename)
68 {
69     writer_t*w = malloc(sizeof(writer_t));
70     FILE*fi = fopen(filename, "wb");
71     memset(w, 0, sizeof(writer_t));
72     w->write = writer_ifwrite_write;
73     w->finish = writer_ifwrite_finish;
74     ifwrite_t*i = (ifwrite_t *)malloc(sizeof(ifwrite_t));
75     i->fi = fi;
76     i->pos = 0;
77     i->bp=0;
78     i->last = 0;
79     i->filename = filename;
80     w->internal = i;
81     
82     fprintf(i->fi, "char* crndata =\n");
83     return w;
84
85 }
86
87 /* ---------------------------- zlibdeflate writer -------------------------- */
88
89 struct zlibdeflate_t
90 {
91     z_stream zs;
92     writer_t*output;
93     int written;
94     int zwritten;
95     unsigned char writebuffer[ZLIB_BUFFER_SIZE];
96 };
97
98 static void zlib_error(int ret, char* msg, z_stream*zs)
99 {
100     fprintf(stderr, "%s: zlib error (%d): last zlib error: %s\n",
101           msg,
102           ret,
103           zs->msg?zs->msg:"unknown");
104     perror("errno:");
105     exit(1);
106 }
107
108 static int writer_zlibdeflate_write(writer_t*writer, void* data, int len) 
109 {
110     struct zlibdeflate_t*z = (struct zlibdeflate_t*)writer->internal;
111     int ret;
112     if(!z) {
113         fprintf(stderr, "zlib not initialized!\n");
114         return 0;
115     }
116     if(!len)
117         return 0;
118     
119     z->zs.next_in = (Bytef *)data;
120     z->zs.avail_in = len;
121
122     while(1) {
123         ret = deflate(&z->zs, Z_NO_FLUSH);
124         
125         if (ret != Z_OK) zlib_error(ret, "bitio:deflate_deflate", &z->zs);
126
127         if(z->zs.next_out != z->writebuffer) {
128             z->zwritten += z->zs.next_out - (Bytef*)z->writebuffer;
129             z->output->write(z->output, z->writebuffer, z->zs.next_out - (Bytef*)z->writebuffer);
130             z->zs.next_out = z->writebuffer;
131             z->zs.avail_out = ZLIB_BUFFER_SIZE;
132         }
133
134         if(!z->zs.avail_in) {
135             break;
136         }
137     }
138     z->written += len;
139     return len;
140 }
141 static void writer_zlibdeflate_finish(writer_t*writer)
142 {
143     struct zlibdeflate_t*z = (struct zlibdeflate_t*)writer->internal;
144     writer_t*output;
145     int ret;
146     if(!z)
147         return;
148     output= z->output;
149     while(1) {
150         ret = deflate(&z->zs, Z_FINISH);
151         if (ret != Z_OK &&
152             ret != Z_STREAM_END) zlib_error(ret, "bitio:deflate_finish", &z->zs);
153
154         if(z->zs.next_out != z->writebuffer) {
155             z->zwritten += z->zs.next_out - (Bytef*)z->writebuffer;
156             z->output->write(z->output, z->writebuffer, z->zs.next_out - (Bytef*)z->writebuffer);
157             z->zs.next_out = z->writebuffer;
158             z->zs.avail_out = ZLIB_BUFFER_SIZE;
159         }
160
161         if (ret == Z_STREAM_END) {
162             break;
163
164         }
165     }
166     ret = deflateEnd(&z->zs);
167     if (ret != Z_OK) zlib_error(ret, "bitio:deflate_end", &z->zs);
168
169     if(z->written) {
170         printf("Compression ratio: %.2f%% (%d bytes of input data, %d bytes of output data)\n", 
171                 z->zwritten*100.0 / z->written,
172                 z->written, z->zwritten);
173     } else {
174         printf("Compression ratio: 0%% (0 bytes of input data, %d bytes of output data)\n", z->zwritten);
175     }
176
177     free(writer->internal);
178     memset(writer, 0, sizeof(writer_t));
179     output->finish(output); 
180 }
181 writer_t*writer_init_zwriter(writer_t*output)
182 {
183     writer_t*w = malloc(sizeof(writer_t));
184     struct zlibdeflate_t*z;
185     int ret;
186     memset(w, 0, sizeof(writer_t));
187     z = (struct zlibdeflate_t*)malloc(sizeof(struct zlibdeflate_t));
188     memset(z, 0, sizeof(struct zlibdeflate_t));
189     w->internal = z;
190     w->write = writer_zlibdeflate_write;
191     w->finish = writer_zlibdeflate_finish;
192     z->output = output;
193     memset(&z->zs,0,sizeof(z_stream));
194     z->zs.zalloc = Z_NULL;
195     z->zs.zfree  = Z_NULL;
196     z->zs.opaque = Z_NULL;
197     ret = deflateInit(&z->zs, 9);
198     if (ret != Z_OK) zlib_error(ret, "bitio:deflate_init", &z->zs);
199     z->zs.next_out = z->writebuffer;
200     z->zs.avail_out = ZLIB_BUFFER_SIZE;
201     z->written = 0;
202     z->zwritten = 0;
203     return w;
204 }
205
206 /* ------------------------------- main ----------- ------------------------------- */
207
208 static int compare_filenames(const void*_n1, const void*_n2)
209 {
210     const char*s1 = *(const char**)_n1;
211     const char*s2 = *(const char**)_n2;
212
213     char*e1 = strrchr(s1, '.');
214     char*e2 = strrchr(s2, '.');
215     if(!e1 && !e2)
216         return 0;
217     if(e1 && !e2)
218         return 1;
219     if(!e1 && e2)
220         return -1;
221     int c = strcasecmp(e1+1,e2+1);
222     if(c)
223         return c;
224     return strcasecmp(s1,s2);
225 }
226
227 int main (int argn, char*argv[])
228 {
229     int t;
230     char buf[320];
231
232     writer_t*include_writer = writer_init_includewriter("crnfiles.c");
233     writer_t*zwriter = writer_init_zwriter(include_writer);
234
235     qsort(argv+1, argn-1, sizeof(argv[0]), compare_filenames);
236
237     for(t=1;t<argn;t++)
238     {
239             if(argv[t][0]!='-')
240             {
241                     FILE*fi=fopen(argv[t],"rb");
242                     if(fi)
243                     {
244                             fseek(fi,0,SEEK_END);
245                             long l=ftell(fi);
246                             fseek(fi,0,SEEK_SET);
247
248                             char*buf=(char*)malloc(l);
249                             char*id="NUL";
250                             struct stat st;
251                             fstat(fileno(fi),&st);
252                             if(S_ISDIR(st.st_mode)) {id ="DIR";l=0;}
253                             else if(strstr(argv[t],".swf")) id="SWF";
254                             else if(strstr(argv[t],".gif")) id="PIC";
255                             else if(strstr(argv[t],".png")) id="PIC";
256                             else if(strstr(argv[t],".jpeg")) id="PIC";
257                             else if(strstr(argv[t],".jpg")) id="PIC";
258                             else if(strstr(argv[t],".tif")) id="PIC";
259                             else if(strstr(argv[t],".c")) id="SRC";
260                             else if(strstr(argv[t],".cc")) id="SRC";
261                             else if(strstr(argv[t],".cpp")) id="SRC";
262                             else if(strstr(argv[t],".h")) id="SRC";
263                             else if(strstr(argv[t],".class")) id="CLA";
264                             else if(strstr(argv[t],".java")) id="SRC";
265                             else if(strstr(argv[t],".exe")) id="EXE";
266                             else if(strstr(argv[t],".ttf")) id="FON";
267                             else if(strstr(argv[t],".pfa")) id="FON";
268                             else if(strstr(argv[t],".pfb")) id="FON";
269                             else if(strstr(argv[t],".afm")) id="FON";
270                             else if(strstr(argv[t],".1")) id="DOC";
271                             else if(strstr(argv[t],".doc")) id="DOC";
272                             else if(strstr(argv[t],".hlp")) id="DOC";
273                             else if(strstr(argv[t],".dll")) id="DLL";
274
275                             fread(buf,l,1,fi);
276                             zwriter->write(zwriter,id,3);
277                             unsigned char b1=l;
278                             unsigned char b2=l>>8;
279                             unsigned char b3=l>>16;
280                             unsigned char b4=l>>24;
281                             zwriter->write(zwriter,&b1,1);
282                             zwriter->write(zwriter,&b2,1);
283                             zwriter->write(zwriter,&b3,1);
284                             zwriter->write(zwriter,&b4,1);
285                             int sl=strlen(argv[t]);
286                             if(sl>255) {
287                                 fprintf(stderr, "Error: filename %s too long\n", argv[t]);
288                             }
289                             unsigned char b = sl;
290                             zwriter->write(zwriter,&b,1); //write filename len
291                             zwriter->write(zwriter,argv[t],sl); //write filename
292                             zwriter->write(zwriter,buf,l); //write data
293                             fprintf(stderr,"[%s] %s: %d bytes written.\n", id, argv[t], l);
294                             fclose(fi);
295                             free(buf);
296                     }
297                     else
298                     {
299                             fprintf(stderr,"%s not found.\n", argv[t]);
300                     }
301             }
302     }
303     char*id_end = "END";
304     zwriter->write(zwriter,id_end,3);
305     zwriter->finish(zwriter);
306     return 0;
307 }
308