Massive work changing API to support zck_read and zck_write functions
authorJonathan Dieter <jdieter@gmail.com>
Tue, 10 Apr 2018 12:57:19 +0000 (15:57 +0300)
committerJonathan Dieter <jdieter@gmail.com>
Tue, 10 Apr 2018 12:58:59 +0000 (15:58 +0300)
Signed-off-by: Jonathan Dieter <jdieter@gmail.com>
src/lib/comp/comp.c
src/lib/comp/nocomp/nocomp.c
src/lib/comp/zstd/zstd.c
src/lib/dl/dl.c
src/lib/header.c
src/lib/io.c
src/lib/zck.c
src/lib/zck_private.h

index c1716e20ece935587da4df3eb8756df327bf7ba2..e278e99b39edb3b2a4ad656c98a5005d5a63680f 100644 (file)
 
 #define BLK_SIZE 32768
 #define VALIDATE(f)     if(!f) { \
-                            zck_log(ZCK_LOG_ERROR, "zckCtx not initialized\n"); \
+                            zck_log(ZCK_LOG_ERROR, \
+                                    "zckCtx not initialized\n"); \
                             return False; \
                         }
 
+#define VALIDATE_READ(f)    VALIDATE(f); \
+                            if(f->mode != ZCK_MODE_READ) { \
+                                zck_log(ZCK_LOG_ERROR, \
+                                        "zckCtx not opened for reading\n"); \
+                                return False; \
+                            }
+
+#define VALIDATE_WRITE(f)   VALIDATE(f); \
+                            if(f->mode != ZCK_MODE_WRITE) { \
+                                zck_log(ZCK_LOG_ERROR, \
+                                        "zckCtx not opened for writing\n"); \
+                                return False; \
+                            }
+
+#define VALIDATE_SIZE(f)    if(!f) { \
+                                zck_log(ZCK_LOG_ERROR, \
+                                        "zckComp not initialized\n"); \
+                                return -1; \
+                            }
+
+#define VALIDATE_READ_SIZE(f)   VALIDATE_SIZE(f); \
+                                if(f->mode != ZCK_MODE_READ) { \
+                                    zck_log(ZCK_LOG_ERROR, \
+                                            "zckComp not opened for reading\n"); \
+                                    return -1; \
+                                }
+
+#define VALIDATE_WRITE_SIZE(f)  VALIDATE_SIZE(f); \
+                                if(f->mode != ZCK_MODE_WRITE) { \
+                                    zck_log(ZCK_LOG_ERROR, \
+                                            "zckComp not opened for writing\n"); \
+                                    return -1; \
+                                }
+
 static char unknown[] = "Unknown(\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
 
 const static char *COMP_NAME[] = {
     "no",
+    "Unknown (1)",
     "zstd"
 };
 
@@ -53,8 +89,6 @@ int zck_comp_init(zckCtx *zck) {
     VALIDATE(zck);
 
     zckComp *comp = &(zck->comp);
-    char *dst = NULL;
-    size_t dst_size = 0;
 
     if(zck->comp.started) {
         zck_log(ZCK_LOG_ERROR, "Compression already initialized\n");
@@ -65,13 +99,17 @@ int zck_comp_init(zckCtx *zck) {
         zck_log(ZCK_LOG_ERROR, "Invalid dictionary configuration\n");
         return False;
     }
+    zck_log(ZCK_LOG_DEBUG, "Initializing %s compression\n",
+            zck_comp_name_from_type(comp->type));
     if(!zck->comp.init(&(zck->comp)))
         return False;
-
     if(zck->temp_fd) {
         if(zck->comp.dict) {
-            if(!zck->comp.compress(comp, zck->comp.dict, zck->comp.dict_size, &dst,
-                                   &dst_size, 0))
+            char *dst = NULL;
+            size_t dst_size = 0;
+
+            if(zck->comp.compress(comp, zck->comp.dict, zck->comp.dict_size,
+                                  &dst, &dst_size, 0) < 0)
                 return False;
             if(!write_data(zck->temp_fd, dst, dst_size)) {
                 free(dst);
@@ -82,7 +120,7 @@ int zck_comp_init(zckCtx *zck) {
             dst = NULL;
             dst_size = 0;
 
-            if(!zck->comp.end_chunk(comp, &dst, &dst_size, 0))
+            if(!zck->comp.end_cchunk(comp, &dst, &dst_size, 0))
                 return False;
             if(!write_data(zck->temp_fd, dst, dst_size)) {
                 free(dst);
@@ -101,15 +139,34 @@ int zck_comp_init(zckCtx *zck) {
     return True;
 }
 
-int zck_comp_close(zckCtx *zck) {
+int zck_comp_reset(zckCtx *zck) {
     VALIDATE(zck);
 
     zck->comp.started = 0;
+    if(zck->comp.dc_data) {
+        free(zck->comp.dc_data);
+        zck->comp.dc_data = NULL;
+        zck->comp.dc_data_loc = 0;
+        zck->comp.dc_data_size = 0;
+    }
     if(zck->comp.close == NULL)
         return True;
     return zck->comp.close(&(zck->comp));
 }
 
+int zck_comp_close(zckCtx *zck) {
+    VALIDATE(zck);
+    zck_log(ZCK_LOG_DEBUG, "Closing compression\n");
+    if(zck->comp.data) {
+        free(zck->comp.data);
+        zck->comp.data = NULL;
+        zck->comp.data_size = 0;
+        zck->comp.data_loc = 0;
+        zck->comp.data_idx = NULL;
+    }
+    return zck_comp_reset(zck);
+}
+
 int zck_set_compression_type(zckCtx *zck, int type) {
     VALIDATE(zck);
 
@@ -165,85 +222,239 @@ int zck_set_comp_parameter(zckCtx *zck, int option, void *value) {
 }
 
 const char *zck_comp_name_from_type(int comp_type) {
-    if(comp_type > 1) {
+    if(comp_type > 2) {
         snprintf(unknown+8, 21, "%i)", comp_type);
         return unknown;
     }
     return COMP_NAME[comp_type];
 }
 
-int zck_write(zckCtx *zck, const char *src, const size_t src_size) {
-    VALIDATE(zck);
+size_t zck_comp_read_from_dc(zckComp *comp, char *dst, size_t dst_size) {
+    VALIDATE_SIZE(comp);
+    VALIDATE_SIZE(dst);
+
+    size_t dl_size = dst_size;
+    if(dl_size > comp->dc_data_size - comp->dc_data_loc)
+        dl_size = comp->dc_data_size - comp->dc_data_loc;
+    memcpy(dst, comp->dc_data+comp->dc_data_loc, dl_size);
+    comp->dc_data_loc += dl_size;
+    if(dl_size > 0)
+        zck_log(ZCK_LOG_DEBUG, "Reading %lu bytes from decompressed buffer\n",
+                dl_size);
+    return dl_size;
+}
 
-    if(!zck->comp.started && !zck_comp_init(zck))
+int zck_comp_add_to_dc(zckComp *comp, const char *src, size_t src_size) {
+    VALIDATE(comp);
+    VALIDATE(src);
+
+    /* Get rid of any already read data and allocate space for new data */
+    char *temp = zmalloc(comp->dc_data_size - comp->dc_data_loc + src_size);
+    if(temp == NULL) {
+        zck_log(ZCK_LOG_ERROR, "Unable to reallocate %lu bytes\n",
+                comp->dc_data_size - comp->dc_data_loc + src_size);
         return False;
+    }
+    if(comp->dc_data_loc != 0)
+        zck_log(ZCK_LOG_DEBUG, "Freeing %lu bytes from decompressed buffer\n",
+                comp->dc_data_loc);
+    zck_log(ZCK_LOG_DEBUG, "Adding %lu bytes to decompressed buffer\n",
+            src_size);
+    memcpy(temp, comp->dc_data + comp->dc_data_loc,
+           comp->dc_data_size - comp->dc_data_loc);
+    free(comp->dc_data);
+    comp->dc_data_size -= comp->dc_data_loc;
+    comp->dc_data_loc = 0;
+    comp->dc_data = temp;
+
+    /* Copy new uncompressed data into comp */
+    memcpy(comp->dc_data + comp->dc_data_size, src, src_size);
+    comp->dc_data_size += src_size;
+    return True;
+}
+
+int zck_comp_add_to_data(zckComp *comp, const char *src, size_t src_size) {
+    VALIDATE(comp);
+    VALIDATE(src);
+    comp->data = realloc(comp->data, comp->data_size + src_size);
+    if(comp->data == NULL) {
+        zck_log(ZCK_LOG_ERROR, "Unable to reallocate %lu bytes\n",
+                comp->data_size + src_size);
+        return False;
+    }
+    zck_log(ZCK_LOG_DEBUG, "Adding %lu bytes to compressed buffer\n",
+        src_size);
+    memcpy(comp->data + comp->data_size, src, src_size);
+    comp->data_size += src_size;
+    comp->data_loc += src_size;
+    return True;
+}
+
+ssize_t zck_write(zckCtx *zck, const char *src, const size_t src_size) {
+    VALIDATE_WRITE_SIZE(zck);
+
+    if(!zck->comp.started && !zck_comp_init(zck))
+        return -1;
 
     if(src_size == 0)
-        return True;
+        return 0;
 
     char *dst = NULL;
     size_t dst_size = 0;
-    if(!zck->comp.compress(&(zck->comp), src, src_size, &dst, &dst_size, 1))
-        return False;
+    if(zck->comp.compress(&(zck->comp), src, src_size, &dst, &dst_size, 1) < 0)
+        return -1;
     if(dst_size > 0 && !write_data(zck->temp_fd, dst, dst_size)) {
         free(dst);
-        return False;
+        return -1;
     }
     if(!zck_index_add_to_chunk(zck, dst, dst_size, src_size)) {
         free(dst);
-        return False;
+        return -1;
     }
     free(dst);
-    return True;
+    return src_size;
 }
 
-int zck_end_chunk(zckCtx *zck) {
-    VALIDATE(zck);
+ssize_t zck_end_chunk(zckCtx *zck) {
+    VALIDATE_WRITE_SIZE(zck);
 
     if(!zck->comp.started && !zck_comp_init(zck))
-        return False;
+        return -1;
 
     /* No point in compressing empty data */
-    if(zck->comp.data_size == 0)
-        return True;
+    if(zck->comp.dc_data_size == 0)
+        return 0;
 
+    size_t data_size = zck->comp.dc_data_size;
     char *dst = NULL;
     size_t dst_size = 0;
-    if(!zck->comp.end_chunk(&(zck->comp), &dst, &dst_size, 1))
-        return False;
+    if(!zck->comp.end_cchunk(&(zck->comp), &dst, &dst_size, 1))
+        return -1;
     if(dst_size > 0 && !write_data(zck->temp_fd, dst, dst_size)) {
         free(dst);
-        return False;
+        return -1;
     }
     if(!zck_index_add_to_chunk(zck, dst, dst_size, 0)) {
         free(dst);
-        return False;
+        return -1;
     }
     if(!zck_index_finish_chunk(zck)) {
         free(dst);
-        return False;
+        return -1;
     }
     free(dst);
-    return True;
+    return data_size;
 }
 
-int zck_read(zckCtx *zck, const char *src, const size_t src_size, char **dst,
-             size_t dst_size) {
-    VALIDATE(zck);
+ssize_t comp_end_dchunk(zckCtx *zck, int use_dict, size_t fd_size) {
+    ssize_t rb = zck->comp.end_dchunk(&(zck->comp), use_dict, fd_size);
+    if(!zck_validate_current_chunk(zck))
+        return -1;
+    zck->comp.data_loc = 0;
+    zck->comp.data_idx = zck->comp.data_idx->next;
+    zck_hash_init(&(zck->check_chunk_hash), &(zck->chunk_hash_type));
+    return rb;
+}
 
-    zckComp *comp = &(zck->comp);
-    *dst = NULL;
+ssize_t comp_read(zckCtx *zck, char *dst, size_t dst_size, int use_dict) {
+    VALIDATE_READ_SIZE(zck);
 
     if(!zck->comp.started) {
         zck_log(ZCK_LOG_ERROR, "Compression hasn't been initialized yet\n");
-        return False;
+        return -1;
     }
 
-    if(src_size == 0)
-        return True;
+    if(dst_size == 0)
+        return 0;
 
-    if(!zck->comp.decompress(comp, src, src_size, dst, dst_size, 1))
+    size_t dc = 0;
+    char *src = zmalloc(dst_size - dc);
+    if(src == NULL) {
+        zck_log(ZCK_LOG_ERROR, "Unable to allocate %lu bytes\n", dst_size-dc);
         return False;
+    }
+    int finished_rd = False;
+    int finished_dc = False;
+    zck_log(ZCK_LOG_DEBUG, "Trying to read %lu bytes\n", dst_size);
+    while(dc < dst_size) {
+        /* Get bytes from decompressed buffer */
+        ssize_t rb = zck_comp_read_from_dc(&(zck->comp), dst+dc, dst_size-dc);
+        if(rb < 0)
+            goto zck_read_error;
+        dc += rb;
+        if(dc == dst_size)
+            break;
+        if(rb > 0)
+            continue;
+        if(finished_dc || zck->comp.data_eof)
+            break;
+
+        /* Decompress compressed buffer into decompressed buffer */
+        size_t dc_data_size = zck->comp.dc_data_size;
+        size_t dc_data_loc = zck->comp.dc_data_loc;
+        if(!zck->comp.decompress(&(zck->comp), use_dict))
+            goto zck_read_error;
+
+        /* Check whether we decompressed more data */
+        if(zck->comp.dc_data_size != dc_data_size ||
+           zck->comp.dc_data_loc != dc_data_loc)
+            continue;
+
+        /* End decompression chunk if we're on a chunk boundary */
+        if(zck->comp.data_idx == NULL) {
+            zck->comp.data_idx = zck->index.first;
+            zck_hash_init(&(zck->check_chunk_hash), &(zck->chunk_hash_type));
+            zck->comp.data_loc = 0;
+        }
+        if(zck->comp.data_loc == zck->comp.data_idx->comp_length) {
+            if(comp_end_dchunk(zck, use_dict, zck->comp.data_idx->length) < 0)
+                return -1;
+            if(zck->comp.data_idx == NULL) {
+                if(!zck_validate_file(zck))
+                    goto zck_hash_error;
+                zck->comp.data_eof = True;
+            }
+            continue;
+        }
 
-    return True;
+        /* If we finished reading and we've reached here, we're done
+         * decompressing */
+        if(finished_rd) {
+            finished_dc = True;
+            continue;
+        }
+
+        /* Make sure we don't read beyond current chunk length */
+        size_t rs = dst_size;
+        if(zck->comp.data_loc + rs > zck->comp.data_idx->comp_length)
+            rs = zck->comp.data_idx->comp_length - zck->comp.data_loc;
+
+        /* Decompressed buffer is empty, so read data from file and fill
+         * compressed buffer */
+        rb = read_data(zck->fd, src, rs);
+        if(rb < 0)
+            goto zck_read_error;
+        if(rb < rs) {
+            zck_log(ZCK_LOG_DEBUG, "EOF\n");
+            finished_rd = True;
+        }
+        zck_hash_update(&(zck->check_full_hash), src, rb);
+        zck_hash_update(&(zck->check_chunk_hash), src, rb);
+        if(!zck_comp_add_to_data(&(zck->comp), src, rb))
+            goto zck_read_error;
+    }
+    free(src);
+    return dc;
+zck_read_error:
+    free(src);
+    return -1;
+zck_hash_error:
+    free(src);
+    return -2;
+}
+
+ssize_t zck_read(zckCtx *zck, char *dst, size_t dst_size) {
+    VALIDATE_READ_SIZE(zck);
+
+    return comp_read(zck, dst, dst_size, 1);
 }
index 0b672066d634325ea5d50c9955b46cf240edbb4b..ca844e79c946c0d5c8749be7d1c591cd474e1f3e 100644 (file)
 
 #include "zck_private.h"
 
-static int zck_nocomp_init(zckComp *comp) {
+static int init(zckComp *comp) {
     return True;
 }
 
-static int zck_nocomp_end_chunk(zckComp *comp, char **dst, size_t *dst_size,
-                                int use_dict) {
+static int end_cchunk(zckComp *comp, char **dst, size_t *dst_size,
+                     int use_dict) {
     *dst = NULL;
     *dst_size = 0;
 
     return True;
 }
 
-static int zck_nocomp_comp(zckComp *comp, const char *src, const size_t src_size,
-                           char **dst, size_t *dst_size, int use_dict) {
+static ssize_t compress(zckComp *comp, const char *src, const size_t src_size,
+                        char **dst, size_t *dst_size, int use_dict) {
     *dst = zmalloc(src_size);
     if(dst == NULL) {
         zck_log(ZCK_LOG_ERROR, "Unable to allocate %lu bytes\n", src_size);
-        return False;
+        return -1;
     }
 
     memcpy(*dst, src, src_size);
     *dst_size = src_size;
 
-    return True;
+    return *dst_size;
 }
 
-static int zck_nocomp_decomp(zckComp *comp, const char *src,
-                             const size_t src_size, char **dst, size_t dst_size,
-                             int use_dict) {
-    *dst = zmalloc(src_size);
-    if(dst == NULL) {
-        zck_log(ZCK_LOG_ERROR, "Unable to allocate %lu bytes\n", src_size);
+
+static int decompress(zckComp *comp, const int use_dict) {
+    char *src = comp->data;
+    char src_size = comp->data_size;
+    comp->data = NULL;
+    comp->data_size = 0;
+    if(!zck_comp_add_to_dc(comp, src, src_size)) {
+        free(src);
         return False;
     }
+    free(src);
+    return True;
+}
 
-    memcpy(*dst, src, src_size);
-
+static int end_dchunk(zckComp *comp, const int use_dict, const size_t fd_size) {
     return True;
 }
 
-static int zck_nocomp_close(zckComp *comp) {
+static int close(zckComp *comp) {
     return True;
 }
 
 /* Nocomp doesn't support any parameters, so return error if setting a parameter
  * was attempted */
-static int zck_nocomp_set_parameter(zckComp *comp, int option, void *value) {
+static int set_parameter(zckComp *comp, int option, void *value) {
     zck_log(ZCK_LOG_ERROR, "Invalid compression parameter for ZCK_COMP_NONE\n");
     return False;
 }
 
 /* No default parameters to set when there's no compression */
-static int zck_nocomp_set_default_parameters(zckComp *comp) {
+static int set_default_parameters(zckComp *comp) {
     return True;
 }
 
 int zck_nocomp_setup(zckComp *comp) {
-    comp->init = zck_nocomp_init;
-    comp->set_parameter = zck_nocomp_set_parameter;
-    comp->compress = zck_nocomp_comp;
-    comp->end_chunk = zck_nocomp_end_chunk;
-    comp->decompress = zck_nocomp_decomp;
-    comp->close = zck_nocomp_close;
+    comp->init = init;
+    comp->set_parameter = set_parameter;
+    comp->compress = compress;
+    comp->end_cchunk = end_cchunk;
+    comp->decompress = decompress;
+    comp->end_dchunk = end_dchunk;
+    comp->close = close;
     comp->type = ZCK_COMP_NONE;
-    return zck_nocomp_set_default_parameters(comp);
+    return set_default_parameters(comp);
 }
index 51a9ed2c36888c5036c0b7b4eaebc50eef85dd85..9c33f56ef2ba5aaea07c279606fefa069a9ec17e 100644 (file)
@@ -61,28 +61,25 @@ static int init(zckComp *comp) {
 /* The zstd compression format doesn't allow streaming compression with a dict
  * unless you statically link to it.  If we have a dict, we do pseudo-streaming
  * compression where we buffer the data until the chunk ends. */
-static int compress(zckComp *comp, const char *src, const size_t src_size,
-                    char **dst, size_t *dst_size, int use_dict) {
-    if(comp->data == NULL)
-        comp->data = zmalloc(src_size);
-    else
-        comp->data = realloc(comp->data, comp->data_size + src_size);
-    if(comp->data == NULL) {
+static ssize_t compress(zckComp *comp, const char *src, const size_t src_size,
+                        char **dst, size_t *dst_size, int use_dict) {
+    comp->dc_data = realloc(comp->dc_data, comp->dc_data_size + src_size);
+    if(comp->dc_data == NULL) {
         zck_log(ZCK_LOG_ERROR, "Unable to allocate %lu bytes\n",
-                comp->data_size + src_size);
-        return False;
+                comp->dc_data_size + src_size);
+        return -1;
     }
-    memcpy(comp->data + comp->data_size, src, src_size);
+    memcpy(comp->dc_data + comp->dc_data_size, src, src_size);
     *dst = NULL;
     *dst_size = 0;
-    comp->data_size += src_size;
-    return True;
+    comp->dc_data_size += src_size;
+    return 0;
 }
 
-static int end_chunk(zckComp *comp, char **dst, size_t *dst_size,
-                     int use_dict) {
+static int end_cchunk(zckComp *comp, char **dst, size_t *dst_size,
+                      int use_dict) {
     VALIDATE(comp);
-    size_t max_size = ZSTD_compressBound(comp->data_size);
+    size_t max_size = ZSTD_compressBound(comp->dc_data_size);
     if(ZSTD_isError(max_size)) {
         zck_log(ZCK_LOG_ERROR, "zstd compression error: %s\n",
                 ZSTD_getErrorName(max_size));
@@ -97,15 +94,16 @@ static int end_chunk(zckComp *comp, char **dst, size_t *dst_size,
 
     if(use_dict && comp->cdict_ctx) {
         *dst_size = ZSTD_compress_usingCDict(comp->cctx, *dst, max_size,
-                                             comp->data, comp->data_size,
+                                             comp->dc_data, comp->dc_data_size,
                                              comp->cdict_ctx);
     } else {
-        *dst_size = ZSTD_compressCCtx(comp->cctx, *dst, max_size, comp->data,
-                                      comp->data_size, comp->level);
+        *dst_size = ZSTD_compressCCtx(comp->cctx, *dst, max_size, comp->dc_data,
+                                      comp->dc_data_size, comp->level);
     }
-    free(comp->data);
-    comp->data = NULL;
-    comp->data_size = 0;
+    free(comp->dc_data);
+    comp->dc_data = NULL;
+    comp->dc_data_size = 0;
+    comp->dc_data_loc = 0;
     if(ZSTD_isError(*dst_size)) {
         zck_log(ZCK_LOG_ERROR, "zstd compression error: %s\n",
                 ZSTD_getErrorName(*dst_size));
@@ -114,31 +112,49 @@ static int end_chunk(zckComp *comp, char **dst, size_t *dst_size,
     return True;
 }
 
-static int decompress(zckComp *comp, const char *src, const size_t src_size,
-                      char **dst, size_t dst_size, int use_dict) {
+static int decompress(zckComp *comp, const int use_dict) {
     VALIDATE(comp);
 
-    *dst = zmalloc(dst_size);
-    if(dst == NULL) {
-        zck_log(ZCK_LOG_ERROR, "Unable to allocate %lu bytes\n", dst_size);
-        return False;
-    }
+    return True;
+}
+
+static int end_dchunk(zckComp *comp, const int use_dict, const size_t fd_size) {
+    char *src = comp->data;
+    size_t src_size = comp->data_size;
+    comp->data = NULL;
+    comp->data_size = 0;
+
+    char *dst = zmalloc(fd_size);
+    if(dst == NULL)
+        goto decomp_error_1;
 
     size_t retval;
-    if(use_dict && comp->ddict_ctx)
-        retval = ZSTD_decompress_usingDDict(comp->dctx, *dst, dst_size, src,
+    zck_log(ZCK_LOG_DEBUG, "Decompressing %lu bytes to %lu bytes\n", src_size,
+            fd_size);
+    if(use_dict && comp->ddict_ctx) {
+        zck_log(ZCK_LOG_DEBUG, "Running decompression using dict\n");
+        retval = ZSTD_decompress_usingDDict(comp->dctx, dst, fd_size, src,
                                             src_size, comp->ddict_ctx);
-    else
-        retval = ZSTD_decompressDCtx(comp->dctx, *dst, dst_size, src,
-                                     src_size);
+    } else {
+        zck_log(ZCK_LOG_DEBUG, "Running decompression\n");
+        retval = ZSTD_decompressDCtx(comp->dctx, dst, fd_size, src, src_size);
+    }
+
     if(ZSTD_isError(retval)) {
-        free(*dst);
-        *dst = NULL;
         zck_log(ZCK_LOG_ERROR, "zstd decompression error: %s\n",
                 ZSTD_getErrorName(retval));
-        return False;
+        goto decomp_error_2;
     }
+    if(!zck_comp_add_to_dc(comp, dst, fd_size))
+        goto decomp_error_2;
+    free(dst);
+    free(src);
     return True;
+decomp_error_2:
+    free(dst);
+decomp_error_1:
+    free(src);
+    return False;
 }
 
 static int close(zckComp *comp) {
@@ -158,11 +174,6 @@ static int close(zckComp *comp) {
         ZSTD_freeDCtx(comp->dctx);
         comp->dctx = NULL;
     }
-    if(comp->data) {
-        free(comp->data);
-        comp->data = NULL;
-    }
-    comp->data_size = 0;
     return True;
 }
 
@@ -187,8 +198,9 @@ int zck_zstd_setup(zckComp *comp) {
     comp->init = init;
     comp->set_parameter = set_parameter;
     comp->compress = compress;
-    comp->end_chunk = end_chunk;
+    comp->end_cchunk = end_cchunk;
     comp->decompress = decompress;
+    comp->end_dchunk = end_dchunk;
     comp->close = close;
     comp->type = ZCK_COMP_ZSTD;
     return set_default_parameters(comp);
index d9eb8e881827a307aaffba2368d74f4ea3acc33b..33edf510ac23ff1bc7fc9e7f81a6802d73fe9bf1 100644 (file)
@@ -286,7 +286,6 @@ int zck_dl_copy_src_chunks(zckRange *info, zckCtx *src, zckCtx *tgt) {
             return False;
         if(!found && !zck_range_add(info, tgt_idx, tgt))
             return False;
-
         tgt_idx = tgt_idx->next;
     }
     return True;
@@ -446,7 +445,7 @@ int zck_dl_get_header(zckCtx *zck, zckDL *dl, char *url) {
     /* Download first hundred bytes and read magic and hash type */
     if(!zck_dl_bytes(dl, url, 100, start, &buffer_len))
         return False;
-    if(!zck_read_initial(zck, dl->dst_fd))
+    if(!zck_read_initial(zck))
         return False;
     start = tell_data(dl->dst_fd);
 
@@ -456,7 +455,7 @@ int zck_dl_get_header(zckCtx *zck, zckDL *dl, char *url) {
                      start, &buffer_len))
         return False;
     /* Read and store the index hash */
-    if(!zck_read_index_hash(zck, dl->dst_fd))
+    if(!zck_read_index_hash(zck))
         return False;
     start += zck->hash_type.digest_size;
     char *digest = zck_get_index_digest(zck);
@@ -467,7 +466,7 @@ int zck_dl_get_header(zckCtx *zck, zckDL *dl, char *url) {
     zck_log(ZCK_LOG_DEBUG, "\n");
 
     /* Read and store compression type and index size */
-    if(!zck_read_ct_is(zck, dl->dst_fd))
+    if(!zck_read_ct_is(zck))
         return False;
     start = tell_data(dl->dst_fd);
     zck_log(ZCK_LOG_DEBUG, "Index size: %llu\n", zck->index_size);
@@ -476,7 +475,7 @@ int zck_dl_get_header(zckCtx *zck, zckDL *dl, char *url) {
     if(!zck_dl_bytes(dl, url, zck->index_size, start,
                      &buffer_len))
         return False;
-    if(!zck_read_index(zck, dl->dst_fd))
+    if(!zck_read_index(zck))
         return False;
 
     /* Write zeros to rest of file */
index 671b3cf2116eb4fc3259fbd39f380b1b9fcf6b78..1cd1b1458c28e23969a04c118692b4d1e8028e82 100644 (file)
 
 #include "zck_private.h"
 
+#define VALIDATE(f)     if(!f) { \
+                            zck_log(ZCK_LOG_ERROR, \
+                                    "zckCtx not initialized\n"); \
+                            return False; \
+                        }
+
+#define VALIDATE_READ(f)    VALIDATE(f); \
+                            if(f->mode != ZCK_MODE_READ) { \
+                                zck_log(ZCK_LOG_ERROR, \
+                                        "zckCtx not opened for reading\n"); \
+                                return False; \
+                            }
+
+#define VALIDATE_WRITE(f)   VALIDATE(f); \
+                            if(f->mode != ZCK_MODE_WRITE) { \
+                                zck_log(ZCK_LOG_ERROR, \
+                                        "zckCtx not opened for writing\n"); \
+                                return False; \
+                            }
+
+int zck_read_initial(zckCtx *zck) {
+    VALIDATE_READ(zck);
 
-int zck_read_initial(zckCtx *zck, int src_fd) {
     char *header = zmalloc(5 + MAX_COMP_SIZE);
     size_t length = 0;
     if(header == NULL) {
@@ -43,7 +64,7 @@ int zck_read_initial(zckCtx *zck, int src_fd) {
     }
 
     zck_log(ZCK_LOG_DEBUG, "Reading magic and hash type\n");
-    if(!read_data(src_fd, header, 5 + MAX_COMP_SIZE)) {
+    if(!read_data(zck->fd, header, 5 + MAX_COMP_SIZE)) {
         free(header);
         return False;
     }
@@ -61,14 +82,18 @@ int zck_read_initial(zckCtx *zck, int src_fd) {
         return False;
     if(!zck_hash_setup(&(zck->hash_type), hash_type))
         return False;
-    if(!seek_data(src_fd, length, SEEK_SET))
+    if(!zck_hash_init(&(zck->check_full_hash), &(zck->hash_type)))
+        return False;
+    if(!seek_data(zck->fd, length, SEEK_SET))
         return False;
     zck->header_string = header;
     zck->header_size = length;
     return True;
 }
 
-int zck_read_index_hash(zckCtx *zck, int src_fd) {
+int zck_read_index_hash(zckCtx *zck) {
+    VALIDATE_READ(zck);
+
     if(zck->header_string == NULL) {
         zck_log(ZCK_LOG_ERROR,
                 "Reading index hash before initial bytes are read\n");
@@ -91,7 +116,7 @@ int zck_read_index_hash(zckCtx *zck, int src_fd) {
         return False;
     }
     zck_log(ZCK_LOG_DEBUG, "Reading index hash\n");
-    if(!read_data(src_fd, digest, zck->hash_type.digest_size)) {
+    if(!read_data(zck->fd, digest, zck->hash_type.digest_size)) {
         free(digest);
         free(header);
         return False;
@@ -106,7 +131,9 @@ int zck_read_index_hash(zckCtx *zck, int src_fd) {
     return True;
 }
 
-int zck_read_ct_is(zckCtx *zck, int src_fd) {
+int zck_read_ct_is(zckCtx *zck) {
+    VALIDATE_READ(zck);
+
     if(zck->header_string == NULL) {
         zck_log(ZCK_LOG_ERROR,
                 "Reading compression type before hash type is read\n");
@@ -124,7 +151,7 @@ int zck_read_ct_is(zckCtx *zck, int src_fd) {
         return False;
     }
     zck_log(ZCK_LOG_DEBUG, "Reading compression type and index size\n");
-    if(!read_data(src_fd, header + length, MAX_COMP_SIZE*2))
+    if(!read_data(zck->fd, header + length, MAX_COMP_SIZE*2))
         return False;
 
     int tmp = 0;
@@ -142,14 +169,16 @@ int zck_read_ct_is(zckCtx *zck, int src_fd) {
         return False;
     zck->index_size = tmp;
 
-    if(!seek_data(src_fd, length, SEEK_SET))
+    if(!seek_data(zck->fd, length, SEEK_SET))
         return False;
     zck->header_string = header;
     zck->header_size = length;
     return True;
 }
 
-int zck_read_index(zckCtx *zck, int src_fd) {
+int zck_read_index(zckCtx *zck) {
+    VALIDATE_READ(zck);
+
     char *index = zmalloc(zck->index_size);
     if(!index) {
         zck_log(ZCK_LOG_ERROR, "Unable to allocate %lu bytes\n",
@@ -157,7 +186,7 @@ int zck_read_index(zckCtx *zck, int src_fd) {
         return False;
     }
     zck_log(ZCK_LOG_DEBUG, "Reading index\n");
-    if(!read_data(src_fd, index, zck->index_size)) {
+    if(!read_data(zck->fd, index, zck->index_size)) {
         free(index);
         return False;
     }
@@ -169,19 +198,18 @@ int zck_read_index(zckCtx *zck, int src_fd) {
     return True;
 }
 
-int zck_read_header(zckCtx *zck, int src_fd) {
-    if(zck == NULL) {
-        zck_log(ZCK_LOG_ERROR, "zckCtx not initialized\n");
+int zck_read_header(zckCtx *zck) {
+    VALIDATE_READ(zck);
+
+    if(!zck_read_initial(zck))
         return False;
-    }
-    zck->fd = src_fd;
-    if(!zck_read_initial(zck, src_fd))
+    if(!zck_read_index_hash(zck))
         return False;
-    if(!zck_read_index_hash(zck, src_fd))
+    if(!zck_read_ct_is(zck))
         return False;
-    if(!zck_read_ct_is(zck, src_fd))
+    if(!zck_read_index(zck))
         return False;
-    if(!zck_read_index(zck, src_fd))
+    if(!zck_import_dict(zck))
         return False;
     return True;
 }
@@ -230,6 +258,8 @@ int zck_header_create(zckCtx *zck) {
 }
 
 int zck_write_header(zckCtx *zck) {
+    VALIDATE_WRITE(zck);
+
     if(!write_data(zck->fd, zck->header_string, zck->header_size))
         return False;
     return True;
index ae99b4e14c4ffba2fd0bbaa19f8d24fde9f2e6d9..bde56be617a9b258804a609825fa550113b6ca9b 100644 (file)
 
 #include "zck_private.h"
 
-int read_data(int fd, char *data, size_t length) {
+ssize_t read_data(int fd, char *data, size_t length) {
     if(length == 0)
-        return True;
+        return 0;
     if(data == NULL) {
         zck_log(ZCK_LOG_ERROR, "Unable to read to NULL data pointer\n");
-        return False;
+        return -1;
     }
     ssize_t read_bytes = read(fd, data, length);
     if(read_bytes == -1) {
         zck_log(ZCK_LOG_ERROR, "Error reading data: %s\n", strerror(errno));
-        return False;
-    } else if(read_bytes != length) {
-        zck_log(ZCK_LOG_ERROR, "Short read\n");
-        return False;
+        return -1;
     }
-    return True;
+    return read_bytes;
 }
 
 int write_data(int fd, const char *data, size_t length) {
@@ -110,8 +107,9 @@ int seek_data(int fd, off_t offset, int whence) {
     return True;
 }
 
-size_t tell_data(int fd) {
-    return lseek(fd, 0, SEEK_CUR);
+ssize_t tell_data(int fd) {
+    ssize_t loc = lseek(fd, 0, SEEK_CUR);
+    return loc;
 }
 
 int chunks_from_temp(zckCtx *zck) {
index 6b47440a2e6fe7872a22e88547ca84bf9c234d6f..50b45c87165dd0e66b717c8e8a610f76f14286d5 100644 (file)
                             return False; \
                         }
 
-int zck_write_file(zckCtx *zck) {
+int zck_close(zckCtx *zck) {
     VALIDATE(zck);
-    zck_index_finalize(zck);
-    zck_log(ZCK_LOG_DEBUG, "Writing header\n");
-    if(!zck_write_header(zck))
-        return False;
-    zck_log(ZCK_LOG_DEBUG, "Writing index\n");
-    if(!zck_write_index(zck))
-        return False;
-    zck_log(ZCK_LOG_DEBUG, "Writing chunks\n");
-    if(!chunks_from_temp(zck))
-        return False;
-    zck_log(ZCK_LOG_DEBUG, "Finished writing file, cleaning up\n");
-    zck_index_free(zck);
-    zck_comp_close(zck);
-    if(zck->temp_fd) {
-        close(zck->temp_fd);
-        zck->temp_fd = 0;
-    }
 
+    if(zck->mode == ZCK_MODE_WRITE) {
+        zck_index_finalize(zck);
+        zck_log(ZCK_LOG_DEBUG, "Writing header\n");
+        if(!zck_write_header(zck))
+            return False;
+        zck_log(ZCK_LOG_DEBUG, "Writing index\n");
+        if(!zck_write_index(zck))
+            return False;
+        zck_log(ZCK_LOG_DEBUG, "Writing chunks\n");
+        if(!chunks_from_temp(zck))
+            return False;
+        zck_log(ZCK_LOG_DEBUG, "Finished writing file, cleaning up\n");
+        zck_index_free(zck);
+        zck_comp_close(zck);
+        if(zck->temp_fd) {
+            close(zck->temp_fd);
+            zck->temp_fd = 0;
+        }
+    }
     return True;
 }
 
@@ -78,6 +80,7 @@ void zck_clear(zckCtx *zck) {
     zck_comp_close(zck);
     zck_hash_close(&(zck->full_hash));
     zck_hash_close(&(zck->check_full_hash));
+    zck_hash_close(&(zck->check_chunk_hash));
     zck_clear_work_index(zck);
     if(zck->full_hash_digest) {
         free(zck->full_hash_digest);
@@ -111,6 +114,57 @@ zckCtx *zck_create() {
     return zck;
 }
 
+zckCtx *zck_init_adv_read (int src_fd) {
+    zckCtx *zck = zck_create();
+    if(zck == NULL)
+        return NULL;
+
+    zck->mode = ZCK_MODE_READ;
+    zck->fd = src_fd;
+    return zck;
+}
+
+zckCtx *zck_init_read (int src_fd) {
+    zckCtx *zck = zck_init_adv_read(src_fd);
+    if(zck == NULL)
+        return NULL;
+
+    if(!zck_read_header(zck))
+        return False;
+
+    return zck;
+}
+
+zckCtx *zck_init_write (int dst_fd) {
+    zckCtx *zck = zck_create();
+    if(zck == NULL)
+        return NULL;
+
+    zck->mode = ZCK_MODE_WRITE;
+    zck->temp_fd = zck_get_tmp_fd();
+    if(zck->temp_fd < 0)
+        goto iw_error;
+
+    /* Set defaults */
+#ifdef ZCHUNK_ZSTD
+    if(!zck_set_compression_type(zck, ZCK_COMP_ZSTD))
+        goto iw_error;
+#else
+    if(!zck_set_compression_type(zck, ZCK_COMP_NONE))
+        goto iw_error;
+#endif
+    if(!zck_set_full_hash_type(zck, ZCK_HASH_SHA256))
+        goto iw_error;
+    if(!zck_set_chunk_hash_type(zck, ZCK_HASH_SHA1))
+        goto iw_error;
+    zck->fd = dst_fd;
+
+    return zck;
+iw_error:
+    free(zck);
+    return NULL;
+}
+
 int zck_set_full_hash_type(zckCtx *zck, int hash_type) {
     VALIDATE(zck);
     zck_log(ZCK_LOG_INFO, "Setting full hash to %s\n",
@@ -197,6 +251,13 @@ ssize_t zck_get_header_length(zckCtx *zck) {
     return zck->header_size + zck->index_size;
 }
 
+ssize_t zck_get_data_length(zckCtx *zck) {
+    zckIndexItem *idx = zck->index.first;
+    while(idx->next != NULL)
+        idx = idx->next;
+    return idx->start + idx->comp_length;
+}
+
 int zck_get_tmp_fd() {
     int temp_fd;
     char *fname = NULL;
@@ -231,39 +292,26 @@ int zck_get_tmp_fd() {
     return temp_fd;
 }
 
-int zck_init_write (zckCtx *zck, int dst_fd) {
+int zck_import_dict(zckCtx *zck) {
     VALIDATE(zck);
-    zck_clear(zck);
-    memset(zck, 0, sizeof(zckCtx));
 
-    zck->temp_fd = zck_get_tmp_fd();
-    if(zck->temp_fd < 0)
-        return False;
-
-    /* Set defaults */
-#ifdef ZCHUNK_ZSTD
-    zck_set_compression_type(zck, ZCK_COMP_ZSTD);
-#else
-    zck_set_compression_type(zck, ZCK_COMP_NONE);
-#endif
-    if(!zck_set_full_hash_type(zck, ZCK_HASH_SHA256))
-        return False;
-    if(!zck_set_chunk_hash_type(zck, ZCK_HASH_SHA1))
-        return False;
-    zck->fd = dst_fd;
+    size_t size = zck->index.first->length;
 
-    return True;
-}
+    /* No dict */
+    if(size == 0)
+        return True;
 
-int zck_import_dict(zckCtx *zck, char *data, size_t size) {
-    VALIDATE(zck);
-    if(data == NULL || size == 0) {
-        zck_log(ZCK_LOG_ERROR,
-                "Attempting to initialize an empty compression dictionary\n");
+    char *data = zmalloc(size);
+    if(data == NULL) {
+        zck_log(ZCK_LOG_ERROR, "Unable to allocate %lu bytes\n", size);
         return False;
     }
-    zck_log(ZCK_LOG_DEBUG, "Closing compression\n");
-    if(!zck_comp_close(zck))
+    if(comp_read(zck, data, size, 0) != size) {
+        zck_log(ZCK_LOG_ERROR, "Error reading compressed dict\n");
+        return False;
+    }
+    zck_log(ZCK_LOG_DEBUG, "Resetting compression\n");
+    if(!zck_comp_reset(zck))
         return False;
     zck_log(ZCK_LOG_DEBUG, "setting dict 1\n");
     if(!zck_set_comp_parameter(zck, ZCK_COMMON_DICT, data))
@@ -271,9 +319,10 @@ int zck_import_dict(zckCtx *zck, char *data, size_t size) {
     zck_log(ZCK_LOG_DEBUG, "setting dict 2\n");
     if(!zck_set_comp_parameter(zck, ZCK_COMMON_DICT_SIZE, &size))
         return False;
-    zck_log(ZCK_LOG_DEBUG, "Initializing\n");
     if(!zck_comp_init(zck))
         return False;
+    free(data);
+
     return True;
 }
 
@@ -321,93 +370,58 @@ int zck_validate_chunk(zckCtx *zck, char *data, size_t size, zckIndexItem *idx,
     return True;
 }
 
-int zck_validate_file(zckCtx *zck) {
+int zck_validate_current_chunk(zckCtx *zck) {
     VALIDATE(zck);
-    char *digest = zck_hash_finalize(&(zck->check_full_hash));
+    char *digest = zck_hash_finalize(&(zck->check_chunk_hash));
     if(digest == NULL) {
         zck_log(ZCK_LOG_ERROR,
-                "Unable to calculate %s checksum for full file\n");
+                "Unable to calculate %s checksum for chunk\n");
         return False;
     }
-    zck_log(ZCK_LOG_DEBUG, "Checking data checksum\n");
-    if(memcmp(digest, zck->full_hash_digest, zck->hash_type.digest_size) != 0) {
+    zck_log(ZCK_LOG_DEBUG, "Checking chunk checksum\n");
+    zck_log(ZCK_LOG_DEBUG, "Expected chunk checksum: ");
+    for(int i=0; i<zck->chunk_hash_type.digest_size; i++)
+        zck_log(ZCK_LOG_DEBUG, "%02x",
+                (unsigned char)zck->comp.data_idx->digest[i]);
+    zck_log(ZCK_LOG_DEBUG, "\n");
+    zck_log(ZCK_LOG_DEBUG, "Calculated chunk checksum: ");
+    for(int i=0; i<zck->chunk_hash_type.digest_size; i++)
+        zck_log(ZCK_LOG_DEBUG, "%02x", (unsigned char)digest[i]);
+    zck_log(ZCK_LOG_DEBUG, "\n");
+    if(memcmp(digest, zck->comp.data_idx->digest,
+              zck->chunk_hash_type.digest_size) != 0) {
         free(digest);
-        zck_log(ZCK_LOG_ERROR, "Data checksum failed!\n");
+        zck_log(ZCK_LOG_ERROR, "Chunk checksum failed!\n");
         return False;
     }
-    zck_log(ZCK_LOG_DEBUG, "Data checksum valid\n");
+    zck_log(ZCK_LOG_DEBUG, "Chunk checksum valid\n");
     free(digest);
     return True;
 }
 
-int zck_decompress_to_file(zckCtx *zck, int src_fd, int dst_fd) {
+int zck_validate_file(zckCtx *zck) {
     VALIDATE(zck);
-    if(!zck_read_header(zck, src_fd))
-        return False;
-    if(!zck_hash_init(&(zck->check_full_hash), &(zck->hash_type)))
-        return False;
-
-    int start = lseek(src_fd, 0, SEEK_CUR);
-    if(start == -1) {
-        zck_log(ZCK_LOG_ERROR, "Unable to set starting point source file: %s\n",
-                strerror(errno));
+    char *digest = zck_hash_finalize(&(zck->check_full_hash));
+    if(digest == NULL) {
+        zck_log(ZCK_LOG_ERROR,
+                "Unable to calculate %s checksum for full file\n");
         return False;
     }
-
-    zckIndex *index = zck_get_index(zck);
-    zckIndexItem *idx = index->first;
-
-    /* Check if zck file is empty */
-    for(int count=0; idx; count++) {
-        size_t csize = idx->comp_length;
-        size_t size = idx->length;
-        char *cdata;
-
-        if(csize == 0) {
-            idx = idx->next;
-            continue;
-        }
-
-        cdata = zmalloc(csize);
-        if(cdata == NULL) {
-            zck_log(ZCK_LOG_ERROR, "Unable to allocate %lu bytes\n", csize);
-            return False;
-        }
-        if(!seek_data(src_fd, start + idx->start, SEEK_SET))
-            return False;
-        if(!read_data(src_fd, cdata, csize)) {
-            free(cdata);
-            zck_log(ZCK_LOG_ERROR, "Error reading chunk %i\n", count);
-            return False;
-        }
-        if(!zck_validate_chunk(zck, cdata, csize, idx, count)) {
-            free(cdata);
-            return False;
-        }
-
-        char *data = NULL;
-        if(!zck_read(zck, cdata, csize, &data, size)) {
-            free(cdata);
-            zck_log(ZCK_LOG_ERROR, "Unable to decompress chunk %i\n", count);
-            return False;
-        }
-        free(cdata);
-        if(count == 0) {
-            if(!zck_import_dict(zck, data, size)) {
-                free(data);
-                return False;
-            }
-        } else {
-            if(!write_data(dst_fd, data, size)) {
-                free(data);
-                zck_log(ZCK_LOG_ERROR, "Unable to write chunk %i\n", count);
-                return False;
-            }
-        }
-        free(data);
-        idx = idx->next;
-    }
-    if(!zck_validate_file(zck))
+    zck_log(ZCK_LOG_DEBUG, "Checking data checksum\n");
+    zck_log(ZCK_LOG_INFO, "Excpected data checksum: ");
+    for(int i=0; i<zck->hash_type.digest_size; i++)
+        zck_log(ZCK_LOG_INFO, "%02x", (unsigned char)zck->full_hash_digest[i]);
+    zck_log(ZCK_LOG_INFO, "\n");
+    zck_log(ZCK_LOG_INFO, "Calculated data checksum: ");
+    for(int i=0; i<zck->hash_type.digest_size; i++)
+        zck_log(ZCK_LOG_INFO, "%02x", (unsigned char)digest[i]);
+    zck_log(ZCK_LOG_INFO, "\n");
+    if(memcmp(digest, zck->full_hash_digest, zck->hash_type.digest_size) != 0) {
+        free(digest);
+        zck_log(ZCK_LOG_ERROR, "Data checksum failed!\n");
         return False;
+    }
+    zck_log(ZCK_LOG_DEBUG, "Data checksum valid\n");
+    free(digest);
     return True;
 }
index f46f1ec04d758bca7113d5141715335052d8b530..de365ce3baf41a7ff2b2306ea9410883a1f3c3d3 100644 (file)
@@ -9,20 +9,23 @@
 /* Maximum string length for a compressed size_t */
 #define MAX_COMP_SIZE (((sizeof(size_t) * 8) / 7) + 1)
 
+#define ZCK_MODE_READ 0
+#define ZCK_MODE_WRITE 1
+
 #define zmalloc(x) calloc(1, x)
 
 struct zckComp;
 
 typedef int (*finit)(struct zckComp *comp);
 typedef int (*fparam)(struct zckComp *comp, int option, void *value);
-typedef int (*fcompend)(struct zckComp *comp, char **dst, size_t *dst_size,
-                        int use_dict);
-typedef int (*fcomp)(struct zckComp *comp, const char *src,
-                     const size_t src_size, char **dst, size_t *dst_size,
-                     int use_dict);
-typedef int (*fdecomp)(struct zckComp *comp, const char *src,
-                       const size_t src_size, char **dst, size_t dst_size,
-                       int use_dict);
+typedef int (*fccompend)(struct zckComp *comp, char **dst, size_t *dst_size,
+                         int use_dict);
+typedef ssize_t (*fcomp)(struct zckComp *comp, const char *src,
+                         const size_t src_size, char **dst, size_t *dst_size,
+                         int use_dict);
+typedef int (*fdecomp)(struct zckComp *comp, const int use_dict);
+typedef int (*fdcompend)(struct zckComp *comp, const int use_dict,
+                         const size_t fd_size);
 typedef int (*fcclose)(struct zckComp *comp);
 
 typedef enum log_type log_type;
@@ -76,18 +79,26 @@ typedef struct zckComp {
 
     char *data;
     size_t data_size;
+    size_t data_loc;
+    zckIndexItem *data_idx;
+    int data_eof;
+    char *dc_data;
+    size_t dc_data_size;
+    size_t dc_data_loc;
 
     finit init;
     fparam set_parameter;
     fcomp compress;
-    fcompend end_chunk;
+    fccompend end_cchunk;
     fdecomp decompress;
+    fdcompend end_dchunk;
     fcclose close;
 } zckComp;
 
 typedef struct zckCtx {
     int temp_fd;
     int fd;
+    int mode;
 
     char *full_hash_digest;
     char *header_string;
@@ -97,17 +108,24 @@ typedef struct zckCtx {
     zckIndex index;
     zckIndexItem *work_index_item;
     zckHash work_index_hash;
+
     char *index_digest;
     zckHash full_hash;
     zckHash check_full_hash;
+    zckHash check_chunk_hash;
     zckComp comp;
     zckHashType hash_type;
     zckHashType chunk_hash_type;
+
+    char *data;
+    size_t data_size;
 } zckCtx;
 
 const char *zck_hash_name_from_type(int hash_type);
 int zck_get_tmp_fd();
+int zck_import_dict(zckCtx *zck);
 int zck_validate_file(zckCtx *zck);
+int zck_validate_current_chunk(zckCtx *zck);
 void zck_clear_work_index(zckCtx *zck);
 
 /* hash/hash.h */
@@ -130,25 +148,32 @@ void zck_index_clean(zckIndex *index);
 void zck_index_free(zckCtx *zck);
 void zck_index_free_item(zckIndexItem **item);
 int zck_write_index(zckCtx *zck);
+zckIndexItem *zck_get_index_of_loc(zckIndex *index, size_t loc);
 
 /* io.c */
 int seek_data(int fd, off_t offset, int whence);
-size_t tell_data(int fd);
-int read_data(int fd, char *data, size_t length);
+ssize_t tell_data(int fd);
+ssize_t read_data(int fd, char *data, size_t length);
 int write_data(int fd, const char *data, size_t length);
 int write_comp_size(int fd, size_t val);
 int read_comp_size(int fd, size_t *val, size_t *length);
 int chunks_from_temp(zckCtx *zck);
 
 /* header.c */
-int zck_read_initial(zckCtx *zck, int src_fd);
-int zck_read_index_hash(zckCtx *zck, int src_fd);
-int zck_read_ct_is(zckCtx *zck, int src_fd);
-int zck_read_index(zckCtx *zck, int src_fd);
+int zck_read_initial(zckCtx *zck);
+int zck_read_index_hash(zckCtx *zck);
+int zck_read_ct_is(zckCtx *zck);
+int zck_read_index(zckCtx *zck);
+int zck_read_header(zckCtx *zck);
 int zck_header_create(zckCtx *zck);
-int zck_read_header(zckCtx *zck, int src_fd);
 int zck_write_header(zckCtx *zck);
 
+/* comp/comp.c */
+int zck_comp_add_to_dc(zckComp *comp, const char *src, size_t src_size);
+int zck_comp_add_to_data(zckComp *comp, const char *src, size_t src_size);
+size_t zck_comp_read_from_dc(zckComp *comp, char *dst, size_t dst_size);
+ssize_t comp_read(zckCtx *zck, char *dst, size_t dst_size, int use_dict);
+
 /* dl/range.c */
 char *zck_range_get_char(zckRangeItem **range, int max_ranges);
 int zck_range_add(zckRange *info, zckIndexItem *idx, zckCtx *zck);
@@ -168,7 +193,6 @@ int zck_compint_to_int(int *val, const char *compint, size_t *length);
 int zck_compint_to_size(size_t *val, const char *compint, size_t *length);
 
 
-
 /* log.c */
 void zck_log(log_type lt, const char *format, ...);
 #endif