Move functions out of zck.h to more appropriate files
authorJonathan Dieter <jdieter@gmail.com>
Wed, 6 Jun 2018 08:36:18 +0000 (11:36 +0300)
committerJonathan Dieter <jdieter@gmail.com>
Wed, 6 Jun 2018 08:36:18 +0000 (11:36 +0300)
Signed-off-by: Jonathan Dieter <jdieter@gmail.com>
src/lib/hash/hash.c
src/lib/header.c
src/lib/index/index_read.c
src/lib/zck.c
src/lib/zck_private.h

index 61d0213c5c964d4426e6cead2b07498e4f87467e..29f5560801e6b070be12db0151510388463d4d3c 100644 (file)
                             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; \
+                            }
+/* This needs to be updated to the largest hash size every time a new hash type
+ * is added */
+int get_max_hash_size() {
+    return SHA256_DIGEST_SIZE;
+}
+
+
+
 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\0";
 
 const static char *HASH_NAME[] = {
@@ -46,10 +67,83 @@ const static char *HASH_NAME[] = {
     "SHA-256"
 };
 
-/* This needs to be updated to the largest hash size every time a new hash type
- * is added */
-int get_max_hash_size() {
-    return SHA256_DIGEST_SIZE;
+static int validate_checksums(zckCtx *zck, zck_log_type bad_checksums) {
+    VALIDATE_READ(zck);
+    char buf[BUF_SIZE];
+
+    if(zck->data_offset == 0) {
+        zck_log(ZCK_LOG_ERROR, "Header hasn't been read yet\n");
+        return 0;
+    }
+
+    hash_close(&(zck->check_full_hash));
+    if(!hash_init(&(zck->check_full_hash), &(zck->hash_type)))
+        return 0;
+
+    if(!seek_data(zck->fd, zck->data_offset, SEEK_SET))
+        return 0;
+
+    /* Check each chunk checksum */
+    int all_good = True;
+    for(zckIndexItem *idx = zck->index.first; idx; idx = idx->next) {
+        if(idx == zck->index.first && idx->length == 0) {
+            idx->valid = 1;
+            continue;
+        }
+
+        if(!hash_init(&(zck->check_chunk_hash), &(zck->chunk_hash_type)))
+            return 0;
+
+        size_t rlen = 0;
+        while(rlen < idx->comp_length) {
+            size_t rsize = BUF_SIZE;
+            if(BUF_SIZE > idx->comp_length - rlen)
+                rsize = idx->comp_length - rlen;
+            if(read_data(zck->fd, buf, rsize) != rsize)
+                zck_log(ZCK_LOG_DEBUG, "No more data\n");
+            if(!hash_update(&(zck->check_chunk_hash), buf, rsize))
+                return 0;
+            if(!hash_update(&(zck->check_full_hash), buf, rsize))
+                return 0;
+            rlen += rsize;
+        }
+        int valid_chunk = validate_chunk(zck, idx, bad_checksums);
+        if(!valid_chunk)
+            return 0;
+        idx->valid = valid_chunk;
+        if(all_good && valid_chunk != 1)
+            all_good = False;
+    }
+    int valid_file = -1;
+    if(all_good) {
+        /* Check data checksum */
+        valid_file = validate_file(zck, bad_checksums);
+        if(!valid_file)
+            return 0;
+
+        /* If data checksum failed, invalidate *all* chunks */
+        if(valid_file == -1)
+            for(zckIndexItem *idx = zck->index.first; idx; idx = idx->next)
+                idx->valid = -1;
+    }
+
+    /* Go back to beginning of data section */
+    if(!seek_data(zck->fd, zck->data_offset, SEEK_SET))
+        return 0;
+
+    /* Reinitialize data checksum */
+    if(!hash_init(&(zck->check_full_hash), &(zck->hash_type)))
+        return 0;
+
+    return valid_file;
+}
+
+char *get_digest_string(const char *digest, int size) {
+    char *str = zmalloc(size*2+1);
+
+    for(int i=0; i<size; i++)
+        snprintf(str + i*2, 3, "%02x", (unsigned char)digest[i]);
+    return str;
 }
 
 int hash_setup(zckHashType *ht, int h) {
@@ -191,6 +285,102 @@ int set_chunk_hash_type(zckCtx *zck, int hash_type) {
     return True;
 }
 
+/* Validate chunk, returning -1 if checksum fails, 1 if good, 0 if error */
+int validate_chunk(zckCtx *zck, zckIndexItem *idx,
+                       zck_log_type bad_checksum) {
+    VALIDATE(zck);
+    if(idx == NULL) {
+        zck_log(ZCK_LOG_ERROR, "Index not initialized\n");
+        return 0;
+    }
+
+    char *digest = hash_finalize(&(zck->check_chunk_hash));
+    if(digest == NULL) {
+        zck_log(ZCK_LOG_ERROR,
+                "Unable to calculate %s checksum for chunk\n");
+        return 0;
+    }
+    if(idx->comp_length == 0)
+        memset(digest, 0, idx->digest_size);
+    zck_log(ZCK_LOG_DEBUG, "Checking chunk checksum\n");
+    char *pdigest = zck_get_chunk_digest(idx);
+    zck_log(ZCK_LOG_DEBUG, "Expected chunk checksum:   %s\n", pdigest);
+    free(pdigest);
+    pdigest = get_digest_string(digest, idx->digest_size);
+    zck_log(ZCK_LOG_DEBUG, "Calculated chunk checksum: %s\n", pdigest);
+    free(pdigest);
+    if(memcmp(digest, idx->digest, idx->digest_size) != 0) {
+        free(digest);
+        zck_log(bad_checksum, "Chunk checksum failed!\n");
+        return -1;
+    }
+    zck_log(ZCK_LOG_DEBUG, "Chunk checksum valid\n");
+    free(digest);
+    return 1;
+}
+
+int validate_current_chunk(zckCtx *zck) {
+    VALIDATE(zck);
+
+    return validate_chunk(zck, zck->comp.data_idx, ZCK_LOG_ERROR);
+}
+
+int validate_file(zckCtx *zck, zck_log_type bad_checksums) {
+    VALIDATE(zck);
+    char *digest = hash_finalize(&(zck->check_full_hash));
+    if(digest == NULL) {
+        zck_log(ZCK_LOG_ERROR,
+                "Unable to calculate %s checksum for full file\n");
+        return 0;
+    }
+    zck_log(ZCK_LOG_DEBUG, "Checking data checksum\n");
+    char *cks = get_digest_string(zck->full_hash_digest,
+                                  zck->hash_type.digest_size);
+    zck_log(ZCK_LOG_DEBUG, "Expected data checksum:   %s\n", cks);
+    free(cks);
+    cks = get_digest_string(digest, zck->hash_type.digest_size);
+    zck_log(ZCK_LOG_DEBUG, "Calculated data checksum: %s\n", cks);
+    free(cks);
+    if(memcmp(digest, zck->full_hash_digest, zck->hash_type.digest_size) != 0) {
+        free(digest);
+        zck_log(bad_checksums, "Data checksum failed!\n");
+        return -1;
+    }
+    zck_log(ZCK_LOG_DEBUG, "Data checksum valid\n");
+    free(digest);
+    return 1;
+}
+
+int validate_header(zckCtx *zck) {
+    VALIDATE(zck);
+    char *digest = hash_finalize(&(zck->check_full_hash));
+    if(digest == NULL) {
+        zck_log(ZCK_LOG_ERROR,
+                "Unable to calculate %s checksum for header\n");
+        return 0;
+    }
+    zck_log(ZCK_LOG_DEBUG, "Checking header checksum\n");
+    char *cks = get_digest_string(zck->header_digest,
+                                  zck->hash_type.digest_size);
+    zck_log(ZCK_LOG_DEBUG, "Expected header checksum:   %s\n", cks);
+    free(cks);
+    cks = get_digest_string(digest, zck->hash_type.digest_size);
+    zck_log(ZCK_LOG_DEBUG, "Calculated header checksum: %s\n", cks);
+    free(cks);
+    if(memcmp(digest, zck->header_digest, zck->hash_type.digest_size) != 0) {
+        free(digest);
+        zck_log(ZCK_LOG_ERROR, "Header checksum failed!\n");
+        return -1;
+    }
+    zck_log(ZCK_LOG_DEBUG, "Header checksum valid\n");
+    free(digest);
+
+    if(!hash_init(&(zck->check_full_hash), &(zck->hash_type)))
+        return 0;
+
+    return 1;
+}
+
 /* Returns 1 if data hash matches, -1 if it doesn't and 0 if error */
 int PUBLIC zck_validate_data_checksum(zckCtx *zck) {
     hash_close(&(zck->check_full_hash));
@@ -225,3 +415,55 @@ const char PUBLIC *zck_hash_name_from_type(int hash_type) {
     }
     return HASH_NAME[hash_type];
 }
+
+int PUBLIC zck_get_full_hash_type(zckCtx *zck) {
+    if(zck == NULL)
+        return -1;
+    return zck->hash_type.type;
+}
+
+ssize_t PUBLIC zck_get_full_digest_size(zckCtx *zck) {
+    if(zck == NULL)
+        return -1;
+    return zck->hash_type.digest_size;
+}
+
+int PUBLIC zck_get_chunk_hash_type(zckCtx *zck) {
+    if(zck == NULL)
+        return -1;
+    return zck->index.hash_type;
+}
+
+ssize_t PUBLIC zck_get_chunk_digest_size(zckCtx *zck) {
+    if(zck == NULL)
+        return -1;
+    return zck->index.digest_size;
+}
+
+char PUBLIC *zck_get_header_digest(zckCtx *zck) {
+    if(zck == NULL)
+        return NULL;
+    return get_digest_string(zck->header_digest, zck->hash_type.digest_size);
+}
+
+char PUBLIC *zck_get_data_digest(zckCtx *zck) {
+    if(zck == NULL)
+        return NULL;
+    return get_digest_string(zck->full_hash_digest, zck->hash_type.digest_size);
+}
+
+char PUBLIC *zck_get_chunk_digest(zckIndexItem *item) {
+    if(item == NULL)
+        return NULL;
+    return get_digest_string(item->digest, item->digest_size);
+}
+
+/* Returns 1 if all chunks are valid, -1 if even one isn't and 0 if error */
+int PUBLIC zck_find_valid_chunks(zckCtx *zck) {
+    return validate_checksums(zck, ZCK_LOG_DEBUG);
+}
+
+/* Returns 1 if all checksums matched, -1 if even one doesn't and 0 if error */
+int PUBLIC zck_validate_checksums(zckCtx *zck) {
+    return validate_checksums(zck, ZCK_LOG_WARNING);
+}
index 485c3b2b7c783ec660930bcd9a47296ea65fc56a..c6fda47c49bca34d2f0c74138d07e6da1f677d2a 100644 (file)
@@ -532,3 +532,26 @@ int PUBLIC zck_read_header(zckCtx *zck) {
         return False;
     return True;
 }
+
+ssize_t PUBLIC zck_get_header_length(zckCtx *zck) {
+    if(zck == NULL)
+        return -1;
+    return zck->lead_size + zck->header_length;
+}
+
+ssize_t PUBLIC zck_get_lead_length(zckCtx *zck) {
+    if(zck == NULL)
+        return -1;
+    return zck->lead_size;
+}
+
+ssize_t PUBLIC zck_get_data_length(zckCtx *zck) {
+    zckIndexItem *idx = zck->index.first;
+    while(idx->next != NULL)
+        idx = idx->next;
+    return idx->start + idx->comp_length;
+}
+
+ssize_t PUBLIC zck_get_length(zckCtx *zck) {
+    return zck_get_header_length(zck) + zck_get_data_length(zck);
+}
index e1ea38c98ff119eeefe1be29e7e783f4cedf8ec6..d59524fcbc42a91e4c1782f54858ca8694657033 100644 (file)
@@ -108,6 +108,18 @@ int index_read(zckCtx *zck, char *data, size_t size, size_t max_length) {
     return True;
 }
 
+ssize_t PUBLIC zck_get_index_count(zckCtx *zck) {
+    if(zck == NULL)
+        return -1;
+    return zck->index.count;
+}
+
+zckIndex PUBLIC *zck_get_index(zckCtx *zck) {
+    if(zck == NULL)
+        return NULL;
+    return &(zck->index);
+}
+
 int PUBLIC zck_missing_chunks(zckCtx *zck) {
     if(zck == NULL) {
         zck_log(ZCK_LOG_ERROR, "zckCtx not initialized\n");
index 515d65275287a231e48ad2c01856e3232c6f4180..ff204a4d38c6f31824cc9ae2a1822ce70ae86400 100644 (file)
@@ -60,63 +60,38 @@ int PUBLIC zck_get_min_download_size() {
     return 5 + MAX_COMP_SIZE*2 + get_max_hash_size();
 }
 
-int PUBLIC zck_set_ioption(zckCtx *zck, zck_ioption option, ssize_t value) {
-    /* Set hash type */
-    if(option == ZCK_HASH_FULL_TYPE) {
-        VALIDATE_WRITE(zck);
-        return set_full_hash_type(zck, value);
-    } else if(option == ZCK_HASH_CHUNK_TYPE) {
-        VALIDATE_WRITE(zck);
-        return set_chunk_hash_type(zck, value);
 
-    /* Validation options */
-    } else if(option == ZCK_VAL_HEADER_HASH_TYPE) {
-        VALIDATE_READ(zck);
-        if(value < 0) {
-            zck_log(ZCK_LOG_ERROR,
-                    "Header hash type can't be less than zero: %li\n",
-                    value);
-            return False;
-        }
-        /* Make sure that header hash type is set before the header digest,
-         * otherwise we run the risk of a buffer overflow */
-        if(zck->prep_digest != NULL) {
-            zck_log(ZCK_LOG_ERROR,
-                    "For validation, you must set the header hash type "
-                    "*before* the header digest itself\n");
-            return False;
-        }
-        zck->prep_hash_type = value;
-    } else if(option == ZCK_VAL_HEADER_LENGTH) {
-        VALIDATE_READ(zck);
-        if(value < 0) {
-            zck_log(ZCK_LOG_ERROR,
-                    "Header size validation can't be less than zero: %li\n",
-                    value);
-            return False;
-        }
-        zck->prep_hdr_size = value;
-
-    /* Hash options */
-    } else if(option < 100) {
-        /* Currently no hash options other than setting hash type, so bail */
-        zck_log(ZCK_LOG_ERROR, "Unknown option %lu\n", value);
-        return False;
-
-    /* Compression options */
-    } else if(option < 2000) {
-        VALIDATE_WRITE(zck);
-        return comp_ioption(zck, option, value);
 
-    /* Unknown options */
-    } else {
-        zck_log(ZCK_LOG_ERROR, "Unknown integer option %i\n", option);
-        return False;
+static void zck_clear(zckCtx *zck) {
+    if(zck == NULL)
+        return;
+    index_free(zck);
+    if(zck->header)
+        free(zck->header);
+    zck->fd = -1;
+    zck->header = NULL;
+    zck->header_size = 0;
+    if(!comp_close(zck))
+        zck_log(ZCK_LOG_WARNING, "Unable to close compression\n");
+    hash_close(&(zck->full_hash));
+    hash_close(&(zck->check_full_hash));
+    hash_close(&(zck->check_chunk_hash));
+    clear_work_index(zck);
+    if(zck->full_hash_digest) {
+        free(zck->full_hash_digest);
+        zck->full_hash_digest = NULL;
+    }
+    if(zck->header_digest) {
+        free(zck->header_digest);
+        zck->header_digest = NULL;
+    }
+    if(zck->temp_fd) {
+        close(zck->temp_fd);
+        zck->temp_fd = 0;
     }
-    return True;
 }
 
-int hex_to_int (char c) {
+static int hex_to_int (char c) {
     if (c >= 97)
         c = c - 32;
     int result = (c / 16 - 3) * 10 + (c % 16);
@@ -125,7 +100,7 @@ int hex_to_int (char c) {
     return result;
 }
 
-char *ascii_checksum_to_bin (char *checksum) {
+static char *ascii_checksum_to_bin (char *checksum) {
     int cl = strlen(checksum);
     char *raw_checksum = zmalloc(cl/2);
     if(raw_checksum == NULL) {
@@ -145,6 +120,72 @@ char *ascii_checksum_to_bin (char *checksum) {
     return raw_checksum;
 }
 
+int get_tmp_fd() {
+    int temp_fd;
+    char *fname = NULL;
+    char template[] = "zcktempXXXXXX";
+    char *tmpdir = getenv("TMPDIR");
+
+    if(tmpdir == NULL) {
+        tmpdir = "/tmp/";
+    }
+    fname = zmalloc(strlen(template) + strlen(tmpdir) + 2);
+    if(fname == NULL) {
+        zck_log(ZCK_LOG_ERROR, "Unable to allocate %lu bytes\n",
+                strlen(template) + strlen(tmpdir) + 2);
+        return -1;
+    }
+    strncpy(fname, tmpdir, strlen(tmpdir));
+    strncpy(fname+strlen(tmpdir), "/", 2);
+    strncpy(fname+strlen(tmpdir)+1, template, strlen(template));
+
+    temp_fd = mkstemp(fname);
+    if(temp_fd < 0) {
+        free(fname);
+        zck_log(ZCK_LOG_ERROR, "Unable to create temporary file\n");
+        return -1;
+    }
+    if(unlink(fname) < 0) {
+        free(fname);
+        zck_log(ZCK_LOG_ERROR, "Unable to delete temporary file\n");
+        return -1;
+    }
+    free(fname);
+    return temp_fd;
+}
+
+int import_dict(zckCtx *zck) {
+    VALIDATE(zck);
+
+    size_t size = zck->index.first->length;
+
+    /* No dict */
+    if(size == 0)
+        return True;
+
+    zck_log(ZCK_LOG_DEBUG, "Reading compression dict\n");
+    char *data = zmalloc(size);
+    if(data == NULL) {
+        zck_log(ZCK_LOG_ERROR, "Unable to allocate %lu bytes\n", size);
+        return False;
+    }
+    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(!comp_reset(zck))
+        return False;
+    zck_log(ZCK_LOG_DEBUG, "Setting dict\n");
+    if(!comp_soption(zck, ZCK_COMP_DICT, data, size))
+        return False;
+    if(!comp_init(zck))
+        return False;
+    free(data);
+
+    return True;
+}
+
 int PUBLIC zck_set_soption(zckCtx *zck, zck_soption option, const char *value,
                            size_t length) {
     char *data = zmalloc(length);
@@ -193,6 +234,63 @@ int PUBLIC zck_set_soption(zckCtx *zck, zck_soption option, const char *value,
     }
     return True;
 }
+
+int PUBLIC zck_set_ioption(zckCtx *zck, zck_ioption option, ssize_t value) {
+    /* Set hash type */
+    if(option == ZCK_HASH_FULL_TYPE) {
+        VALIDATE_WRITE(zck);
+        return set_full_hash_type(zck, value);
+    } else if(option == ZCK_HASH_CHUNK_TYPE) {
+        VALIDATE_WRITE(zck);
+        return set_chunk_hash_type(zck, value);
+
+    /* Validation options */
+    } else if(option == ZCK_VAL_HEADER_HASH_TYPE) {
+        VALIDATE_READ(zck);
+        if(value < 0) {
+            zck_log(ZCK_LOG_ERROR,
+                    "Header hash type can't be less than zero: %li\n",
+                    value);
+            return False;
+        }
+        /* Make sure that header hash type is set before the header digest,
+         * otherwise we run the risk of a buffer overflow */
+        if(zck->prep_digest != NULL) {
+            zck_log(ZCK_LOG_ERROR,
+                    "For validation, you must set the header hash type "
+                    "*before* the header digest itself\n");
+            return False;
+        }
+        zck->prep_hash_type = value;
+    } else if(option == ZCK_VAL_HEADER_LENGTH) {
+        VALIDATE_READ(zck);
+        if(value < 0) {
+            zck_log(ZCK_LOG_ERROR,
+                    "Header size validation can't be less than zero: %li\n",
+                    value);
+            return False;
+        }
+        zck->prep_hdr_size = value;
+
+    /* Hash options */
+    } else if(option < 100) {
+        /* Currently no hash options other than setting hash type, so bail */
+        zck_log(ZCK_LOG_ERROR, "Unknown option %lu\n", value);
+        return False;
+
+    /* Compression options */
+    } else if(option < 2000) {
+        VALIDATE_WRITE(zck);
+        return comp_ioption(zck, option, value);
+
+    /* Unknown options */
+    } else {
+        zck_log(ZCK_LOG_ERROR, "Unknown integer option %i\n", option);
+        return False;
+    }
+    return True;
+}
+
 int PUBLIC zck_close(zckCtx *zck) {
     VALIDATE(zck);
 
@@ -221,35 +319,6 @@ int PUBLIC zck_close(zckCtx *zck) {
     return True;
 }
 
-void zck_clear(zckCtx *zck) {
-    if(zck == NULL)
-        return;
-    index_free(zck);
-    if(zck->header)
-        free(zck->header);
-    zck->fd = -1;
-    zck->header = NULL;
-    zck->header_size = 0;
-    if(!comp_close(zck))
-        zck_log(ZCK_LOG_WARNING, "Unable to close compression\n");
-    hash_close(&(zck->full_hash));
-    hash_close(&(zck->check_full_hash));
-    hash_close(&(zck->check_chunk_hash));
-    clear_work_index(zck);
-    if(zck->full_hash_digest) {
-        free(zck->full_hash_digest);
-        zck->full_hash_digest = NULL;
-    }
-    if(zck->header_digest) {
-        free(zck->header_digest);
-        zck->header_digest = NULL;
-    }
-    if(zck->temp_fd) {
-        close(zck->temp_fd);
-        zck->temp_fd = 0;
-    }
-}
-
 void PUBLIC zck_free(zckCtx **zck) {
     if(*zck == NULL)
         return;
@@ -327,334 +396,6 @@ iw_error:
     return NULL;
 }
 
-int PUBLIC zck_get_full_hash_type(zckCtx *zck) {
-    if(zck == NULL)
-        return -1;
-    return zck->hash_type.type;
-}
-
-ssize_t PUBLIC zck_get_full_digest_size(zckCtx *zck) {
-    if(zck == NULL)
-        return -1;
-    return zck->hash_type.digest_size;
-}
-
-int PUBLIC zck_get_chunk_hash_type(zckCtx *zck) {
-    if(zck == NULL)
-        return -1;
-    return zck->index.hash_type;
-}
-
-ssize_t PUBLIC zck_get_chunk_digest_size(zckCtx *zck) {
-    if(zck == NULL)
-        return -1;
-    return zck->index.digest_size;
-}
-
-ssize_t PUBLIC zck_get_index_count(zckCtx *zck) {
-    if(zck == NULL)
-        return -1;
-    return zck->index.count;
-}
-
-zckIndex PUBLIC *zck_get_index(zckCtx *zck) {
-    if(zck == NULL)
-        return NULL;
-    return &(zck->index);
-}
-
-char *get_digest_string(const char *digest, int size) {
-    char *str = zmalloc(size*2+1);
-
-    for(int i=0; i<size; i++)
-        snprintf(str + i*2, 3, "%02x", (unsigned char)digest[i]);
-    return str;
-}
-
-char PUBLIC *zck_get_header_digest(zckCtx *zck) {
-    if(zck == NULL)
-        return NULL;
-    return get_digest_string(zck->header_digest, zck->hash_type.digest_size);
-}
-
-char PUBLIC *zck_get_data_digest(zckCtx *zck) {
-    if(zck == NULL)
-        return NULL;
-    return get_digest_string(zck->full_hash_digest, zck->hash_type.digest_size);
-}
-
-char PUBLIC *zck_get_chunk_digest(zckIndexItem *item) {
-    if(item == NULL)
-        return NULL;
-    return get_digest_string(item->digest, item->digest_size);
-}
-
-ssize_t PUBLIC zck_get_header_length(zckCtx *zck) {
-    if(zck == NULL)
-        return -1;
-    return zck->lead_size + zck->header_length;
-}
-
-ssize_t PUBLIC zck_get_lead_length(zckCtx *zck) {
-    if(zck == NULL)
-        return -1;
-    return zck->lead_size;
-}
-
-ssize_t PUBLIC zck_get_data_length(zckCtx *zck) {
-    zckIndexItem *idx = zck->index.first;
-    while(idx->next != NULL)
-        idx = idx->next;
-    return idx->start + idx->comp_length;
-}
-
-ssize_t PUBLIC zck_get_length(zckCtx *zck) {
-    return zck_get_header_length(zck) + zck_get_data_length(zck);
-}
-
-int get_tmp_fd() {
-    int temp_fd;
-    char *fname = NULL;
-    char template[] = "zcktempXXXXXX";
-    char *tmpdir = getenv("TMPDIR");
-
-    if(tmpdir == NULL) {
-        tmpdir = "/tmp/";
-    }
-    fname = zmalloc(strlen(template) + strlen(tmpdir) + 2);
-    if(fname == NULL) {
-        zck_log(ZCK_LOG_ERROR, "Unable to allocate %lu bytes\n",
-                strlen(template) + strlen(tmpdir) + 2);
-        return -1;
-    }
-    strncpy(fname, tmpdir, strlen(tmpdir));
-    strncpy(fname+strlen(tmpdir), "/", 2);
-    strncpy(fname+strlen(tmpdir)+1, template, strlen(template));
-
-    temp_fd = mkstemp(fname);
-    if(temp_fd < 0) {
-        free(fname);
-        zck_log(ZCK_LOG_ERROR, "Unable to create temporary file\n");
-        return -1;
-    }
-    if(unlink(fname) < 0) {
-        free(fname);
-        zck_log(ZCK_LOG_ERROR, "Unable to delete temporary file\n");
-        return -1;
-    }
-    free(fname);
-    return temp_fd;
-}
-
-int import_dict(zckCtx *zck) {
-    VALIDATE(zck);
-
-    size_t size = zck->index.first->length;
-
-    /* No dict */
-    if(size == 0)
-        return True;
-
-    zck_log(ZCK_LOG_DEBUG, "Reading compression dict\n");
-    char *data = zmalloc(size);
-    if(data == NULL) {
-        zck_log(ZCK_LOG_ERROR, "Unable to allocate %lu bytes\n", size);
-        return False;
-    }
-    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(!comp_reset(zck))
-        return False;
-    zck_log(ZCK_LOG_DEBUG, "Setting dict\n");
-    if(!comp_soption(zck, ZCK_COMP_DICT, data, size))
-        return False;
-    if(!comp_init(zck))
-        return False;
-    free(data);
-
-    return True;
-}
-
-/* Validate chunk, returning -1 if checksum fails, 1 if good, 0 if error */
-int validate_chunk(zckCtx *zck, zckIndexItem *idx,
-                       zck_log_type bad_checksum) {
-    VALIDATE(zck);
-    if(idx == NULL) {
-        zck_log(ZCK_LOG_ERROR, "Index not initialized\n");
-        return 0;
-    }
-
-    char *digest = hash_finalize(&(zck->check_chunk_hash));
-    if(digest == NULL) {
-        zck_log(ZCK_LOG_ERROR,
-                "Unable to calculate %s checksum for chunk\n");
-        return 0;
-    }
-    if(idx->comp_length == 0)
-        memset(digest, 0, idx->digest_size);
-    zck_log(ZCK_LOG_DEBUG, "Checking chunk checksum\n");
-    char *pdigest = zck_get_chunk_digest(idx);
-    zck_log(ZCK_LOG_DEBUG, "Expected chunk checksum:   %s\n", pdigest);
-    free(pdigest);
-    pdigest = get_digest_string(digest, idx->digest_size);
-    zck_log(ZCK_LOG_DEBUG, "Calculated chunk checksum: %s\n", pdigest);
-    free(pdigest);
-    if(memcmp(digest, idx->digest, idx->digest_size) != 0) {
-        free(digest);
-        zck_log(bad_checksum, "Chunk checksum failed!\n");
-        return -1;
-    }
-    zck_log(ZCK_LOG_DEBUG, "Chunk checksum valid\n");
-    free(digest);
-    return 1;
-}
-
-int validate_current_chunk(zckCtx *zck) {
-    VALIDATE(zck);
-
-    return validate_chunk(zck, zck->comp.data_idx, ZCK_LOG_ERROR);
-}
-
-int validate_file(zckCtx *zck, zck_log_type bad_checksums) {
-    VALIDATE(zck);
-    char *digest = hash_finalize(&(zck->check_full_hash));
-    if(digest == NULL) {
-        zck_log(ZCK_LOG_ERROR,
-                "Unable to calculate %s checksum for full file\n");
-        return 0;
-    }
-    zck_log(ZCK_LOG_DEBUG, "Checking data checksum\n");
-    char *cks = get_digest_string(zck->full_hash_digest,
-                                  zck->hash_type.digest_size);
-    zck_log(ZCK_LOG_DEBUG, "Expected data checksum:   %s\n", cks);
-    free(cks);
-    cks = get_digest_string(digest, zck->hash_type.digest_size);
-    zck_log(ZCK_LOG_DEBUG, "Calculated data checksum: %s\n", cks);
-    free(cks);
-    if(memcmp(digest, zck->full_hash_digest, zck->hash_type.digest_size) != 0) {
-        free(digest);
-        zck_log(bad_checksums, "Data checksum failed!\n");
-        return -1;
-    }
-    zck_log(ZCK_LOG_DEBUG, "Data checksum valid\n");
-    free(digest);
-    return 1;
-}
-
-int validate_header(zckCtx *zck) {
-    VALIDATE(zck);
-    char *digest = hash_finalize(&(zck->check_full_hash));
-    if(digest == NULL) {
-        zck_log(ZCK_LOG_ERROR,
-                "Unable to calculate %s checksum for header\n");
-        return 0;
-    }
-    zck_log(ZCK_LOG_DEBUG, "Checking header checksum\n");
-    char *cks = get_digest_string(zck->header_digest,
-                                  zck->hash_type.digest_size);
-    zck_log(ZCK_LOG_DEBUG, "Expected header checksum:   %s\n", cks);
-    free(cks);
-    cks = get_digest_string(digest, zck->hash_type.digest_size);
-    zck_log(ZCK_LOG_DEBUG, "Calculated header checksum: %s\n", cks);
-    free(cks);
-    if(memcmp(digest, zck->header_digest, zck->hash_type.digest_size) != 0) {
-        free(digest);
-        zck_log(ZCK_LOG_ERROR, "Header checksum failed!\n");
-        return -1;
-    }
-    zck_log(ZCK_LOG_DEBUG, "Header checksum valid\n");
-    free(digest);
-
-    if(!hash_init(&(zck->check_full_hash), &(zck->hash_type)))
-        return 0;
-
-    return 1;
-}
-
-int validate_checksums(zckCtx *zck, zck_log_type bad_checksums) {
-    VALIDATE_READ(zck);
-    char buf[BUF_SIZE];
-
-    if(zck->data_offset == 0) {
-        zck_log(ZCK_LOG_ERROR, "Header hasn't been read yet\n");
-        return 0;
-    }
-
-    hash_close(&(zck->check_full_hash));
-    if(!hash_init(&(zck->check_full_hash), &(zck->hash_type)))
-        return 0;
-
-    if(!seek_data(zck->fd, zck->data_offset, SEEK_SET))
-        return 0;
-
-    /* Check each chunk checksum */
-    int all_good = True;
-    for(zckIndexItem *idx = zck->index.first; idx; idx = idx->next) {
-        if(idx == zck->index.first && idx->length == 0) {
-            idx->valid = 1;
-            continue;
-        }
-
-        if(!hash_init(&(zck->check_chunk_hash), &(zck->chunk_hash_type)))
-            return 0;
-
-        size_t rlen = 0;
-        while(rlen < idx->comp_length) {
-            size_t rsize = BUF_SIZE;
-            if(BUF_SIZE > idx->comp_length - rlen)
-                rsize = idx->comp_length - rlen;
-            if(read_data(zck->fd, buf, rsize) != rsize)
-                zck_log(ZCK_LOG_DEBUG, "No more data\n");
-            if(!hash_update(&(zck->check_chunk_hash), buf, rsize))
-                return 0;
-            if(!hash_update(&(zck->check_full_hash), buf, rsize))
-                return 0;
-            rlen += rsize;
-        }
-        int valid_chunk = validate_chunk(zck, idx, bad_checksums);
-        if(!valid_chunk)
-            return 0;
-        idx->valid = valid_chunk;
-        if(all_good && valid_chunk != 1)
-            all_good = False;
-    }
-    int valid_file = -1;
-    if(all_good) {
-        /* Check data checksum */
-        valid_file = validate_file(zck, bad_checksums);
-        if(!valid_file)
-            return 0;
-
-        /* If data checksum failed, invalidate *all* chunks */
-        if(valid_file == -1)
-            for(zckIndexItem *idx = zck->index.first; idx; idx = idx->next)
-                idx->valid = -1;
-    }
-
-    /* Go back to beginning of data section */
-    if(!seek_data(zck->fd, zck->data_offset, SEEK_SET))
-        return 0;
-
-    /* Reinitialize data checksum */
-    if(!hash_init(&(zck->check_full_hash), &(zck->hash_type)))
-        return 0;
-
-    return valid_file;
-}
-
-/* Returns 1 if all chunks are valid, -1 if even one isn't and 0 if error */
-int PUBLIC zck_find_valid_chunks(zckCtx *zck) {
-    return validate_checksums(zck, ZCK_LOG_DEBUG);
-}
-
-/* Returns 1 if all checksums matched, -1 if even one doesn't and 0 if error */
-int PUBLIC zck_validate_checksums(zckCtx *zck) {
-    return validate_checksums(zck, ZCK_LOG_WARNING);
-}
-
 int PUBLIC zck_get_fd(zckCtx *zck) {
     return zck->fd;
 }
index 4e4c549db82fe2d394abd0fe3b8af2f634259e4f..fff79b309e2cb41810043f08941aa2d5693a11bf 100644 (file)
@@ -160,18 +160,7 @@ int get_tmp_fd()
     __attribute__ ((warn_unused_result));
 int import_dict(zckCtx *zck)
     __attribute__ ((warn_unused_result));
-int validate_chunk(zckCtx *zck, zckIndexItem *idx, zck_log_type bad_checksum)
-    __attribute__ ((warn_unused_result));
-int validate_file(zckCtx *zck, zck_log_type bad_checksums)
-    __attribute__ ((warn_unused_result));
-int validate_current_chunk(zckCtx *zck)
-    __attribute__ ((warn_unused_result));
-int validate_header(zckCtx *zck)
-    __attribute__ ((warn_unused_result));
-const char *hash_name_from_type(int hash_type)
-    __attribute__ ((warn_unused_result));
-char *get_digest_string(const char *digest, int size)
-    __attribute__ ((warn_unused_result));
+
 
 /* hash/hash.h */
 int hash_setup(zckHashType *ht, int h)
@@ -183,7 +172,13 @@ int hash_update(zckHash *hash, const char *message, const size_t size)
 char *hash_finalize(zckHash *hash)
     __attribute__ ((warn_unused_result));
 void hash_close(zckHash *hash);
-const char *zck_hash_get_printable(const char *digest, zckHashType *type)
+int validate_chunk(zckCtx *zck, zckIndexItem *idx, zck_log_type bad_checksum)
+    __attribute__ ((warn_unused_result));
+int validate_file(zckCtx *zck, zck_log_type bad_checksums)
+    __attribute__ ((warn_unused_result));
+int validate_current_chunk(zckCtx *zck)
+    __attribute__ ((warn_unused_result));
+int validate_header(zckCtx *zck)
     __attribute__ ((warn_unused_result));
 int set_full_hash_type(zckCtx *zck, int hash_type)
     __attribute__ ((warn_unused_result));
@@ -191,6 +186,8 @@ int set_chunk_hash_type(zckCtx *zck, int hash_type)
     __attribute__ ((warn_unused_result));
 int get_max_hash_size()
     __attribute__ ((warn_unused_result));
+char *get_digest_string(const char *digest, int size)
+    __attribute__ ((warn_unused_result));
 
 
 /* index/index.c */