fixed empty org/ibex/translators files
[org.ibex.core.git] / src / org / ibex / translators / MSPack.c
index e69de29..f09cf35 100644 (file)
@@ -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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/fcntl.h>
+
+#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;i<MAX_MEMBERS;i++) {
+            if(write_buf_table[i].filename == NULL) {
+                write_buf_table[i].filename = xstrdup(filename);
+                buf = &write_buf_table[i].buf;
+                buf->writable = 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<MAX_MEMBERS && write_buf_table[i].filename;i++) {
+        output_table[i].filename = write_buf_table[i].filename;
+        output_table[i].data = write_buf_table[i].buf.addr;
+        output_table[i].length = write_buf_table[i].buf.size;
+    }
+    
+    user_info[2] = (char*) output_table;
+    
+    return 0;
+}