3 Part of the swftools installer.
5 Copyright (c) 2004 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 */
31 #include "../z/zlib.h"
32 #define ZLIB_BUFFER_SIZE 16384
34 static int verbose = 0;
35 static void msg(char*format, ...)
42 va_start(arglist, format);
43 vsprintf(buf, format, arglist);
46 while(l && buf[l-1]=='\n') {
50 printf("(archive) %s\n", buf);
55 typedef struct _reader
57 int (*read)(struct _reader*, void*data, int len);
58 void (*dealloc)(struct _reader*);
63 /* ---------------------------- mem reader ------------------------------- */
70 static int reader_memread(reader_t*reader, void* data, int _len)
72 struct memread_t*mr = (struct memread_t*)reader->internal;
75 if(mr->length - reader->pos < len) {
76 len = mr->length - reader->pos;
78 memcpy(data, &mr->data[reader->pos], len);
79 msg("at pos %d, asked to read %d bytes, did read %d bytes\n", reader->pos, _len, len);
83 static void reader_memread_dealloc(reader_t*reader)
86 free(reader->internal);
87 memset(reader, 0, sizeof(reader_t));
89 reader_t*reader_init_memreader(void*newdata, int newlength)
91 reader_t*r = malloc(sizeof(reader_t));
92 struct memread_t*mr = (struct memread_t*)malloc(sizeof(struct memread_t));
93 mr->data = (unsigned char*)newdata;
94 mr->length = newlength;
95 r->read = reader_memread;
96 r->dealloc = reader_memread_dealloc;
97 r->internal = (void*)mr;
103 /* ---------------------------- zlibinflate reader -------------------------- */
108 unsigned char readbuffer[ZLIB_BUFFER_SIZE];
111 static void zlib_error(int ret, char* msg, z_stream*zs)
113 fprintf(stderr, "%s: zlib error (%d): last zlib error: %s\n", msg, ret, zs->msg?zs->msg:"unknown");
118 static int reader_zlibinflate(reader_t*reader, void* data, int len)
120 struct zlibinflate_t*z = (struct zlibinflate_t*)reader->internal;
128 z->zs.next_out = (Bytef *)data;
129 z->zs.avail_out = len;
132 if(!z->zs.avail_in) {
133 z->zs.avail_in = z->input->read(z->input, z->readbuffer, ZLIB_BUFFER_SIZE);
134 z->zs.next_in = z->readbuffer;
137 ret = inflate(&z->zs, Z_NO_FLUSH);
139 ret = inflate(&z->zs, Z_FINISH);
142 ret != Z_STREAM_END) zlib_error(ret, "bitio:inflate_inflate", &z->zs);
144 if (ret == Z_STREAM_END) {
145 int pos = z->zs.next_out - (Bytef*)data;
146 ret = inflateEnd(&z->zs);
147 if (ret != Z_OK) zlib_error(ret, "bitio:inflate_end", &z->zs);
148 free(reader->internal);
149 reader->internal = 0;
153 if(!z->zs.avail_out) {
160 static void reader_zlibinflate_dealloc(reader_t*reader)
162 struct zlibinflate_t*z = (struct zlibinflate_t*)reader->internal;
165 z->input->dealloc(z->input);z->input = 0;
168 free(reader->internal);
170 memset(reader, 0, sizeof(reader_t));
172 reader_t* reader_init_zlibinflate(reader_t*input)
174 reader_t*r = malloc(sizeof(reader_t));
175 struct zlibinflate_t*z;
177 memset(r, 0, sizeof(reader_t));
178 z = (struct zlibinflate_t*)malloc(sizeof(struct zlibinflate_t));
179 memset(z, 0, sizeof(struct zlibinflate_t));
181 r->read = reader_zlibinflate;
182 r->dealloc = reader_zlibinflate_dealloc;
185 memset(&z->zs,0,sizeof(z_stream));
186 z->zs.zalloc = Z_NULL;
187 z->zs.zfree = Z_NULL;
188 z->zs.opaque = Z_NULL;
189 ret = inflateInit(&z->zs);
190 if (ret != Z_OK) zlib_error(ret, "bitio:inflate_init", &z->zs);
194 /* -------------------------------------------------------------------------- */
197 static int create_directory(char*path,statusfunc_t f)
199 if(!path || !*path || (*path=='.' && (!path[1] || path[1]=='.')))
200 return 1; //nothing to do
201 while(path[0]=='.' && (path[1]=='/' || path[1]=='\\'))
205 if(PathIsDirectoryA(path))
209 if(stat(path, &st)>=0) {
210 if(S_ISDIR(st.st_mode)) {
211 return 1; /* already exists */
216 if(mkdir(path,0755)<0) {
219 sprintf(buf, "create directory \"%s\" FAILED", path);
225 static int goto_directory(char*path,statusfunc_t f)
229 sprintf(buf, "changing to directory \"%s\" FAILED", path);
235 static char basenamebuf[256];
236 static char*get_directory(char*filename)
238 char*r1 = strrchr(filename, '\\');
239 char*r2 = strrchr(filename, '/');
240 char*r = r1>r2?r1:r2;
243 memcpy(basenamebuf, filename, r-filename);
244 basenamebuf[r-filename] = 0;
245 //msg("directory name of \"%s\" is \"%s\"", filename, basenamebuf);
248 static int write_file(char*filename, reader_t*r, int len,statusfunc_t f)
250 while(filename[0]=='.' && (filename[1]=='/' || filename[1]=='\\'))
253 filename=strdup(filename);
261 msg("create file \"%s\" (%d bytes)", filename, len);
262 FILE*fo = fopen(filename, "wb");
266 sprintf(buf, "Couldn't create file %s", filename);
277 int n = r->read(r, buf, l);
280 sprintf(buf, "Couldn't read byte %d (pos+%d) from input buffer for file %s", pos+n, n, filename);
284 fwrite(buf, l, 1, fo);
292 int unpack_archive(void*data, int len, char*destdir, statusfunc_t f)
294 reader_t*m = reader_init_memreader(data, len);
295 reader_t*z = reader_init_zlibinflate(m);
297 f(0, "Creating installation directory");
298 if(!create_directory(destdir,f)) return 0;
299 f(0, "Changing to installation directory");
300 if(!goto_directory(destdir,f)) return 0;
302 f(0, "Uncompressing files...");
307 if(z->read(z, id, 3)<3) {
308 f(-1, "Unexpected end of archive");
311 if(!strcmp(id, "END"))
314 unsigned b1=0,b2=0,b3=0,b4=0;
316 l+=z->read(z, &b1, 1);
317 l+=z->read(z, &b2, 1);
318 l+=z->read(z, &b3, 1);
319 l+=z->read(z, &b4, 1);
324 int len = b1|b2<<8|b3<<16|b4<<24;
327 unsigned char filename_len;
328 z->read(z, &filename_len, 1);
329 char*filename = malloc(filename_len+1);
330 z->read(z, filename, filename_len);
331 filename[(int)filename_len] = 0;
333 if(verbose) printf("[%s] %s %d\n", id, filename, len);
335 sprintf(buf, "[%s] %s (%d bytes)", id, filename, len);
337 if(!strcmp(id, "DIR")) {
338 if(!create_directory(filename,f)) return 0;
340 if(!create_directory(get_directory(filename),f)) return 0;
342 if(!write_file(filename,z,len,f)) return 0;
345 f(0, "Finishing Installation");