From fd124c82d2a1639b7626454bae4ac0fb4c84252d Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Tue, 11 Aug 2009 12:07:32 +0200 Subject: [PATCH] New API for MD5 production: iso_md5_start(), iso_md5_compute(), iso_md5_clone(), iso_md5_end() --- libisofs/ecma119.c | 11 +++--- libisofs/filesrc.c | 38 +++++++++++++------- libisofs/libisofs.h | 87 +++++++++++++++++++++++++++++++++++++++------ libisofs/md5.c | 84 +++++++++++++++++++++++++++++++++++++++++-- libisofs/md5.h | 24 +------------ 5 files changed, 191 insertions(+), 53 deletions(-) diff --git a/libisofs/ecma119.c b/libisofs/ecma119.c index c1f9316..22a6882 100644 --- a/libisofs/ecma119.c +++ b/libisofs/ecma119.c @@ -63,8 +63,10 @@ void ecma119_image_free(Ecma119Image *t) free(t->output_charset); #ifdef Libisofs_with_checksumS - if (t->checksum_ctx != NULL) /* dispose checksum context */ - libisofs_md5(&(t->checksum_ctx), NULL, 0, NULL, (1 << 15)); + if (t->checksum_ctx != NULL) { /* dispose checksum context */ + char md5[16]; + iso_md5_end(&(t->checksum_ctx), md5); + } if (t->checksum_buffer != NULL) free(t->checksum_buffer); #endif @@ -1275,7 +1277,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img) #ifdef Libisofs_with_checksumS if (target->md5_session_checksum) { /* After any fake writes are done: Initialize image checksum context */ - ret = libisofs_md5(&(target->checksum_ctx), NULL, 0, NULL, 1); + ret = iso_md5_start(&(target->checksum_ctx)); if (ret < 0) return ret; } @@ -1450,8 +1452,7 @@ int iso_write(Ecma119Image *target, void *buf, size_t count) if (target->checksum_ctx != NULL) { /* Add to image checksum */ target->checksum_counter += count; - libisofs_md5(&(target->checksum_ctx), (char *) buf, (int) count, - NULL, 0); + iso_md5_compute(target->checksum_ctx, (char *) buf, (int) count); } #endif /* Libisofs_with_checksumS */ diff --git a/libisofs/filesrc.c b/libisofs/filesrc.c index 1899664..6a4c22b 100644 --- a/libisofs/filesrc.c +++ b/libisofs/filesrc.c @@ -308,7 +308,7 @@ int filesrc_read(IsoFileSrc *file, char *buf, size_t count) static int filesrc_writer_write_data(IsoImageWriter *writer) { - int res; + int res, ret; size_t i, b; Ecma119Image *t; IsoFileSrc *file; @@ -351,14 +351,16 @@ int filesrc_writer_write_data(IsoImageWriter *writer) res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res, "File \"%s\" can't be opened. Filling with 0s.", name); if (res < 0) { - return res; /* aborted due to error severity */ + ret = res; /* aborted due to error severity */ + goto ex; } memset(buffer, 0, BLOCK_SIZE); for (b = 0; b < nblocks; ++b) { res = iso_write(t, buffer, BLOCK_SIZE); if (res < 0) { /* ko, writer error, we need to go out! */ - return res; + ret = res; + goto ex; } } continue; @@ -369,7 +371,8 @@ int filesrc_writer_write_data(IsoImageWriter *writer) (res == 2 ? "truncated" : "padded with 0's")); if (res < 0) { filesrc_close(file); - return res; /* aborted due to error severity */ + ret = res; /* aborted due to error severity */ + goto ex; } } #ifdef LIBISOFS_VERBOSE_DEBUG @@ -383,7 +386,7 @@ int filesrc_writer_write_data(IsoImageWriter *writer) if (file->checksum_index > 0) { /* initialize file checksum */ - res = libisofs_md5(&ctx, NULL, 0, md5, 1); + res = iso_md5_start(&ctx); if (res <= 0) file->checksum_index = 0; } @@ -402,7 +405,8 @@ int filesrc_writer_write_data(IsoImageWriter *writer) if (wres < 0) { /* ko, writer error, we need to go out! */ filesrc_close(file); - return wres; + ret = wres; + goto ex; } #ifdef Libisofs_with_checksumS @@ -412,7 +416,7 @@ int filesrc_writer_write_data(IsoImageWriter *writer) res = file_size - b * BLOCK_SIZE; if (res > BLOCK_SIZE) res = BLOCK_SIZE; - res = libisofs_md5(&ctx, buffer, res, md5, 0); + res = iso_md5_compute(ctx, buffer, res); if (res <= 0) file->checksum_index = 0; } @@ -437,7 +441,8 @@ int filesrc_writer_write_data(IsoImageWriter *writer) } if (res < 0) { - return res; /* aborted due error severity */ + ret = res; /* aborted due error severity */ + goto ex; } /* fill with 0s */ @@ -448,7 +453,8 @@ int filesrc_writer_write_data(IsoImageWriter *writer) res = iso_write(t, buffer, BLOCK_SIZE); if (res < 0) { /* ko, writer error, we need to go out! */ - return res; + ret = res; + goto ex; } #ifdef Libisofs_with_checksumS @@ -458,7 +464,7 @@ int filesrc_writer_write_data(IsoImageWriter *writer) res = file_size - b * BLOCK_SIZE; if (res > BLOCK_SIZE) res = BLOCK_SIZE; - res = libisofs_md5(&ctx, buffer, res, md5, 0); + res = iso_md5_compute(ctx, buffer, res); if (res <= 0) file->checksum_index = 0; } @@ -472,7 +478,7 @@ int filesrc_writer_write_data(IsoImageWriter *writer) if (file->checksum_index > 0) { /* Obtain checksum and dispose checksum context */ - res = libisofs_md5(&ctx, buffer, 0, md5, 2 | (1 << 15)); + res = iso_md5_end(&ctx, md5); if (res <= 0) file->checksum_index = 0; @@ -487,7 +493,15 @@ int filesrc_writer_write_data(IsoImageWriter *writer) } - return ISO_SUCCESS; + ret = ISO_SUCCESS; +ex:; + +#ifdef Libisofs_with_checksumS + if (ctx != NULL) /* avoid any memory leak */ + iso_md5_end(&ctx, md5); +#endif + + return ret; } static diff --git a/libisofs/libisofs.h b/libisofs/libisofs.h index 2855caf..7b644ba 100644 --- a/libisofs/libisofs.h +++ b/libisofs/libisofs.h @@ -4991,6 +4991,9 @@ int iso_gzip_get_refcounts(off_t *gzip_count, off_t *gunzip_count, int flag); /* ---------------------------- MD5 Checksums --------------------------- */ +/* Production and loading of MD5 checksums is controlled by calls + iso_write_opts_set_record_md5() and iso_read_opts_set_no_md5() +*/ /** * Eventually obtain the recorded MD5 checksum of the session which was @@ -5039,6 +5042,72 @@ int iso_image_get_session_md5(IsoImage *image, uint32_t *start_lba, int iso_file_get_md5(IsoImage *image, IsoFile *file, char md5[16], int flag); +/* The following functions allow to do own MD5 computations. E.g for + comparing the result with a recorded checksum. +*/ +/** + * Create a MD5 computation context and hand out an opaque handle. + * + * @param md5_context + * Returns the opaque handle. Submitted *md5_context must be NULL or + * point to freeable memory. + * @return + * 1= success , <0 indicates error + * + * @since 0.6.22 + */ +int iso_md5_start(void **md5_context); + +/** + * Advance the computation of a MD5 checksum by a chunk of data bytes. + * + * @param md5_context + * An opaque handle once returned by iso_md5_start() or iso_md5_clone(). + * @param data + * The bytes which shall be processed into to the checksum. + * @param datalen + * The number of bytes to be processed. + * @return + * 1= success , <0 indicates error + * + * @since 0.6.22 + */ +int iso_md5_compute(void *md5_context, char *data, int datalen); + +/** + * Create a MD5 computation context as clone of an existing one. One may call + * iso_md5_clone(old, &new, 0) and then iso_md5_end(&new, result, 0) in order + * to obtain an intermediate MD5 sum before the computation goes on. + * + * @param old_md5_context + * An opaque handle once returned by iso_md5_start() or iso_md5_clone(). + * @param new_md5_context + * Returns the opaque handle to the new MD5 context. Submitted + * *md5_context must be NULL or point to freeable memory. + * @return + * 1= success , <0 indicates error + * + * @since 0.6.22 + */ +int iso_md5_clone(void *old_md5_context, void **new_md5_context); + +/** + * Obtain the MD5 checksum from a MD5 computation context and dispose this + * context. (If you want to keep the context then call iso_md5_clone() and + * apply iso_md5_end() to the clone.) + * + * @param md5_context + * A pointer to an opaque handle once returned by iso_md5_start() or + * iso_md5_clone(). *md5_context will be set to NULL in this call. + * @param result + * Gets filled with the 16 bytes of MD5 checksum. + * @return + * 1= success , <0 indicates error + * + * @since 0.6.22 + */ +int iso_md5_end(void **md5_context, char result[16]); + /************ Error codes and return values for libisofs ********************/ @@ -5523,6 +5592,14 @@ struct burn_source { #define Libisofs_hardlink_prooF yes +/* Checksums : During image writing equip IsoFile objects with MD5 checksums + and compute an overall checksum of the session. Store them in + a separate checksum block area after the data area of the + session. +*/ +#define Libisofs_with_checksumS yes + + /* ---------------------------- Experiments ---------------------------- */ /* <<< on its way out @@ -5542,14 +5619,4 @@ struct burn_source { */ -/* Experiment: During image writing equip IsoFile objects with MD5 checksums - and compute an overall checksum of the image. Store them in - a separate checksum block area after the data area of the - image. - - ENABLE ONLY FOR DEVELOPMENT TESTS ! -*/ -#define Libisofs_with_checksumS yes - - #endif /*LIBISO_LIBISOFS_H_*/ diff --git a/libisofs/md5.c b/libisofs/md5.c index 9265f31..ad405d2 100644 --- a/libisofs/md5.c +++ b/libisofs/md5.c @@ -269,7 +269,28 @@ static int md5_final(libisofs_md5_ctx *ctx, char result[16], int flag) return(1); } +/** Compute a MD5 checksum from one or more calls of this function. + The first call has to be made with flag bit0 == 1. It may already submit + processing payload in data and datalen. + The last call has to be made with bit15 set. Normally bit1 will be set + too in order to receive the checksum before it gets disposed. + bit1 may only be set in the last call or together with bit2. + The combination of bit1 and bit2 may be used to get an intermediate + result without hampering an ongoing checksum computation. + @param ctx the checksum context which stores the state between calls. + It gets created with flag bit0 and disposed with bit15. + With flag bit0, *ctx has to be NULL or point to freeable + memory. + @param data the bytes to be checksummed + @param datalen the number of bytes in data + @param result returns the 16 bytes of checksum if called with bit1 set + @param flag bit0= allocate and init *ctx + bit1= transfer ctx to result + bit2= with bit 0 : clone new *ctx from data + bit15= free *ctx +*/ +static int libisofs_md5(void **ctx_in, char *data, int datalen, char result[16], int flag) /* *ctx has to be NULL or point to freeable memory */ @@ -310,6 +331,60 @@ int libisofs_md5(void **ctx_in, char *data, int datalen, } +/* ----------------------------------------------------------------------- */ + +/* Public MD5 computing facility */ + +/* API */ +int iso_md5_start(void **md5_context) +{ + int ret; + + ret = libisofs_md5(md5_context, NULL, 0, NULL, 1); + if (ret <= 0) + return ISO_OUT_OF_MEM; + return 1; +} + + +/* API */ +int iso_md5_compute(void *md5_context, char *data, int datalen) +{ + int ret; + + ret = libisofs_md5(&md5_context, data, datalen, NULL, 0); + if (ret <= 0) + return ISO_NULL_POINTER; + return 1; +} + + +/* API */ +int iso_md5_clone(void *old_md5_context, void **new_md5_context) +{ + int ret; + + ret = libisofs_md5(new_md5_context, old_md5_context, 0, NULL, 4); + if (ret < 0) + return ISO_OUT_OF_MEM; + if (ret == 0) + return ISO_NULL_POINTER; + return 1; +} + + +/* API */ +int iso_md5_end(void **md5_context, char result[16]) +{ + int ret; + + ret = libisofs_md5(md5_context, NULL, 0, result, 2 | (1 << 15)); + if (ret <= 0) + return ISO_NULL_POINTER; + return 1; +} + + /* ----------------------------------------------------------------------- */ @@ -324,6 +399,10 @@ int checksum_xinfo_func(void *data, int flag) } +/* ----------------------------------------------------------------------- */ + +/* MD5 checksum image writer */ + #ifdef Libisofs_with_checksumS /* @@ -459,10 +538,9 @@ int checksum_writer_write_data(IsoImageWriter *writer) /* Write image checksum to index 0 */ if (t->checksum_ctx != NULL) { - /* >>> rather fork a result than killing t->checksum_ctx */; + /* >>> rather clone a result than killing t->checksum_ctx */; - res = libisofs_md5(&(t->checksum_ctx), NULL, 0, t->image_md5, - 2 | (1 << 15)); + res = iso_md5_end(&(t->checksum_ctx), t->image_md5); if (res > 0) memcpy(t->checksum_buffer + 0, t->image_md5, 16); } diff --git a/libisofs/md5.h b/libisofs/md5.h index 1387b98..e899d7e 100644 --- a/libisofs/md5.h +++ b/libisofs/md5.h @@ -10,29 +10,7 @@ #define LIBISO_MD5_H_ -/** Compute a MD5 checksum from one or more calls of this function. - The first call has to be made with flag bit0 == 1. It may already submit - processing payload in data and datalen. - The last call has to be made with bit15 set. Normally bit1 will be set - too in order to receive the checksum before it gets disposed. - bit1 may only be set in the last call or together with bit2. - The combination of bit1 and bit2 may be used to get an intermediate - result without hampering an ongoing checksum computation. - - @param ctx the checksum context which stores the state between calls. - It gets created with flag bit0 and disposed with bit15. - With flag bit0, *ctx has to be NULL or point to freeable - memory. - @param data the bytes to be checksummed - @param datalen the number of bytes in data - @param result returns the 16 bytes of checksum if called with bit1 set - @param flag bit0= allocate and init *ctx - bit1= transfer ctx to result - bit2= with bit 0 : clone new *ctx from data - bit15= free *ctx -*/ -int libisofs_md5(void **ctx, char *data, int datalen, - char result[16], int flag); +/* The MD5 computation API is in libisofs.h : iso_md5_start() et.al. */ /** Create a writer object for checksums and add it to the writer list of