zip.c splitting/rewriting begun

--HG--
branch : HEAD
diff --git a/lib/zip.h b/lib/zip.h
index 8373057..f635427 100644
--- a/lib/zip.h
+++ b/lib/zip.h
@@ -7,7 +7,7 @@
 
 enum zip_state { ZIP_ST_UNCHANGED, ZIP_ST_DELETED, ZIP_ST_REPLACED,
 		 ZIP_ST_ADDED, ZIP_ST_RENAMED };
-enum zip_cmd { ZIP_CMD_INIT, ZIP_CMD_READ, ZIP_CMD_CRC, ZIP_CMD_CLOSE };
+enum zip_cmd { ZIP_CMD_INIT, ZIP_CMD_READ, ZIP_CMD_META, ZIP_CMD_CLOSE };
 
 /* flags for zip_open */
 #define ZIP_CREATE           1
@@ -39,7 +39,7 @@
 
 /* zip file */
 
-typedef unsigned long (*zip_read_func)(void *state, char *buf,
+typedef unsigned long (*zip_read_func)(void *state, void *data,
 				       int len, enum zip_cmd cmd);
 
 struct zip {
@@ -85,17 +85,14 @@
     char *fn, *ef, *fcom;
     char *fn_old;
 
-    
+    zip_read_func *ch_func;
+    void *ch_data;
+    int ch_comp;
+};
 
-    /* only use one of the following three for supplying new data
-       listed in order of priority, if more than one is set */
-    struct zip *ch_data_zf;
-    char *ch_data_buf;
-    FILE *ch_data_fp;
-    /* offset & len of new data in ch_data_fp or ch_data_buf */
-    unsigned int ch_data_offset, ch_data_len;
-    /* if source is another zipfile, number of file in zipfile */
-    unsigned int ch_data_zf_fileno;
+struct zip_meta { /* meta information needed to add compressed data */
+    unsigned int crc, uncomp_size;
+    /* ... */
 };
 
 
diff --git a/lib/zip_add_zip.c b/lib/zip_add_zip.c
new file mode 100644
index 0000000..063a19b
--- /dev/null
+++ b/lib/zip_add_zip.c
@@ -0,0 +1,11 @@
+#include "zip.h"
+#include "zipint.h"
+
+
+
+int
+zip_add_zip(struct zip *zf, char *name,
+	    struct zip *srczf, int srcidx, int start, int len)
+{
+    return zip_replace_zip(zf, -1, name, srczf, srcidx, start, len);
+}
diff --git a/lib/zip_replace.c b/lib/zip_replace.c
new file mode 100644
index 0000000..9adf5b7
--- /dev/null
+++ b/lib/zip_replace.c
@@ -0,0 +1,32 @@
+#include "zip.h"
+#include "zipint.h"
+
+
+
+int
+zip_replace(struct zip *zf, int idx, char *name,
+	    zip_read_func *fn, void *state, int comp)
+{
+    if (idx == -1)
+	zip_add(zf, name, fn, state, comp);
+    
+    if (idx < 0 || idx >= zf->nentry) {
+	zip_err = ZERR_NOENT;
+	return -1;
+    }
+
+    if (_zip_unchange_data(zf, idx) != 0)
+	return -1;
+
+    if (_zip_set_name(zf, idx, name) != 0)
+	return -1;
+    
+    zf->changes = 1;
+    zf->entry[idx].state = Z_REPLACED;
+
+    zf->entry[idx].ch_func = fn;
+    zf->entry[idx].ch_data = state;
+    zf->entry[idx].ch_comp = comp;
+
+    return 0;
+}
diff --git a/lib/zip_replace_zip.c b/lib/zip_replace_zip.c
new file mode 100644
index 0000000..9bd4d24
--- /dev/null
+++ b/lib/zip_replace_zip.c
@@ -0,0 +1,136 @@
+#include "zip.h"
+#include "zipint.h"
+
+struct read_zip {
+    struct zip *zf;
+    int idx;
+    /* ... */
+};
+
+struct read_part {
+    struct zip *zf;
+    int idx;
+    struct zip_file *zff;
+    int off, len;
+    /* ... */
+}
+
+static zip_read_func read_zip;
+static zip_read_func read_part;
+
+
+
+int
+zip_replace_zip(struct zip *zf, int idx, char *name,
+		struct zip *srczf, int srcidx, int start, int len)
+{
+    struct read_zip *z;
+    struct read_part *p;
+
+    if (srcidx < 0 || srcidx >= srczf->nentry) {
+	zip_err = ZERR_NOENT;
+	return -1;
+    }
+
+    if (start == 0 && (len == 0 || len == -1)) {
+	if ((z=(struct read_zip *)malloc(sizeof(struct read_zip))) == NULL) {
+	    zip_err = ZERR_MEMORY;
+	    return -1;
+	}
+	z->zf = srczf;
+	z->idx = srcidx;
+	return zip_replace(zf, idx, name, read_zip, z, 1);
+    }
+    else {
+	if ((p=(struct read_part *)malloc(sizeof(struct read_part))) == NULL) {
+	    zip_err = ZERR_MEMORY;
+	    return -1;
+	}
+	p->zf = srczf;
+	p->idx = srcidx;
+	p->off = start;
+	p->len = len;
+	p->zff = NULL;
+	return zip_replace(zf, idx, name, read_part, z, 0);
+    }
+}
+
+
+
+static unsigned long
+read_zip(void *state, void *data, int len, enum zip_cmd cmd);
+{
+    struct read_zip *z;
+
+    z = (struct read_zip *)state;
+
+    switch (cmd) {
+    case ZIP_CMD_INIT:
+	/* XXX */
+	break;
+	
+    case ZIP_CMD_READ:
+	/* XXX */
+	break;
+	
+    case ZIP_CMD_META:
+	/* XXX */
+	break;
+
+    case ZIP_CMD_CLOSE:
+	return 0;
+    }
+}
+
+
+
+static unsigned long
+read_part(void *state, void *data, int len, enum zip_cmd cmd);
+{
+    struct read_part *z;
+    char b[8192], *buf;
+    int i, n;
+
+    z = (struct read_part *)state;
+    buf = (char *)data;
+
+    switch (cmd) {
+    case ZIP_CMD_INIT:
+	if ((z->zff=zip_fopen_index(z->zf, idx) ) == NULL)
+	    return -1;
+
+	for (n=0; n<z->off; n+= i) {
+	    i = (z->off-n > 8192 ? 8192 : z->off-n);
+	    if ((i=zip_fread(z->zff, b, n)) < 0) {
+		zip_fclose(z->zff);
+		z->zff = NULL;
+		return -1;
+	    }
+	}
+	return 0;
+	
+    case ZIP_CMD_READ:
+	if (z->len != -1)
+	    n = len > z->len ? z->len : len;
+	else
+	    n = len;
+	
+	if ((i=zip_fread(z->zff, buf, n)) < 0)
+	    return -1;
+
+	if (z->len != -1)
+	    z->len -= i;
+
+	return i;
+	
+    case ZIP_CMD_CRC:
+	return -1;
+
+    case ZIP_CMD_CLOSE:
+	if (z->zff) {
+	    zip_fclose(z->zff);
+	    z->zff = NULL;
+	}
+	return 0;
+    }
+}
diff --git a/lib/zip_set_name.c b/lib/zip_set_name.c
new file mode 100644
index 0000000..715d321
--- /dev/null
+++ b/lib/zip_set_name.c
@@ -0,0 +1,29 @@
+#include "zip.h"
+#include "zipint.h"
+
+
+
+int
+_zip_set_name(struct zip *zf, int idx, char *name)
+{
+    if (idx >= zf->nentry || idx < 0) {
+	zip_err = ZERR_NOENT;
+	return -1;
+    }
+
+    if (name != NULL) {
+	if (zf->entry[idx].fn_old == NULL)
+	    zf->entry[idx].fn_old = zf->entry[idx].fn;
+	else
+	    free(zf->entry[idx].fn);
+	zf->entry[idx].fn = strdup(name);
+	if (zf->entry[idx].fn) {
+	    /* XXX: fn is NULL; very bad */
+	    zip_err = ZERR_MEMORY;
+	    return -1;
+	}
+	zf->entry[idx].fnlen = strlen(name);
+    }
+
+    return idx;
+}
diff --git a/lib/zipint.h b/lib/zipint.h
index 3929c64..1e8e504 100644
--- a/lib/zipint.h
+++ b/lib/zipint.h
@@ -20,5 +20,6 @@
 void *_zip_memdup(const void *mem, int len);
 void _zip_new_entry(struct zip *zf);
 void _zip_entry_init(struct zip *zf, int idx);
+int _zip_set_name(struct zip *zf, int idx, char *name);
 
 #endif /* zipint.h */