Initial implementation of MD5 checksums for session and single data files.

To be activated by macro Libisofs_with_checksumS.
New AAIP attributes "isfs.ca" and "isofs.cx".
New API calls iso_image_get_session_md5() and iso_file_get_md5().
This commit is contained in:
2009-08-10 13:56:06 +02:00
parent 55690756ae
commit b5f4a66c59
15 changed files with 1349 additions and 40 deletions

View File

@ -27,6 +27,10 @@
#include "util.h"
#include "system_area.h"
#ifdef Libisofs_with_checksumS
#include "md5.h"
#endif
#include <stdlib.h>
#include <time.h>
#include <string.h>
@ -57,6 +61,14 @@ void ecma119_image_free(Ecma119Image *t)
}
free(t->input_charset);
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_buffer != NULL)
free(t->checksum_buffer);
#endif
free(t->writers);
free(t);
}
@ -294,7 +306,7 @@ void write_one_dir_record(Ecma119Image *t, Ecma119Node *node, int file_id,
rec->len_dr[0] = len_dr + (info != NULL ? info->suf_len : 0);
iso_bb(rec->block, block, 4);
iso_bb(rec->length, len, 4);
if(t->dir_rec_mtime) {
if (t->dir_rec_mtime) {
iso= node->node;
iso_datetime_7(rec->recording_time,
t->replace_timestamps ? t->timestamp : iso->mtime,
@ -860,6 +872,79 @@ void *write_function(void *arg)
pthread_exit(NULL);
}
#ifdef Libisofs_with_checksumS
static
int checksum_prepare_image(IsoImage *src, int flag)
{
int ret;
/* Set provisory value of isofs.ca with
4 byte LBA, 4 byte count, size 16, name MD5 */
ret = iso_root_set_isofsca((IsoNode *) src->root, 0, 0, 0, 16, "MD5", 0);
if (ret < 0)
return ret;
return ISO_SUCCESS;
}
/*
@flag bit0= recursion
*/
static
int checksum_prepare_nodes(IsoImage *img, IsoNode *node, int flag)
{
IsoNode *pos;
IsoFile *file;
int ret, i;
size_t value_length;
unsigned int idx = 0;
char *value;
void *xipt = NULL;
if (node->type == LIBISO_FILE) {
file = (IsoFile *) node;
if (file->from_old_session) {
/* Save eventual MD5 data of files from old image */
value= NULL;
ret = iso_node_lookup_attr(node, "isofs.cx", &value_length,
&value, 0);
if (ret == 1 && value_length == 4) {
for (i = 0; i < 4; i++)
idx = (idx << 8) | ((unsigned char *) value)[i];
if (idx > 0 && idx < 0x8000000) {
/* xipt is an int disguised as void pointer */
for (i = 0; i < 4; i++)
((char *) &xipt)[i] = value[i];
ret = iso_node_add_xinfo(node, checksum_xinfo_func,
xipt);
if (ret < 0)
return ret;
}
}
if (value != NULL)
free(value);
}
/* Equip all nodes with provisory isofs.cx numbers: 4 byte, all 0. */
ret = iso_file_set_isofscx(file, (unsigned int) 0, 0);
if (ret < 0)
return ret;
} else if (node->type == LIBISO_DIR) {
for (pos = ((IsoDir *) node)->children; pos != NULL; pos = pos->next) {
ret = checksum_prepare_nodes(img, pos, 1);
if (ret < 0)
return ret;
}
}
return ISO_SUCCESS;
}
#endif /* Libisofs_with_checksumS */
static
int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
{
@ -951,6 +1036,18 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
return ISO_OUT_OF_MEM;
}
#ifdef Libisofs_with_checksumS
/* >>> need an IsoWriteOpts component to control this */;
target->md5_checksums = 1;
target->checksum_idx_counter = 0;
target->checksum_ctx = NULL;
target->checksum_counter = 0;
target->checksum_buffer = NULL;
#endif
/*
* 2. Based on those options, create needed writers: iso, joliet...
* Each writer inits its structures and stores needed info into
@ -974,6 +1071,25 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
nwriters++;
}
#ifdef Libisofs_with_checksumS
if (target->md5_checksums) {
nwriters++;
ret = checksum_prepare_image(src, 0);
if (ret < 0)
return ret;
if (target->appendable) {
ret = checksum_prepare_nodes(src, (IsoNode *) src->root, 0);
if (ret < 0)
return ret;
}
target->checksum_idx_counter = 0;
}
#endif /* Libisofs_with_checksumS */
target->writers = malloc(nwriters * sizeof(void*));
if (target->writers == NULL) {
iso_image_unref(src);
@ -1019,7 +1135,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
/*
* Create the writer for possible padding to ensure that in case of image
* growing we can safety overwrite the first 64 KiB of image.
* growing we can safely overwrite the first 64 KiB of image.
*/
ret = pad_writer_create(target);
if (ret < 0) {
@ -1033,6 +1149,20 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
}
file_src_writer_index = target->nwriters - 1;
#ifdef Libisofs_with_checksumS
/* ??? Is it safe to add a writer after the content writer ? */
if (target->md5_checksums) {
ret = checksum_writer_create(target);
if (ret < 0)
goto target_cleanup;
}
#endif /* Libisofs_with_checksumS */
/*
* 3.
* Call compute_data_blocks() in each Writer.
@ -1140,7 +1270,15 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
target->vol_space_size = target->curblock - target->ms_block;
target->total_size = (off_t) target->vol_space_size * BLOCK_SIZE;
/* 4. Create and start writting thread */
/* 4. Create and start writing thread */
#ifdef Libisofs_with_checksumS
/* After any fake writes are done: Initialize image checksum context */
ret = libisofs_md5(&(target->checksum_ctx), NULL, 0, NULL, 1);
if (ret < 0)
return ret;
#endif /* Libisofs_with_checksumS */
/* ensure the thread is created joinable */
pthread_attr_init(&(target->th_attr));
@ -1306,6 +1444,17 @@ int iso_write(Ecma119Image *target, void *buf, size_t count)
return ISO_CANCELED;
}
#ifdef Libisofs_with_checksumS
if (target->checksum_ctx != NULL) {
/* Add to image checksum */
target->checksum_counter += count;
libisofs_md5(&(target->checksum_ctx), (char *) buf, (int) count,
NULL, 0);
}
#endif /* Libisofs_with_checksumS */
/* total size is 0 when writing the overwrite buffer */
if (ret > 0 && (target->total_size != (off_t) 0)){
unsigned int kbw, kbt;
@ -1710,7 +1859,7 @@ int iso_write_opts_set_fifo_size(IsoWriteOpts *opts, size_t fifo_size)
int iso_write_opts_get_data_start(IsoWriteOpts *opts, uint32_t *data_start,
int flag)
{
if(opts->data_start_lba == 0)
if (opts->data_start_lba == 0)
return ISO_ERROR;
*data_start = opts->data_start_lba;
return ISO_SUCCESS;