#define ZCK_VER_REVISION 1
#define ZCK_VER_SUBREVISION 0
-#define ZCK_COMP_NONE 0
-#define ZCK_COMP_ZSTD 2
-
-#define ZCK_HASH_SHA1 0
-#define ZCK_HASH_SHA256 1
-
-#define ZCK_COMMON_DICT 1
-#define ZCK_COMMON_DICT_SIZE 2
-
-#define ZCK_ZCK_COMP_LEVEL 20
-
#define True 1
#define False 0
-typedef enum log_type { ZCK_LOG_DEBUG,
- ZCK_LOG_INFO,
- ZCK_LOG_WARNING,
- ZCK_LOG_ERROR } log_type;
-
-/* Contains an index item */
+typedef enum zck_hash {
+ ZCK_HASH_SHA1,
+ ZCK_HASH_SHA256
+} zck_hash;
+
+typedef enum zck_comp {
+ ZCK_COMP_NONE,
+ ZCK_COMP_GZIP, /* Not implemented yet */
+ ZCK_COMP_ZSTD
+} zck_comp;
+
+typedef enum zck_ioption {
+ ZCK_HASH_FULL_TYPE = 0, /* Set full file hash type, using zck_hash */
+ ZCK_HASH_CHUNK_TYPE, /* Set chunk hash type using zck_hash */
+ ZCK_COMP_TYPE = 100, /* Set compression type using zck_comp */
+ ZCK_COMP_DICT_SIZE, /* Set compression dictionary size */
+ ZCK_ZSTD_COMP_LEVEL = 1000 /* Set zstd compression level */
+} zck_ioption;
+
+typedef enum zck_soption {
+ ZCK_COMP_DICT = 100 /* Set compression dictionary */
+} zck_soption;
+
+typedef enum zck_log_type {
+ ZCK_LOG_DEBUG,
+ ZCK_LOG_INFO,
+ ZCK_LOG_WARNING,
+ ZCK_LOG_ERROR
+} zck_log_type;
+
+
+/* Contains an index item pointing to a chunk */
typedef struct zckIndexItem {
char *digest;
int digest_size;
/*******************************************************************
- * Compression
+ * Options
*******************************************************************/
-/* Set compression type */
-int zck_set_compression_type(zckCtx *zck, int comp_type);
-/* Set compression parameter */
-int zck_set_comp_parameter(zckCtx *zck, int option, const void *value);
-
-
-/*******************************************************************
- * Hashing
- *******************************************************************/
-/* Set overall hash type */
-int zck_set_full_hash_type(zckCtx *zck, int hash_type);
-/* Set chunk hash type */
-int zck_set_chunk_hash_type(zckCtx *zck, int hash_type);
+/* Set string option */
+int zck_set_soption(zckCtx *zck, zck_soption option, const void *value);
+/* Set integer option */
+int zck_set_ioption(zckCtx *zck, zck_ioption option, ssize_t value);
/*******************************************************************
* Miscellaneous utilities
*******************************************************************/
/* Set logging level */
-void zck_set_log_level(log_type ll);
+void zck_set_log_level(zck_log_type ll);
/*******************************************************************
ssize_t zck_get_header_length(zckCtx *zck);
/* Get data length */
ssize_t zck_get_data_length(zckCtx *zck);
+/* Get index digest */
+char *zck_get_header_digest(zckCtx *zck);
+/* Get data digest */
+char *zck_get_data_digest(zckCtx *zck);
/* Get temporary fd that will disappear when fd is closed */
int zck_get_tmp_fd();
ssize_t zck_get_index_count(zckCtx *zck);
/* Get index */
zckIndex *zck_get_index(zckCtx *zck);
+/* Get chunk digest */
+char *zck_get_chunk_digest(zckIndexItem *item);
/*******************************************************************
int zck_get_full_hash_type(zckCtx *zck);
/* Get digest size of overall hash type */
int zck_get_full_digest_size(zckCtx *zck);
-/* Get index digest (uses overall hash type) */
-char *zck_get_index_digest(zckCtx *zck);
-/* Get index digest (uses overall hash type) */
-char *zck_get_data_digest(zckCtx *zck);
/* Get chunk hash type */
int zck_get_chunk_hash_type(zckCtx *zck);
/* Get digest size of chunk hash type */
}
zck_index_add_to_chunk(zck, dst, dst_size, 0);
zck_index_finish_chunk(zck);
- free(comp->dict);
- comp->dict_size = 0;
free(dst);
} else {
zck_index_finish_chunk(zck);
}
}
+ free(zck->comp.dict);
zck->comp.dict = NULL;
zck->comp.dict_size = 0;
zck->comp.started = True;
return zck_comp_reset(zck);
}
-int PUBLIC zck_set_compression_type(zckCtx *zck, int type) {
+static int set_comp_type(zckCtx *zck, ssize_t type) {
VALIDATE(zck);
zckComp *comp = &(zck->comp);
}
/* Set all values to 0 before setting compression type */
+ char *dc_data = comp->dc_data;
+ size_t dc_data_loc = comp->dc_data_loc;
+ size_t dc_data_size = comp->dc_data_size;
memset(comp, 0, sizeof(zckComp));
+ comp->dc_data = dc_data;
+ comp->dc_data_loc = dc_data_loc;
+ comp->dc_data_size = dc_data_size;
+
zck_log(ZCK_LOG_DEBUG, "Setting compression to %s\n",
zck_comp_name_from_type(type));
if(type == ZCK_COMP_NONE) {
return True;
}
-int PUBLIC zck_set_comp_parameter(zckCtx *zck, int option, const void *value) {
+int comp_ioption(zckCtx *zck, zck_ioption option, ssize_t value) {
+ VALIDATE(zck);
+
+ /* Cannot change compression parameters after compression has started */
+ if(zck && zck->comp.started) {
+ zck_log(ZCK_LOG_ERROR,
+ "Unable to set compression parameters after initialization\n");
+ return False;
+ }
+ if(option == ZCK_COMP_TYPE) {
+ return set_comp_type(zck, value);
+ } else if(option == ZCK_COMP_DICT_SIZE) {
+ zck->comp.dict_size = value;
+ } else {
+ if(zck && zck->comp.set_parameter)
+ return zck->comp.set_parameter(&(zck->comp), option, &value);
+
+ zck_log(ZCK_LOG_ERROR, "Unsupported compression parameter: %i\n",
+ option);
+ return False;
+ }
+ return True;
+}
+
+int comp_soption(zckCtx *zck, zck_soption option, const void *value) {
VALIDATE(zck);
/* Cannot change compression parameters after compression has started */
"Unable to set compression parameters after initialization\n");
return False;
}
- if(option == ZCK_COMMON_DICT) {
+ if(option == ZCK_COMP_DICT) {
if(zck->comp.dict_size == 0) {
zck_log(ZCK_LOG_ERROR,
"Dict size must be set before adding dict\n");
}
memcpy(dict, value, zck->comp.dict_size);
zck->comp.dict = dict;
- }else if(option == ZCK_COMMON_DICT_SIZE) {
- zck->comp.dict_size = *(size_t*)value;
- }else {
+ } else {
if(zck && zck->comp.set_parameter)
return zck->comp.set_parameter(&(zck->comp), option, value);
}
static int set_parameter(zckComp *comp, int option, const void *value) {
- if(option == ZCK_ZCK_COMP_LEVEL) {
+ if(option == ZCK_ZSTD_COMP_LEVEL) {
if(*(int*)value >= 0 && *(int*)value <= ZSTD_maxCLevel()) {
comp->level = *(int*)value;
return True;
static int set_default_parameters(zckComp *comp) {
/* Set default compression level to 16 */
int level=16;
- return set_parameter(comp, ZCK_ZCK_COMP_LEVEL, &level);
+ return set_parameter(comp, ZCK_ZSTD_COMP_LEVEL, &level);
}
int zck_zstd_setup(zckComp *comp) {
char *digest = zck_hash_finalize(&check_hash);
/* If chunk is invalid, overwrite with zeros and add to download range */
if(memcmp(digest, src_idx->digest, src_idx->digest_size) != 0) {
- zck_log(ZCK_LOG_WARNING, "Source hash: %s\n",
- zck_hash_get_printable(src_idx->digest, &(src->chunk_hash_type)));
- zck_log(ZCK_LOG_WARNING, "Target hash: %s\n",
- zck_hash_get_printable(digest, &(src->chunk_hash_type)));
+ char *pdigest = zck_get_chunk_digest(src_idx);
+ zck_log(ZCK_LOG_WARNING, "Source hash: %s\n", pdigest);
+ free(pdigest);
+ pdigest = get_digest_string(digest, src_idx->digest_size);
+ zck_log(ZCK_LOG_WARNING, "Target hash: %s\n", pdigest);
+ free(pdigest);
if(!zck_dl_write_zero(tgt, tgt_idx))
return False;
if(!zck_range_add(info, tgt_idx, tgt))
while(src_idx) {
if(tgt_idx->comp_length == src_idx->comp_length &&
memcmp(tgt_idx->digest, src_idx->digest,
- zck_get_chunk_digest_size(tgt)) == 0) {
+ tgt_idx->digest_size) == 0) {
found = True;
break;
}
if(!zck_read_index_hash(zck))
return False;
start += zck->hash_type.digest_size;
- zck_log(ZCK_LOG_DEBUG, "Index hash: (%s)",
+ zck_log(ZCK_LOG_DEBUG, "Header hash: (%s)",
zck_hash_name_from_type(zck_get_full_hash_type(zck)));
- char *digest = zck_get_index_digest(zck);
+ char *digest = zck_get_header_digest(zck);
zck_log(ZCK_LOG_DEBUG, "%s\n", digest);
free(digest);
src_idx = src_info->first;
while(src_idx) {
- if(memcmp(tgt_idx->digest, src_idx->digest, zck_get_chunk_digest_size(zck_tgt)) == 0) {
+ if(memcmp(tgt_idx->digest, src_idx->digest, tgt_idx->digest_size) == 0) {
found = True;
break;
}
#include "sha1/sha1.h"
#include "sha2/sha2.h"
+#define VALIDATE(f) if(!f) { \
+ zck_log(ZCK_LOG_ERROR, "zckCtx not initialized\n"); \
+ return False; \
+ }
+
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";
-static char hash_text[BUF_SIZE] = {0};
const static char *HASH_NAME[] = {
"SHA-1",
return HASH_NAME[hash_type];
}
-const char *zck_hash_get_printable(const char *digest, zckHashType *type) {
- if(digest == NULL || type == NULL) {
- zck_log(ZCK_LOG_ERROR,
- "digest or zckHashType haven't been initialized\n");
+int set_full_hash_type(zckCtx *zck, int hash_type) {
+ VALIDATE(zck);
+ zck_log(ZCK_LOG_INFO, "Setting full hash to %s\n",
+ zck_hash_name_from_type(hash_type));
+ if(!zck_hash_setup(&(zck->hash_type), hash_type)) {
+ zck_log(ZCK_LOG_ERROR, "Unable to set full hash to %s\n",
+ zck_hash_name_from_type(hash_type));
return False;
}
- for(int i=0; i<type->digest_size; i++) {
- if(snprintf(hash_text + (i*2), 3, "%02x", (unsigned char)digest[i]) < 0) {
- zck_log(ZCK_LOG_ERROR, "Unable to generate printable hash\n");
- return NULL;
- }
+ zck_hash_close(&(zck->full_hash));
+ if(!zck_hash_init(&(zck->full_hash), &(zck->hash_type))) {
+ zck_log(ZCK_LOG_ERROR, "Unable initialize full hash\n");
+ return False;
+ }
+ return True;
+}
+
+int set_chunk_hash_type(zckCtx *zck, int hash_type) {
+ VALIDATE(zck);
+ memset(&(zck->chunk_hash_type), 0, sizeof(zckHashType));
+ zck_log(ZCK_LOG_INFO, "Setting chunk hash to %s\n",
+ zck_hash_name_from_type(hash_type));
+ if(!zck_hash_setup(&(zck->chunk_hash_type), hash_type)) {
+ zck_log(ZCK_LOG_ERROR, "Unable to set chunk hash to %s\n",
+ zck_hash_name_from_type(hash_type));
+ return False;
}
- return hash_text;
+ zck->index.hash_type = zck->chunk_hash_type.type;
+ zck->index.digest_size = zck->chunk_hash_type.digest_size;
+ return True;
}
/* Read and initialize compression type */
if(!zck_compint_to_int(&tmp, header + length, &length))
return False;
- if(!zck_set_compression_type(zck, tmp))
+ if(!zck_set_ioption(zck, ZCK_COMP_TYPE, tmp))
return False;
if(!zck_comp_init(zck))
return False;
int hash_type;
if(!zck_compint_to_int(&hash_type, data + length, &length))
return False;
- if(!zck_set_chunk_hash_type(zck, hash_type))
+ if(!zck_set_ioption(zck, ZCK_HASH_CHUNK_TYPE, hash_type))
return False;
/* Read number of index entries */
#include "zck_private.h"
-static log_type log_level = ZCK_LOG_ERROR;
+static zck_log_type log_level = ZCK_LOG_ERROR;
-void PUBLIC zck_set_log_level(log_type ll) {
+void PUBLIC zck_set_log_level(zck_log_type ll) {
log_level = ll;
}
-void PUBLIC zck_log(log_type lt, const char *format, ...) {
+void PUBLIC zck_log(zck_log_type lt, const char *format, ...) {
if(lt >= log_level) {
va_list args;
va_start(args, format);
return False; \
}
+int PUBLIC zck_set_ioption(zckCtx *zck, zck_ioption option, ssize_t value) {
+ /* Set hash type */
+ if(option == ZCK_HASH_FULL_TYPE) {
+ return set_full_hash_type(zck, value);
+ } else if(option == ZCK_HASH_CHUNK_TYPE) {
+ return set_chunk_hash_type(zck, 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) {
+ return comp_ioption(zck, option, value);
+
+ /* Unknown options */
+ } else {
+ zck_log(ZCK_LOG_ERROR, "Unknown option %lu\n", value);
+ return False;
+ }
+}
+
+int PUBLIC zck_set_soption(zckCtx *zck, zck_soption option, const void *value) {
+ /* Hash options */
+ 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) {
+ return comp_soption(zck, option, value);
+
+ /* Unknown options */
+ } else {
+ zck_log(ZCK_LOG_ERROR, "Unknown option %lu\n", value);
+ return False;
+ }
+}
int PUBLIC zck_close(zckCtx *zck) {
VALIDATE(zck);
/* Set defaults */
#ifdef ZCHUNK_ZSTD
- if(!zck_set_compression_type(zck, ZCK_COMP_ZSTD))
+ if(!zck_set_ioption(zck, ZCK_COMP_TYPE, ZCK_COMP_ZSTD))
goto iw_error;
#else
- if(!zck_set_compression_type(zck, ZCK_COMP_NONE))
+ if(!zck_set_ioption(zck, ZCK_COMP_TYPE, ZCK_COMP_NONE))
goto iw_error;
#endif
- if(!zck_set_full_hash_type(zck, ZCK_HASH_SHA256))
+ if(!zck_set_ioption(zck, ZCK_HASH_FULL_TYPE, ZCK_HASH_SHA256))
goto iw_error;
- if(!zck_set_chunk_hash_type(zck, ZCK_HASH_SHA1))
+ if(!zck_set_ioption(zck, ZCK_HASH_CHUNK_TYPE, ZCK_HASH_SHA1))
goto iw_error;
zck->fd = dst_fd;
return NULL;
}
-int PUBLIC zck_set_full_hash_type(zckCtx *zck, int hash_type) {
- VALIDATE(zck);
- zck_log(ZCK_LOG_INFO, "Setting full hash to %s\n",
- zck_hash_name_from_type(hash_type));
- if(!zck_hash_setup(&(zck->hash_type), hash_type)) {
- zck_log(ZCK_LOG_ERROR, "Unable to set full hash to %s\n",
- zck_hash_name_from_type(hash_type));
- return False;
- }
- zck_hash_close(&(zck->full_hash));
- if(!zck_hash_init(&(zck->full_hash), &(zck->hash_type))) {
- zck_log(ZCK_LOG_ERROR, "Unable initialize full hash\n");
- return False;
- }
- return True;
-}
-
-int PUBLIC zck_set_chunk_hash_type(zckCtx *zck, int hash_type) {
- VALIDATE(zck);
- memset(&(zck->chunk_hash_type), 0, sizeof(zckHashType));
- zck_log(ZCK_LOG_INFO, "Setting chunk hash to %s\n",
- zck_hash_name_from_type(hash_type));
- if(!zck_hash_setup(&(zck->chunk_hash_type), hash_type)) {
- zck_log(ZCK_LOG_ERROR, "Unable to set chunk hash to %s\n",
- zck_hash_name_from_type(hash_type));
- return False;
- }
- zck->index.hash_type = zck->chunk_hash_type.type;
- zck->index.digest_size = zck->chunk_hash_type.digest_size;
- return True;
-}
-
-int PUBLIC zck_get_full_digest_size(zckCtx *zck) {
- if(zck == NULL)
- return -1;
- return zck->hash_type.digest_size;
-}
-
-int PUBLIC zck_get_chunk_digest_size(zckCtx *zck) {
- if(zck == NULL || zck->index.digest_size == 0)
- return -1;
- return zck->index.digest_size;
-}
-
int PUBLIC zck_get_full_hash_type(zckCtx *zck) {
if(zck == NULL)
return -1;
return str;
}
-char PUBLIC *zck_get_index_digest(zckCtx *zck) {
+char PUBLIC *zck_get_header_digest(zckCtx *zck) {
if(zck == NULL)
return NULL;
return get_digest_string(zck->index_digest, zck->hash_type.digest_size);
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;
if(!zck_comp_reset(zck))
return False;
zck_log(ZCK_LOG_DEBUG, "Setting dict size\n");
- if(!zck_set_comp_parameter(zck, ZCK_COMMON_DICT_SIZE, &size))
+ if(!zck_set_ioption(zck, ZCK_COMP_DICT_SIZE, size))
return False;
zck_log(ZCK_LOG_DEBUG, "Setting dict\n");
- if(!zck_set_comp_parameter(zck, ZCK_COMMON_DICT, data))
+ if(!zck_set_soption(zck, ZCK_COMP_DICT, data))
return False;
if(!zck_comp_init(zck))
return False;
"Unable to calculate %s checksum for chunk\n");
return False;
}
+ if(zck->comp.data_idx->comp_length == 0)
+ memset(digest, 0, zck->comp.data_idx->digest_size);
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");
+ char *pdigest = zck_get_chunk_digest(zck->comp.data_idx);
+ zck_log(ZCK_LOG_DEBUG, "Expected chunk checksum: %s\n", pdigest);
+ free(pdigest);
+ pdigest = get_digest_string(digest, zck->comp.data_idx->digest_size);
+ zck_log(ZCK_LOG_DEBUG, "Calculated chunk checksum: %s\n", pdigest);
+ free(pdigest);
if(memcmp(digest, zck->comp.data_idx->digest,
zck->chunk_hash_type.digest_size) != 0) {
free(digest);
const size_t fd_size);
typedef int (*fcclose)(struct zckComp *comp);
-typedef enum log_type log_type;
+typedef enum zck_log_type zck_log_type;
typedef struct zckHashType {
int type;
int zck_validate_file(zckCtx *zck);
int zck_validate_current_chunk(zckCtx *zck);
void zck_clear_work_index(zckCtx *zck);
+char *get_digest_string(const char *digest, int size);
/* hash/hash.h */
int zck_hash_setup(zckHashType *ht, int h);
char *zck_hash_finalize(zckHash *hash);
void zck_hash_close(zckHash *hash);
const char *zck_hash_get_printable(const char *digest, zckHashType *type);
+int set_full_hash_type(zckCtx *zck, int hash_type);
+int set_chunk_hash_type(zckCtx *zck, int hash_type);
/* index/index.c */
int zck_index_read(zckCtx *zck, char *data, size_t 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);
+int comp_ioption(zckCtx *zck, zck_ioption option, ssize_t value);
+int comp_soption(zckCtx *zck, zck_soption option, const void *value);
/* dl/range.c */
char *zck_range_get_char(zckRangeItem **range, int max_ranges);
/* log.c */
-void zck_log(log_type lt, const char *format, ...);
+void zck_log(zck_log_type lt, const char *format, ...);
#endif
exit(1);
}
- /*if(!zck_set_compression_type(zck, ZCK_COMP_NONE)) {
+ /*if(!zck_set_ioption(zck, ZCK_COMP_TYPE, ZCK_COMP_NONE)) {
perror("Unable to set compression type\n");
exit(1);
}*/
if(dict_size > 0) {
- if(!zck_set_comp_parameter(zck, ZCK_COMMON_DICT_SIZE, &dict_size))
+ if(!zck_set_ioption(zck, ZCK_COMP_DICT_SIZE, dict_size))
exit(1);
- if(!zck_set_comp_parameter(zck, ZCK_COMMON_DICT, dict))
+ if(!zck_set_soption(zck, ZCK_COMP_DICT, dict))
exit(1);
}
free(dict);
exit(1);
zckIndexItem *tgt_idx = tgt_info->first;
zckIndexItem *src_idx = src_info->first;
- if(memcmp(tgt_idx->digest, src_idx->digest, zck_get_chunk_digest_size(zck_tgt)) != 0)
+ if(memcmp(tgt_idx->digest, src_idx->digest, tgt_idx->digest_size) != 0)
printf("WARNING: Dicts don't match\n");
ssize_t dl_size = zck_get_header_length(zck_tgt);
if(dl_size < 0)
src_idx = src_info->first;
while(src_idx) {
- if(memcmp(tgt_idx->digest, src_idx->digest, zck_get_chunk_digest_size(zck_tgt)) == 0) {
+ if(memcmp(tgt_idx->digest, src_idx->digest, tgt_idx->digest_size) == 0) {
found = True;
break;
}
close(src_fd);
printf("Overall checksum type: %s\n", zck_hash_name_from_type(zck_get_full_hash_type(zck)));
- char *digest = zck_get_index_digest(zck);
+ char *digest = zck_get_header_digest(zck);
printf("Header checksum: %s\n", digest);
free(digest);
digest = zck_get_data_digest(zck);
exit(1);
zckIndexItem *idx = idxi->first;
while(idx) {
- for(int i=0; i<zck_get_chunk_digest_size(zck); i++)
- printf("%02x", (unsigned char)idx->digest[i]);
- printf(" %12lu %12lu %12lu\n", idx->start + zck_get_header_length(zck), idx->comp_length, idx->length);
+ char *digest = zck_get_chunk_digest(idx);
+ if(digest == NULL)
+ exit(1);
+ printf("%s %12lu %12lu %12lu\n", digest, idx->start + zck_get_header_length(zck), idx->comp_length, idx->length);
+ free(digest);
idx = idx->next;
}
-
zck_free(&zck);
}