X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Fibex%2Ftranslators%2FMSPack.c;h=f09cf3534558ac5afa5253ce253a96bcac13b574;hb=da1f843588c8bd2b2c7cc74a5b4ffff8d57ab712;hp=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391;hpb=167e1c09923897c956b31723211ea890c105c75d;p=org.ibex.core.git diff --git a/src/org/ibex/translators/MSPack.c b/src/org/ibex/translators/MSPack.c index e69de29..f09cf35 100644 --- a/src/org/ibex/translators/MSPack.c +++ b/src/org/ibex/translators/MSPack.c @@ -0,0 +1,202 @@ +/* +UserInfo: + On start: + 0: Addr of CAB/EXE + 1: Length of CAB/EXE + On Edit: + 2: Addr of output_table array + +Exit codes: + 0: Success + 1: Internal Error + 2: Invalid CAB +*/ + +#include +#include +#include +#include +#include + +#include "mspack.h" + +#define MAX(a,b) (((a)>(b))?(a):(b)) +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX_MEMBERS 64 + +char *xstrdup(const char *s) { + char *ret = strdup(s); + if(ret == NULL) exit(1); + return ret; +} + +typedef struct { + char *addr; + int pos; + int size; + int length; + int writable; +} mem_buf_t; + +static mem_buf_t *cab_mem_buf = NULL; + +static void mem_buf_grow(mem_buf_t *buf,size_t newsize) { + size_t new_len; + char *p; + if(buf->length < 0) exit(1); + if(newsize <= buf->length) return; + new_len = MAX(buf->length ? buf->length*2 : 65536,newsize); + p = realloc(buf->addr,new_len); + if(p == NULL) exit(1); + buf->addr = p; + buf->length = new_len; +} + +static struct { + char *filename; + mem_buf_t buf; +} write_buf_table[MAX_MEMBERS]; + +static struct { + char *filename; + char *data; + int length; +} output_table[MAX_MEMBERS+1]; + +static struct mspack_file *my_open(struct mspack_system *sys, char *filename, int mode) { + mem_buf_t *buf = NULL; + int i; + if(strcmp(filename,"/dev/cab")==0) { + if(mode != MSPACK_SYS_OPEN_READ) return NULL; + buf = cab_mem_buf; + } else { + if(mode != MSPACK_SYS_OPEN_WRITE) return NULL; + + for(i=0;iwritable = 1; + break; + } + } + } + + return (struct mspack_file *) buf; +} + +static void my_close(struct mspack_file *buf_) { + mem_buf_t *buf = (mem_buf_t*) buf_; + /* NO OP */ +} + +static int my_read(struct mspack_file *buf_, void *out, int count) { + mem_buf_t *buf = (mem_buf_t*) buf_; + count = MIN(buf->size - buf->pos, count); + memcpy(out,buf->addr + buf->pos,count); + buf->pos += count; + return count; +} + +static int my_write(struct mspack_file *buf_, void *in, int count) { + mem_buf_t *buf = (mem_buf_t*) buf_; + if(!buf->writable) return -1; + if(buf->length < buf->pos + count) mem_buf_grow(buf,buf->pos + count); + memcpy(buf->addr+buf->pos,in,count); + buf->pos += count; + buf->size = MAX(buf->size,buf->pos); + return count; +} + +static int my_seek(struct mspack_file *buf_, off_t off, int mode) { + mem_buf_t *buf = (mem_buf_t*) buf_; + int newpos; + switch(mode) { + case MSPACK_SYS_SEEK_START: newpos = off; break; + case MSPACK_SYS_SEEK_CUR: newpos = buf->pos + off; break; + case MSPACK_SYS_SEEK_END: newpos = buf->size - off; break; + default: return -1; + } + if(newpos < 0) return -1; + if(newpos > buf->size) { + if(!buf->writable) return -1; + if(newpos > buf->length) + mem_buf_grow(buf,newpos); + } + buf->pos = newpos; + return 0; +} + +static off_t my_tell(struct mspack_file *buf_) { + mem_buf_t *buf = (mem_buf_t*) buf_; + return buf ? buf->pos : 0; +} + +// FEATURE: Remove this to possibly avoid pulling in stdio from libc +// (it may be getting pulled in anyway from malloc or something) +static void my_message(struct mspack_file *file, char *format, ...) { + va_list ap; + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); + fputc((int) '\n', stderr); + fflush(stderr); +} + +static void *my_alloc(struct mspack_system *sys, size_t size) { return malloc(size); } +static void my_free(void *p) { free(p); } +static void my_copy(void *src, void *dest, size_t bytes) { memcpy(dest, src, bytes); } + +static struct mspack_system my_system = { + &my_open, + &my_close, + &my_read, + &my_write, + &my_seek, + &my_tell, + &my_message, + &my_alloc, + &my_free, + &my_copy, + NULL +}; + +extern char *user_info[1024]; + +int mspack_main() { + struct mscab_decompressor *decomp; + struct mscabd_cabinet *cab; + struct mscabd_file *file; + mem_buf_t mem_buf; + size_t size = (size_t)user_info[1]; + int i; + + mem_buf.addr = user_info[0]; + mem_buf.pos = mem_buf.writable = 0; + mem_buf.length = -1; + mem_buf.size = size; + + cab_mem_buf = &mem_buf; + + decomp = mspack_create_cab_decompressor(&my_system); + if(!decomp) exit(1); + + cab = decomp->search(decomp,"/dev/cab"); + if(!cab) exit(2); + + for(file = cab->files;file;file=file->next) + decomp->extract(decomp,file,file->filename); + + decomp->close(decomp,cab); + mspack_destroy_cab_decompressor(decomp); + + for(i=0;i