4 * Copyright (c) 2010-2011 Thomas Schmitt <scdbackup@gmx.net>
5 * Copyright (c) 2019 Steve McImtyre <steve@einval.com>
7 * API functions of libjte
9 * GNU LGPL v2.1 (including option for GPL v2 or later)
14 #include "../config.h"
19 #include <sys/types.h>
27 #ifdef HAVE_INTTYPES_H
38 #include "libjte_private.h"
43 /* @param flag bit0= do not free *dest before overwriting it
45 static int libjte__set_string(char **dest, char *source, int flag)
47 if (*dest != NULL && !(flag & 1))
52 *dest = strdup(source);
59 /* Version inquiry API */
61 void libjte__version(int *major, int *minor, int *micro)
63 *major = LIBJTE_VERSION_MAJOR;
64 *minor = LIBJTE_VERSION_MINOR;
65 *micro = LIBJTE_VERSION_MICRO;
69 int libjte__is_compatible(int major, int minor, int micro, int flag)
71 int own_major, own_minor, own_micro;
73 libjte__version(&own_major, &own_minor, &own_micro);
74 return(own_major > major ||
75 (own_major == major && (own_minor > minor ||
76 (own_minor == minor && own_micro >= micro))));
83 int libjte_new(struct libjte_env **jte_handle, int flag)
87 if (sizeof(off_t) < 8) {
88 fprintf(stderr, "libjte: Fatal compile time misconfiguration. sizeof(off_t) = %d too small.\n\n", (int) sizeof(off_t));
92 *jte_handle = o = calloc(1, sizeof(struct libjte_env));
95 o->jtemplate_out = NULL;
97 o->jchecksum_list = NULL;
98 o->checksum_algo = CHECK_MD5;
100 o->jttemplate = NULL;
101 o->jte_min_size = MIN_JIGDO_FILE_SIZE;
102 o->checksum_algo_iso = (CHECK_MD5_USED | \
104 CHECK_SHA256_USED | \
106 o->checksum_algo_tmpl = (CHECK_MD5_USED | CHECK_SHA256_USED);
107 o->jte_template_compression = JTE_TEMP_GZIP;
108 o->exclude_list = NULL;
109 o->include_list = NULL;
111 o->template_size = 0;
113 o->iso_context = NULL;
114 o->template_context = NULL;
115 o->entry_list = NULL;
116 o->entry_last = NULL;
121 o->checksum_list = NULL;
122 o->checksum_last = NULL;
123 o->include_in_jigdo = 0;
124 memset(o->message_buffer, 0, sizeof(o->message_buffer));
125 o->error_behavior = 1; /* Print to stderr, do not exit but return -1 */
127 o->uncomp_buf = NULL;
129 o->uncomp_buf_used = 0;
133 int libjte_destroy(struct libjte_env **jte_handle)
135 struct libjte_env *o;
142 free(o->jtemplate_out);
144 free(o->jchecksum_list);
145 if (o->jtjigdo != NULL)
147 if (o->jttemplate != NULL)
148 fclose(o->jttemplate);
150 libjte_destroy_path_match_list(o, 0); /* include_list */
151 libjte_destroy_path_match_list(o, 1); /* exclude_list */
152 libjte_destroy_path_mapping(o, 0);
154 if (o->iso_context != NULL)
155 checksum_free_context(o->iso_context);
156 if (o->template_context != NULL)
157 checksum_free_context(o->template_context);
159 /* >>> TODO : get rid of the following odd situation
160 o->j_file and o->t_file seem to be only copies of
161 o->jttemplate and o->jtjigdo */
163 libjte_destroy_entry_list(o, 0);
164 libjte_destroy_checksum_list(o, 0);
166 libjte_clear_msg_list(o, 1 | 2); /* dump pending messages to stderr */
175 int libjte_set_outfile(struct libjte_env *o, char *outfile)
177 return libjte__set_string(&(o->outfile), outfile, 0);
180 int libjte_set_verbose(struct libjte_env *o, int verbose)
182 o->verbose = !!verbose;
186 int libjte_set_checksum_algorithm(struct libjte_env *o,
193 if (check_algos[i].name == NULL)
195 sprintf(o->message_buffer,
196 "libjte: Unknown checksum algorithm %s", algorithm);
197 libjte_add_msg_entry(o, o->message_buffer, 0);
200 if (!strcmp(algorithm, check_algos[i].name))
203 o->checksum_algo = i;
204 *size = check_algos[i].raw_bytes;
209 int libjte_set_template_path(struct libjte_env *o, char *jtemplate_out)
211 return libjte__set_string(&(o->jtemplate_out), jtemplate_out, 0);
214 int libjte_set_jigdo_path(struct libjte_env *o, char *jjigdo_out)
216 return libjte__set_string(&(o->jjigdo_out), jjigdo_out, 0);
219 int libjte_set_md5_path(struct libjte_env *o, char *path)
221 return libjte_set_checksum_path(o, path);
224 int libjte_set_checksum_path(struct libjte_env *o, char *path)
226 return libjte__set_string(&(o->jchecksum_list), path, 0);
229 int libjte_set_min_size(struct libjte_env *o, int jte_min_size)
231 o->jte_min_size = jte_min_size;
235 static int libjte_decode_checksum_string(struct libjte_env *o,
236 char *checksum_code, int default_algo,
243 if (strcmp(checksum_code, "default") != 0) {
244 if (strstr(checksum_code, "md5") != NULL)
245 *algo |= CHECK_MD5_USED;
246 if (strstr(checksum_code, "sha1") != NULL)
247 *algo |= CHECK_SHA1_USED;
248 if (strstr(checksum_code, "sha256") != NULL)
249 *algo |= CHECK_SHA256_USED;
250 if (strstr(checksum_code, "sha512") != NULL)
251 *algo |= CHECK_SHA512_USED;
254 *algo = default_algo;
260 ret = parse_checksum_algo(checksum_code, algo);
262 *algo = default_algo;
263 sprintf(o->message_buffer, "Invalid checksum algorithm name in '%s'",
265 libjte_add_msg_entry(o, o->message_buffer, 0);
274 int libjte_set_checksum_iso(struct libjte_env *o, char *checksum_code)
277 int checksum_algo_iso = (CHECK_MD5_USED |
282 ret = libjte_decode_checksum_string(o, checksum_code, checksum_algo_iso,
286 o->checksum_algo_iso = checksum_algo_iso;
288 /* Maybe have to override - if we're doing a v2 jigdo file based
289 * around sha256, we always need the sha256 calculated too */
290 if (o->checksum_algo == CHECK_SHA256)
291 o->checksum_algo_iso |= CHECK_SHA256_USED;
296 int libjte_set_checksum_template(struct libjte_env *o, char *checksum_code)
299 int checksum_algo_tmpl = CHECK_MD5_USED;
301 ret = libjte_decode_checksum_string(o, checksum_code, checksum_algo_tmpl,
302 &checksum_algo_tmpl);
305 o->checksum_algo_tmpl = checksum_algo_tmpl;
307 /* Maybe have to override - if we're doing a v2 jigdo file based
308 * around sha256, we always need the sha256 calculated too */
309 if (o->checksum_algo == CHECK_SHA256)
310 o->checksum_algo_tmpl |= CHECK_SHA256_USED;
315 int libjte_set_compression(struct libjte_env *o, char *compression_code)
317 jtc_t compr = JTE_TEMP_GZIP;
319 if (strcmp(compression_code, "default") != 0) {
320 if (strcmp(compression_code, "gzip") == 0)
321 compr = JTE_TEMP_GZIP;
322 else if (strcmp(compression_code, "bzip2") ==0)
323 compr = JTE_TEMP_BZIP2;
325 sprintf(o->message_buffer,
326 "libjte: Unknown compression code. Known: gzip bzip2");
327 libjte_add_msg_entry(o, o->message_buffer, 0);
332 #ifndef LIBJTE_WITH_LIBBZ2
334 if (compr == JTE_TEMP_BZIP2) {
335 sprintf(o->message_buffer,
336 "libjte: Usage of libbz2 not enabled at compile time\n");
337 libjte_add_msg_entry(o, o->message_buffer, 0);
341 #endif /* LIBJTE_WITH_LIBBZ2 */
343 o->jte_template_compression = compr;
347 int libjte_add_exclude(struct libjte_env *o, char *pattern)
351 ret = jte_add_exclude(o, pattern);
355 int libjte_add_md5_demand(struct libjte_env *o, char *pattern)
359 ret = jte_add_include(o, pattern);
363 int libjte_add_checksum_demand(struct libjte_env *o, char *pattern)
367 ret = jte_add_include(o, pattern);
371 int libjte_add_mapping(struct libjte_env *o, char *arg)
375 ret = jte_add_mapping(o, arg);
379 int libjte_set_image_size(struct libjte_env *o, off_t image_size)
381 o->image_size = image_size;
388 int libjte_write_header(struct libjte_env *o)
392 if (o->jtemplate_out == NULL || o->jjigdo_out == NULL ||
393 o->outfile == NULL || o->jchecksum_list == NULL) {
394 sprintf(o->message_buffer,
395 "Undefined: template_path, jigdo_path, checksum_paths, or outfile.");
396 libjte_add_msg_entry(o, o->message_buffer, 0);
400 o->jttemplate = fopen(o->jtemplate_out, "wb");
401 if (o->jttemplate == NULL) {
402 sprintf(o->message_buffer,
403 "Cannot open template file '%1.1024s' for writing. errno=%d",
404 o->jtemplate_out, errno);
405 libjte_add_msg_entry(o, o->message_buffer, 0);
408 o->jtjigdo = fopen(o->jjigdo_out, "wb");
409 if (o->jtjigdo == NULL) {
410 sprintf(o->message_buffer,
411 "Cannot open jigdo file '%1.1024s' for writing. errno=%d",
412 o->jjigdo_out, errno);
413 libjte_add_msg_entry(o, o->message_buffer, 0);
417 ret = write_jt_header(o, o->jttemplate, o->jtjigdo);
423 int libjte_write_footer(struct libjte_env *o)
427 ret = write_jt_footer(o);
428 if (o->jtjigdo != NULL)
430 if (o->jttemplate != NULL)
431 fclose(o->jttemplate);
433 o->jttemplate = NULL;
439 /* Traditional Data File API */
441 int libjte_write_unmatched(struct libjte_env *o, void *buffer, int size,
446 ret = jtwrite(o, buffer, size, count);
450 int libjte_write_match_record(struct libjte_env *o,
451 char *filename, char *mirror_name, int sector_size,
452 off_t size, unsigned char md5[16])
456 if (check_algos[o->checksum_algo].type != CHECK_MD5)
458 sprintf(o->message_buffer, "Attempted to call libjte_write_match_record() after choosing checksum algorithm '%s'",
459 check_algos[o->checksum_algo].name);
460 libjte_add_msg_entry(o, o->message_buffer, 0);
464 ret = write_jt_match_record(o, filename, mirror_name, sector_size, size,
471 int libjte_write_match_record2(struct libjte_env *o,
472 char *filename, char *mirror_name, int sector_size,
473 off_t size, unsigned char *checksum)
477 ret = write_jt_match_record(o, filename, mirror_name,
478 sector_size, size, checksum);
484 int libjte_decide_file_jigdo(struct libjte_env *o,
485 char *filename, off_t size, char **mirror_name,
486 unsigned char md5[16])
488 if (check_algos[o->checksum_algo].type != CHECK_MD5)
490 sprintf(o->message_buffer, "Attempted to call libjte_decide_file_jigdo() after choosing checksum algorithm '%s'",
491 check_algos[o->checksum_algo].name);
492 libjte_add_msg_entry(o, o->message_buffer, 0);
496 return libjte_decide_file_jigdo2(o, filename, size, mirror_name, md5);
499 int libjte_decide_file_jigdo2(struct libjte_env *o,
500 char *filename, off_t size, char **mirror_name,
501 unsigned char *checksum)
507 ret = list_file_in_jigdo(o, filename, size, &checksum_name, checksum);
510 *mirror_name = strdup(checksum_name);
511 if (*mirror_name == NULL) {
512 libjte_report_no_mem(o, strlen(checksum_name) + 1, 0);
518 /* Simplified Data File API */
520 int libjte_begin_data_file(struct libjte_env *o, char *filename,
521 int sector_size, off_t size)
525 unsigned char *checksum;
527 checksum = calloc(1, check_algos[o->checksum_algo].raw_bytes);
531 o->include_in_jigdo = 0;
532 ret = list_file_in_jigdo(o, filename, size, &mirror_name, checksum);
543 write_jt_match_record(o, filename, mirror_name, sector_size,
545 o->include_in_jigdo = 1;
549 int libjte_show_data_chunk(struct libjte_env *o,
550 void *buffer, int sector_size,
553 o->image_size += count * sector_size;
554 if (o->include_in_jigdo)
556 jtwrite(o, buffer, sector_size, count);
560 int libjte_end_data_file(struct libjte_env *o)
562 o->include_in_jigdo = 0;
567 /* Error reporting API */
569 int libjte_set_error_behavior(struct libjte_env *o,
570 int to_stderr, int with_exit)
572 o->error_behavior = 0;
574 o->error_behavior |= 1;
576 o->error_behavior |= 2;
580 char *libjte_get_next_message(struct libjte_env *o)
582 jigdo_msg_entry_t *old_entry;
585 if (o->msg_list == NULL)
587 old_entry = o->msg_list;
588 o->msg_list = old_entry->next;
589 msg = old_entry->message;
594 /* @param flag bit0= print pending messages to stderr
596 int libjte_clear_msg_list(struct libjte_env *o, int flag)
600 if ((flag & 2) && o->msg_list != NULL)
602 "libjte: -- have to dump error messages to stderr --\n");
604 msg = libjte_get_next_message(o);
608 fprintf(stderr, "libjte: %s\n", msg);