X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=installer%2Farchive.c;h=050284558e5c747a0569544576483549c1c9bdcc;hp=9dcfbfef90ca06aa69f76378a9c974d8f0039b79;hb=c63b2bf21dc1df9a736f0b4c08f6cba828cdab92;hpb=8eebd508d27d7ecd7b4ce26d7e99356f92847b75 diff --git a/installer/archive.c b/installer/archive.c index 9dcfbfe..0502845 100644 --- a/installer/archive.c +++ b/installer/archive.c @@ -1,8 +1,8 @@ /* archive.c - Part of the swftools installer. + Part of the rfx installer. - Copyright (c) 2004 Matthias Kramm + Copyright (c) 2004-2008 Matthias Kramm This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,8 +28,14 @@ #include #endif #include "archive.h" +#include "utils.h" + +#ifdef ZLIB #include "../z/zlib.h" #define ZLIB_BUFFER_SIZE 16384 +#else +#include "lzma/LzmaDecode.h" +#endif static int verbose = 0; static void msg(char*format, ...) @@ -40,7 +46,7 @@ static void msg(char*format, ...) if(!verbose) return; va_start(arglist, format); - vsprintf(buf, format, arglist); + vsnprintf(buf, sizeof(buf)-1, format, arglist); va_end(arglist); l = strlen(buf); while(l && buf[l-1]=='\n') { @@ -98,8 +104,76 @@ reader_t*reader_init_memreader(void*newdata, int newlength) r->pos = 0; return r; } +/* ---------------------------- lzma reader -------------------------- */ +typedef struct +{ + reader_t*input; + CLzmaDecoderState state; + unsigned char*mem; + int pos; + int len; + int lzmapos; + int available; +} lzma_t; + +static void reader_lzma_dealloc(reader_t*reader) +{ + lzma_t*i = (lzma_t*)reader->internal; + free(i->state.Probs);i->state.Probs = 0; + free(i->state.Dictionary);i->state.Dictionary = 0; + free(reader->internal);reader->internal=0; +} + +static int reader_lzma_read(reader_t*reader, void*data, int len) +{ + lzma_t*i = (lzma_t*)reader->internal; + + SizeT processed = 0; + if(len>i->available) + len = i->available; + int ret = LzmaDecode(&i->state, + &i->mem[i->pos], i->len-i->pos, &i->lzmapos, + data, len, &processed); + i->available -= processed; + i->pos += i->lzmapos; + return processed; +} + +reader_t* reader_init_lzma(void*mem, int len) +{ + reader_t*r = malloc(sizeof(reader_t)); + memset(r, 0, sizeof(reader_t)); + + lzma_t*i = (lzma_t*)malloc(sizeof(lzma_t)); + memset(i, 0, sizeof(lzma_t)); + r->internal = i; + r->read = reader_lzma_read; + r->dealloc = reader_lzma_dealloc; + r->pos = 0; + + i->mem = mem; + i->len = len; + i->lzmapos = 0; + + if(LzmaDecodeProperties(&i->state.Properties, mem, LZMA_PROPERTIES_SIZE)) { + printf("Couldn't decode properties\n"); + return 0; + } + i->pos += LZMA_PROPERTIES_SIZE; + + unsigned char*l = &i->mem[i->pos]; + i->available = (long long)l[0] | (long long)l[1]<<8 | (long long)l[2]<<16 | (long long)l[3]<<24 | + (long long)l[4]<<32 | (long long)l[5]<<40 | (long long)l[6]<<48 | (long long)l[7]<<56; + i->pos += 8; //uncompressed size + i->state.Probs = (CProb *)malloc(LzmaGetNumProbs(&i->state.Properties) * sizeof(CProb)); + i->state.Dictionary = (unsigned char *)malloc(i->state.Properties.DictionarySize); + LzmaDecoderInit(&i->state); + + return r; +} +#ifdef ZLIB /* ---------------------------- zlibinflate reader -------------------------- */ struct zlibinflate_t { @@ -192,9 +266,10 @@ reader_t* reader_init_zlibinflate(reader_t*input) } /* -------------------------------------------------------------------------- */ +#endif -static int create_directory(char*path,statusfunc_t f) +static int create_directory(char*path,status_t* f) { if(!path || !*path || (*path=='.' && (!path[1] || path[1]=='.'))) return 1; //nothing to do @@ -217,17 +292,17 @@ static int create_directory(char*path,statusfunc_t f) perror("mkdir"); char buf[1024]; sprintf(buf, "create directory \"%s\" FAILED", path); - f(-1, buf); + f->error(buf); return 0; } return 1; } -static int goto_directory(char*path,statusfunc_t f) +static int goto_directory(char*path,status_t* f) { if(chdir(path)<0) { char buf[1024]; sprintf(buf, "changing to directory \"%s\" FAILED", path); - f(-1, buf); + f->error(buf); return 0; } return 1; @@ -245,7 +320,7 @@ static char*get_directory(char*filename) //msg("directory name of \"%s\" is \"%s\"", filename, basenamebuf); return basenamebuf; } -static int write_file(char*filename, reader_t*r, int len,statusfunc_t f) +static int write_file(char*filename, reader_t*r, int len,status_t* f) { while(filename[0]=='.' && (filename[1]=='/' || filename[1]=='\\')) filename+=2; @@ -258,13 +333,15 @@ static int write_file(char*filename, reader_t*r, int len,statusfunc_t f) p++; } + f->new_file(filename); + msg("create file \"%s\" (%d bytes)", filename, len); FILE*fo = fopen(filename, "wb"); if(!fo) { char buf[1024]; sprintf(buf, "Couldn't create file %s", filename); - f(-1, buf); + f->error(buf); free(filename); return 0; } @@ -278,7 +355,7 @@ static int write_file(char*filename, reader_t*r, int len,statusfunc_t f) if(n < l) { char buf[1024]; sprintf(buf, "Couldn't read byte %d (pos+%d) from input buffer for file %s", pos+n, n, filename); - f(-1, buf); + f->error(buf); return 0; } fwrite(buf, l, 1, fo); @@ -289,23 +366,45 @@ static int write_file(char*filename, reader_t*r, int len,statusfunc_t f) return 1; } -int unpack_archive(void*data, int len, char*destdir, statusfunc_t f) +int unpack_archive(void*data, int len, char*destdir, status_t* f) { reader_t*m = reader_init_memreader(data, len); +#ifdef ZLIB reader_t*z = reader_init_zlibinflate(m); +#else + reader_t*z = reader_init_lzma(data, len); +#endif + if(!z) { + f->error("Couldn't decompress installation files"); + return 0; + } - f(0, "Creating installation directory"); + f->message("Creating installation directory"); if(!create_directory(destdir,f)) return 0; - f(0, "Changing to installation directory"); - if(!goto_directory(destdir,f)) return 0; + + printf("%s\n", destdir); + + unsigned b1=0,b2=0,b3=0,b4=0; + int l = 0; + l+=z->read(z, &b1, 1); + l+=z->read(z, &b2, 1); + l+=z->read(z, &b3, 1); + l+=z->read(z, &b4, 1); + if(l<4) + return 0; + /* read size */ + int num = b1|b2<<8|b3<<16|b4<<24; + + f->status(0, num); - f(0, "Uncompressing files..."); + f->message("Uncompressing files..."); + int pos = 0; while(1) { /* read id */ unsigned char id[4]; id[3] = 0; if(z->read(z, id, 3)<3) { - f(-1, "Unexpected end of archive"); + f->error("Unexpected end of archive"); return 0; } if(!strcmp(id, "END")) @@ -329,20 +428,26 @@ int unpack_archive(void*data, int len, char*destdir, statusfunc_t f) char*filename = malloc(filename_len+1); z->read(z, filename, filename_len); filename[(int)filename_len] = 0; + + while(filename[0]=='.' && (filename[1]=='/' || filename[1]=='\\')) + filename+=2; + filename = concatPaths(destdir, filename); + + f->status(++pos, num); if(verbose) printf("[%s] %s %d\n", id, filename, len); char buf[2048]; sprintf(buf, "[%s] %s (%d bytes)", id, filename, len); - f(0, buf); + f->message(buf); if(!strcmp(id, "DIR")) { + f->new_directory(filename); if(!create_directory(filename,f)) return 0; } else { if(!create_directory(get_directory(filename),f)) return 0; - if(!write_file(filename,z,len,f)) return 0; } } - f(0, "Finishing Installation"); + f->message("Finishing Installation"); return 1; }