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