1 #ifndef ZCK_H 2 #define ZCK_H 3 4 #define ZCK_VERSION "1.1.16" 5 6 #include <stdlib.h> 7 #include <stdbool.h> 8 #include <sys/types.h> 9 10 typedef 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 18 typedef enum zck_comp { 19 ZCK_COMP_NONE, 20 ZCK_COMP_GZIP, /* Not implemented yet */ 21 ZCK_COMP_ZSTD 22 } zck_comp; 23 24 typedef 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 36 typedef 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 41 typedef 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 50 typedef struct zckCtx zckCtx; 51 typedef struct zckHash zckHash; 52 typedef struct zckChunk zckChunk; 53 typedef struct zckIndex zckIndex; 54 typedef struct zckRange zckRange; 55 typedef struct zckDL zckDL; 56 57 typedef 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 */ 63 zckCtx *zck_create() 64 __attribute__ ((warn_unused_result)); 65 /* Initialize zchunk for reading */ 66 bool 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 */ 69 ssize_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 */ 77 bool 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 */ 82 ssize_t zck_write(zckCtx *zck, const char *src, const size_t src_size) 83 __attribute__ ((warn_unused_result)); 84 /* Create a chunk boundary */ 85 ssize_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 */ 94 bool 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 */ 98 void zck_free(zckCtx **zck); 99 100 101 /******************************************************************* 102 * Options 103 *******************************************************************/ 104 /* Set string option */ 105 bool zck_set_soption(zckCtx *zck, zck_soption option, const char *value, 106 size_t length) 107 __attribute__ ((warn_unused_result)); 108 /* Set integer option */ 109 bool 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 */ 117 void zck_set_log_level(zck_log_type ll); 118 /* Set logging fd */ 119 void 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 */ 122 int 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 */ 127 const 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 */ 130 bool 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 */ 137 int 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 */ 141 int 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 */ 145 int 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 */ 152 zckRange *zck_get_missing_range(zckCtx *zck, int max_ranges) 153 __attribute__ ((warn_unused_result)); 154 /* Get a string representation of a zckRange */ 155 char *zck_get_range_char(zckCtx *zck, zckRange *range) 156 __attribute__ ((warn_unused_result)); 157 /* Get file descriptor attached to zchunk context */ 158 int zck_get_fd(zckCtx *zck) 159 __attribute__ ((warn_unused_result)); 160 /* Set file descriptor attached to zchunk context */ 161 bool zck_set_fd(zckCtx *zck, int fd) 162 __attribute__ ((warn_unused_result)); 163 164 /* Return number of missing chunks (-1 if error) */ 165 int zck_missing_chunks(zckCtx *zck) 166 __attribute__ ((warn_unused_result)); 167 /* Return number of failed chunks (-1 if error) */ 168 int zck_failed_chunks(zckCtx *zck) 169 __attribute__ ((warn_unused_result)); 170 /* Reset failed chunks to become missing */ 171 void 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 */ 185 ssize_t zck_get_lead_length(zckCtx *zck) 186 __attribute__ ((warn_unused_result)); 187 /* Get header length (lead + preface + index + sigs) */ 188 ssize_t zck_get_header_length(zckCtx *zck) 189 __attribute__ ((warn_unused_result)); 190 /* Get data length */ 191 ssize_t zck_get_data_length(zckCtx *zck) 192 __attribute__ ((warn_unused_result)); 193 /* Get file length */ 194 ssize_t zck_get_length(zckCtx *zck) 195 __attribute__ ((warn_unused_result)); 196 /* Get index digest */ 197 char *zck_get_header_digest(zckCtx *zck) 198 __attribute__ ((warn_unused_result)); 199 /* Get data digest */ 200 char *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 */ 208 const 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 */ 218 bool zck_init_adv_read (zckCtx *zck, int src_fd) 219 __attribute__ ((warn_unused_result)); 220 /* Read zchunk lead */ 221 bool zck_read_lead(zckCtx *zck) 222 __attribute__ ((warn_unused_result)); 223 /* Read zchunk header */ 224 bool zck_read_header(zckCtx *zck) 225 __attribute__ ((warn_unused_result)); 226 /* Validate lead */ 227 bool zck_validate_lead(zckCtx *zck) 228 __attribute__ ((warn_unused_result)); 229 230 /******************************************************************* 231 * Indexes 232 *******************************************************************/ 233 /* Get chunk count */ 234 ssize_t zck_get_chunk_count(zckCtx *zck) 235 __attribute__ ((warn_unused_result)); 236 /* Get chunk by number */ 237 zckChunk *zck_get_chunk(zckCtx *zck, size_t number) 238 __attribute__ ((warn_unused_result)); 239 /* Get first chunk */ 240 zckChunk *zck_get_first_chunk(zckCtx *zck) 241 __attribute__ ((warn_unused_result)); 242 /* Get next chunk */ 243 zckChunk *zck_get_next_chunk(zckChunk *idx) 244 __attribute__ ((warn_unused_result)); 245 /* Get chunk starting location */ 246 ssize_t zck_get_chunk_start(zckChunk *idx) 247 __attribute__ ((warn_unused_result)); 248 /* Get uncompressed chunk size */ 249 ssize_t zck_get_chunk_size(zckChunk *idx) 250 __attribute__ ((warn_unused_result)); 251 /* Get compressed chunk size */ 252 ssize_t zck_get_chunk_comp_size(zckChunk *idx) 253 __attribute__ ((warn_unused_result)); 254 /* Get chunk number */ 255 ssize_t zck_get_chunk_number(zckChunk *idx) 256 __attribute__ ((warn_unused_result)); 257 /* Get validity of current chunk - 1 = valid, 0 = missing, -1 = invalid */ 258 int zck_get_chunk_valid(zckChunk *idx) 259 __attribute__ ((warn_unused_result)); 260 /* Get chunk digest */ 261 char *zck_get_chunk_digest(zckChunk *item) 262 __attribute__ ((warn_unused_result)); 263 /* Get digest size of chunk hash type */ 264 ssize_t zck_get_chunk_digest_size(zckCtx *zck) 265 __attribute__ ((warn_unused_result)); 266 /* Get chunk data */ 267 ssize_t zck_get_chunk_data(zckChunk *idx, char *dst, size_t dst_size) 268 __attribute__ ((warn_unused_result)); 269 /* Get compressed chunk data */ 270 ssize_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 */ 273 bool 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 */ 281 int zck_get_full_hash_type(zckCtx *zck) 282 __attribute__ ((warn_unused_result)); 283 /* Get digest size of overall hash type */ 284 ssize_t zck_get_full_digest_size(zckCtx *zck) 285 __attribute__ ((warn_unused_result)); 286 /* Get chunk hash type */ 287 int zck_get_chunk_hash_type(zckCtx *zck) 288 __attribute__ ((warn_unused_result)); 289 /* Get name of hash type */ 290 const 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 */ 303 bool zck_copy_chunks(zckCtx *src, zckCtx *tgt) 304 __attribute__ ((warn_unused_result)); 305 /* Free zckRange */ 306 void zck_range_free(zckRange **info); 307 /* Get range string from start and end location */ 308 char *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 */ 312 int zck_get_min_download_size() 313 __attribute__ ((warn_unused_result)); 314 /* Get the number of separate range items in the range */ 315 int zck_get_range_count(zckRange *range) 316 __attribute__ ((warn_unused_result)); 317 318 /******************************************************************* 319 * Downloading 320 *******************************************************************/ 321 /* Initialize zchunk download context */ 322 zckDL *zck_dl_init(zckCtx *zck) 323 __attribute__ ((warn_unused_result)); 324 /* Reset zchunk download context for reuse */ 325 void zck_dl_reset(zckDL *dl); 326 /* Free zchunk download context */ 327 void zck_dl_free(zckDL **dl); 328 /* Get zchunk context from download context */ 329 zckCtx *zck_dl_get_zck(zckDL *dl) 330 __attribute__ ((warn_unused_result)); 331 /* Set zchunk context in download context */ 332 bool zck_dl_set_zck(zckDL *dl, zckCtx *zck) 333 __attribute__ ((warn_unused_result)); 334 /* Clear regex used for extracting download ranges from multipart download */ 335 void zck_dl_clear_regex(zckDL *dl); 336 /* Download and process the header from url */ 337 bool zck_dl_get_header(zckCtx *zck, zckDL *dl, char *url) 338 __attribute__ ((warn_unused_result)); 339 /* Get number of bytes downloaded using download context */ 340 ssize_t zck_dl_get_bytes_downloaded(zckDL *dl) 341 __attribute__ ((warn_unused_result)); 342 /* Get number of bytes uploaded using download context */ 343 ssize_t zck_dl_get_bytes_uploaded(zckDL *dl) 344 __attribute__ ((warn_unused_result)); 345 /* Set download ranges for zchunk download context */ 346 bool zck_dl_set_range(zckDL *dl, zckRange *range) 347 __attribute__ ((warn_unused_result)); 348 /* Get download ranges from zchunk download context */ 349 zckRange *zck_dl_get_range(zckDL *dl) 350 __attribute__ ((warn_unused_result)); 351 352 /* Set header callback function */ 353 bool zck_dl_set_header_cb(zckDL *dl, zck_wcb func) 354 __attribute__ ((warn_unused_result)); 355 /* Set header userdata */ 356 bool zck_dl_set_header_data(zckDL *dl, void *data) 357 __attribute__ ((warn_unused_result)); 358 /* Set write callback function */ 359 bool zck_dl_set_write_cb(zckDL *dl, zck_wcb func) 360 __attribute__ ((warn_unused_result)); 361 /* Set write userdata */ 362 bool 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. */ 369 size_t zck_write_chunk_cb(void *ptr, size_t l, size_t c, void *dl_v); 370 size_t zck_write_zck_header_cb(void *ptr, size_t l, size_t c, void *dl_v); 371 size_t zck_header_cb(char *b, size_t l, size_t c, void *dl_v); 372 373 #endif 374