1#ifndef ZCK_H 2#define ZCK_H 3 4#define ZCK_VERSION "@version@" 5 6#include <stdlib.h> 7#include <stdbool.h> 8#include <sys/types.h> 9 10typedef enum zck_hash { 11 ZCK_HASH_SHA1, 12 ZCK_HASH_SHA256, 13 ZCK_HASH_SHA512, 14 ZCK_HASH_SHA512_128, 15 ZCK_HASH_UNKNOWN 16} zck_hash; 17 18typedef enum zck_comp { 19 ZCK_COMP_NONE, 20 ZCK_COMP_GZIP, /* Not implemented yet */ 21 ZCK_COMP_ZSTD 22} zck_comp; 23 24typedef enum zck_ioption { 25 ZCK_HASH_FULL_TYPE = 0, /* Set full file hash type, using zck_hash */ 26 ZCK_HASH_CHUNK_TYPE, /* Set chunk hash type using zck_hash */ 27 ZCK_VAL_HEADER_HASH_TYPE, /* Set what the header hash type *should* be */ 28 ZCK_VAL_HEADER_LENGTH, /* Set what the header length *should* be */ 29 ZCK_COMP_TYPE = 100, /* Set compression type using zck_comp */ 30 ZCK_MANUAL_CHUNK, /* Disable auto-chunking */ 31 ZCK_CHUNK_MIN, /* Minimum chunk size when manual chunking */ 32 ZCK_CHUNK_MAX, /* Maximum chunk size when manual chunking */ 33 ZCK_ZSTD_COMP_LEVEL = 1000 /* Set zstd compression level */ 34} zck_ioption; 35 36typedef enum zck_soption { 37 ZCK_VAL_HEADER_DIGEST = 0, /* Set what the header hash *should* be */ 38 ZCK_COMP_DICT = 100 /* Set compression dictionary */ 39} zck_soption; 40 41typedef enum zck_log_type { 42 ZCK_LOG_DDEBUG = -1, 43 ZCK_LOG_DEBUG, 44 ZCK_LOG_INFO, 45 ZCK_LOG_WARNING, 46 ZCK_LOG_ERROR, 47 ZCK_LOG_NONE 48} zck_log_type; 49 50typedef struct zckCtx zckCtx; 51typedef struct zckHash zckHash; 52typedef struct zckChunk zckChunk; 53typedef struct zckIndex zckIndex; 54typedef struct zckRange zckRange; 55typedef struct zckDL zckDL; 56 57typedef size_t (*zck_wcb)(void *ptr, size_t l, size_t c, void *dl_v); 58 59/******************************************************************* 60 * Reading a zchunk file 61 *******************************************************************/ 62/* Initialize zchunk context */ 63zckCtx *zck_create() 64 __attribute__ ((warn_unused_result)); 65/* Initialize zchunk for reading */ 66bool zck_init_read (zckCtx *zck, int src_fd) 67 __attribute__ ((warn_unused_result)); 68/* Decompress dst_size bytes from zchunk file to dst, while verifying hashes */ 69ssize_t zck_read(zckCtx *zck, char *dst, size_t dst_size) 70 __attribute__ ((warn_unused_result)); 71 72 73/******************************************************************* 74 * Writing a zchunk file 75 *******************************************************************/ 76/* Initialize zchunk for writing */ 77bool zck_init_write (zckCtx *zck, int dst_fd) 78 __attribute__ ((warn_unused_result)); 79/* Compress data src of size src_size, and write to zchunk file 80 * Due to the nature of zchunk files and how they are built, no data will 81 * actually appear in the zchunk file until zck_close() is called */ 82ssize_t zck_write(zckCtx *zck, const char *src, const size_t src_size) 83 __attribute__ ((warn_unused_result)); 84/* Create a chunk boundary */ 85ssize_t zck_end_chunk(zckCtx *zck) 86 __attribute__ ((warn_unused_result)); 87 88 89/******************************************************************* 90 * Common functions for finishing a zchunk file 91 *******************************************************************/ 92/* Close a zchunk file so it may no longer be read from or written to. The 93 * context still contains information about the file */ 94bool zck_close(zckCtx *zck) 95 __attribute__ ((warn_unused_result)); 96/* Free a zchunk context. You must pass the address of the context, and the 97 * context will automatically be set to NULL after it is freed */ 98void zck_free(zckCtx **zck); 99 100 101/******************************************************************* 102 * Options 103 *******************************************************************/ 104/* Set string option */ 105bool zck_set_soption(zckCtx *zck, zck_soption option, const char *value, 106 size_t length) 107 __attribute__ ((warn_unused_result)); 108/* Set integer option */ 109bool zck_set_ioption(zckCtx *zck, zck_ioption option, ssize_t value) 110 __attribute__ ((warn_unused_result)); 111 112 113/******************************************************************* 114 * Error handling 115 *******************************************************************/ 116/* Set logging level */ 117void zck_set_log_level(zck_log_type ll); 118/* Set logging fd */ 119void zck_set_log_fd(int fd); 120/* Check whether zck is in error state 121 * Returns 0 if not, 1 if recoverable error, 2 if fatal error */ 122int zck_is_error(zckCtx *zck) 123 __attribute__ ((warn_unused_result)); 124/* Get error message 125 * Returns char* containing error message. char* will contain empty string if 126 * there is no error message */ 127const char *zck_get_error(zckCtx *zck); 128/* Clear error message 129 * Returns 1 if message was cleared, 0 if error is fatal and can't be cleared */ 130bool zck_clear_error(zckCtx *zck); 131 132/******************************************************************* 133 * Miscellaneous utilities 134 *******************************************************************/ 135/* Validate the chunk and data checksums for the current file. 136 * Returns 0 for error, -1 for invalid checksum and 1 for valid checksum */ 137int zck_validate_checksums(zckCtx *zck) 138 __attribute__ ((warn_unused_result)); 139/* Validate just the data checksum for the current file 140 * Returns 0 for error, -1 for invalid checksum and 1 for valid checksum */ 141int zck_validate_data_checksum(zckCtx *zck) 142 __attribute__ ((warn_unused_result)); 143/* Go through file and mark valid chunks as valid 144 * Returns 0 for error, -1 for invalid checksum and 1 for valid checksum */ 145int zck_find_valid_chunks(zckCtx *zck) 146 __attribute__ ((warn_unused_result)); 147 148/* Get a zckRange of ranges that need to still be downloaded. 149 * max_ranges is the maximum number of ranges supported in a single request 150 * by the server. If the server supports unlimited ranges, set this to -1 151 * Returns NULL if there's an error */ 152zckRange *zck_get_missing_range(zckCtx *zck, int max_ranges) 153 __attribute__ ((warn_unused_result)); 154/* Get a string representation of a zckRange */ 155char *zck_get_range_char(zckCtx *zck, zckRange *range) 156 __attribute__ ((warn_unused_result)); 157/* Get file descriptor attached to zchunk context */ 158int zck_get_fd(zckCtx *zck) 159 __attribute__ ((warn_unused_result)); 160/* Set file descriptor attached to zchunk context */ 161bool zck_set_fd(zckCtx *zck, int fd) 162 __attribute__ ((warn_unused_result)); 163 164/* Return number of missing chunks (-1 if error) */ 165int zck_missing_chunks(zckCtx *zck) 166 __attribute__ ((warn_unused_result)); 167/* Return number of failed chunks (-1 if error) */ 168int zck_failed_chunks(zckCtx *zck) 169 __attribute__ ((warn_unused_result)); 170/* Reset failed chunks to become missing */ 171void zck_reset_failed_chunks(zckCtx *zck); 172 173 174/******************************************************************* 175 * The functions should be all you need to read and write a zchunk 176 * file. After this point are advanced functions with an unstable 177 * API, so use them with care. 178 *******************************************************************/ 179 180 181/******************************************************************* 182 * Advanced miscellaneous zchunk functions 183 *******************************************************************/ 184/* Get lead length */ 185ssize_t zck_get_lead_length(zckCtx *zck) 186 __attribute__ ((warn_unused_result)); 187/* Get header length (lead + preface + index + sigs) */ 188ssize_t zck_get_header_length(zckCtx *zck) 189 __attribute__ ((warn_unused_result)); 190/* Get data length */ 191ssize_t zck_get_data_length(zckCtx *zck) 192 __attribute__ ((warn_unused_result)); 193/* Get file length */ 194ssize_t zck_get_length(zckCtx *zck) 195 __attribute__ ((warn_unused_result)); 196/* Get index digest */ 197char *zck_get_header_digest(zckCtx *zck) 198 __attribute__ ((warn_unused_result)); 199/* Get data digest */ 200char *zck_get_data_digest(zckCtx *zck) 201 __attribute__ ((warn_unused_result)); 202 203 204/******************************************************************* 205 * Advanced compression functions 206 *******************************************************************/ 207/* Get name of compression type */ 208const char *zck_comp_name_from_type(int comp_type) 209 __attribute__ ((warn_unused_result)); 210/* Initialize compression. Compression type and parameters *must* be done 211 * before this is called */ 212 213 214/******************************************************************* 215 * Advanced zchunk reading functions 216 *******************************************************************/ 217/* Initialize zchunk for reading using advanced options */ 218bool zck_init_adv_read (zckCtx *zck, int src_fd) 219 __attribute__ ((warn_unused_result)); 220/* Read zchunk lead */ 221bool zck_read_lead(zckCtx *zck) 222 __attribute__ ((warn_unused_result)); 223/* Read zchunk header */ 224bool zck_read_header(zckCtx *zck) 225 __attribute__ ((warn_unused_result)); 226/* Validate lead */ 227bool zck_validate_lead(zckCtx *zck) 228 __attribute__ ((warn_unused_result)); 229 230/******************************************************************* 231 * Indexes 232 *******************************************************************/ 233/* Get chunk count */ 234ssize_t zck_get_chunk_count(zckCtx *zck) 235 __attribute__ ((warn_unused_result)); 236/* Get chunk by number */ 237zckChunk *zck_get_chunk(zckCtx *zck, size_t number) 238 __attribute__ ((warn_unused_result)); 239/* Get first chunk */ 240zckChunk *zck_get_first_chunk(zckCtx *zck) 241 __attribute__ ((warn_unused_result)); 242/* Get next chunk */ 243zckChunk *zck_get_next_chunk(zckChunk *idx) 244 __attribute__ ((warn_unused_result)); 245/* Get chunk starting location */ 246ssize_t zck_get_chunk_start(zckChunk *idx) 247 __attribute__ ((warn_unused_result)); 248/* Get uncompressed chunk size */ 249ssize_t zck_get_chunk_size(zckChunk *idx) 250 __attribute__ ((warn_unused_result)); 251/* Get compressed chunk size */ 252ssize_t zck_get_chunk_comp_size(zckChunk *idx) 253 __attribute__ ((warn_unused_result)); 254/* Get chunk number */ 255ssize_t zck_get_chunk_number(zckChunk *idx) 256 __attribute__ ((warn_unused_result)); 257/* Get validity of current chunk - 1 = valid, 0 = missing, -1 = invalid */ 258int zck_get_chunk_valid(zckChunk *idx) 259 __attribute__ ((warn_unused_result)); 260/* Get chunk digest */ 261char *zck_get_chunk_digest(zckChunk *item) 262 __attribute__ ((warn_unused_result)); 263/* Get digest size of chunk hash type */ 264ssize_t zck_get_chunk_digest_size(zckCtx *zck) 265 __attribute__ ((warn_unused_result)); 266/* Get chunk data */ 267ssize_t zck_get_chunk_data(zckChunk *idx, char *dst, size_t dst_size) 268 __attribute__ ((warn_unused_result)); 269/* Get compressed chunk data */ 270ssize_t zck_get_chunk_comp_data(zckChunk *idx, char *dst, size_t dst_size) 271 __attribute__ ((warn_unused_result)); 272/* Find out if two chunk digests are the same */ 273bool zck_compare_chunk_digest(zckChunk *a, zckChunk *b) 274 __attribute__ ((warn_unused_result)); 275 276 277/******************************************************************* 278 * Advanced hash functions 279 *******************************************************************/ 280/* Get overall hash type */ 281int zck_get_full_hash_type(zckCtx *zck) 282 __attribute__ ((warn_unused_result)); 283/* Get digest size of overall hash type */ 284ssize_t zck_get_full_digest_size(zckCtx *zck) 285 __attribute__ ((warn_unused_result)); 286/* Get chunk hash type */ 287int zck_get_chunk_hash_type(zckCtx *zck) 288 __attribute__ ((warn_unused_result)); 289/* Get name of hash type */ 290const char *zck_hash_name_from_type(int hash_type) 291 __attribute__ ((warn_unused_result)); 292 293 294 295/******************************************************************* 296 * Downloading (should this go in a separate header and library?) 297 *******************************************************************/ 298 299/******************************************************************* 300 * Ranges 301 *******************************************************************/ 302/* Get any matching chunks from src and put them in the right place in tgt */ 303bool zck_copy_chunks(zckCtx *src, zckCtx *tgt) 304 __attribute__ ((warn_unused_result)); 305/* Free zckRange */ 306void zck_range_free(zckRange **info); 307/* Get range string from start and end location */ 308char *zck_get_range(size_t start, size_t end) 309 __attribute__ ((warn_unused_result)); 310/* Get the minimum size needed to download in order to know how large the header 311 * is */ 312int zck_get_min_download_size() 313 __attribute__ ((warn_unused_result)); 314/* Get the number of separate range items in the range */ 315int zck_get_range_count(zckRange *range) 316 __attribute__ ((warn_unused_result)); 317 318/******************************************************************* 319 * Downloading 320 *******************************************************************/ 321/* Initialize zchunk download context */ 322zckDL *zck_dl_init(zckCtx *zck) 323 __attribute__ ((warn_unused_result)); 324/* Reset zchunk download context for reuse */ 325void zck_dl_reset(zckDL *dl); 326/* Free zchunk download context */ 327void zck_dl_free(zckDL **dl); 328/* Get zchunk context from download context */ 329zckCtx *zck_dl_get_zck(zckDL *dl) 330 __attribute__ ((warn_unused_result)); 331/* Set zchunk context in download context */ 332bool zck_dl_set_zck(zckDL *dl, zckCtx *zck) 333 __attribute__ ((warn_unused_result)); 334/* Clear regex used for extracting download ranges from multipart download */ 335void zck_dl_clear_regex(zckDL *dl); 336/* Download and process the header from url */ 337bool zck_dl_get_header(zckCtx *zck, zckDL *dl, char *url) 338 __attribute__ ((warn_unused_result)); 339/* Get number of bytes downloaded using download context */ 340ssize_t zck_dl_get_bytes_downloaded(zckDL *dl) 341 __attribute__ ((warn_unused_result)); 342/* Get number of bytes uploaded using download context */ 343ssize_t zck_dl_get_bytes_uploaded(zckDL *dl) 344 __attribute__ ((warn_unused_result)); 345/* Set download ranges for zchunk download context */ 346bool zck_dl_set_range(zckDL *dl, zckRange *range) 347 __attribute__ ((warn_unused_result)); 348/* Get download ranges from zchunk download context */ 349zckRange *zck_dl_get_range(zckDL *dl) 350 __attribute__ ((warn_unused_result)); 351 352/* Set header callback function */ 353bool zck_dl_set_header_cb(zckDL *dl, zck_wcb func) 354 __attribute__ ((warn_unused_result)); 355/* Set header userdata */ 356bool zck_dl_set_header_data(zckDL *dl, void *data) 357 __attribute__ ((warn_unused_result)); 358/* Set write callback function */ 359bool zck_dl_set_write_cb(zckDL *dl, zck_wcb func) 360 __attribute__ ((warn_unused_result)); 361/* Set write userdata */ 362bool zck_dl_set_write_data(zckDL *dl, void *data) 363 __attribute__ ((warn_unused_result)); 364 365/* Write callback. You *must* pass this and your initialized zchunk download 366 * context to the downloader when downloading a zchunk file. If you have your 367 * own callback, set dl->write_cb to your callback and dl->wdata to your 368 * callback data. */ 369size_t zck_write_chunk_cb(void *ptr, size_t l, size_t c, void *dl_v); 370size_t zck_write_zck_header_cb(void *ptr, size_t l, size_t c, void *dl_v); 371size_t zck_header_cb(char *b, size_t l, size_t c, void *dl_v); 372 373#endif 374