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