New API call iso_file_make_md5() to equip old file nodes with MD5.

This commit is contained in:
Thomas Schmitt 2009-08-22 19:38:07 +02:00
parent cadd77776b
commit 3f918d1acb
9 changed files with 282 additions and 94 deletions

View File

@ -962,10 +962,10 @@ int checksum_prepare_nodes(Ecma119Image *target, IsoNode *node, int flag)
IsoNode *pos; IsoNode *pos;
IsoFile *file; IsoFile *file;
IsoImage *img; IsoImage *img;
int ret, i, no_md5 = 0; int ret, i, no_md5 = 0, has_xinfo = 0;
size_t value_length; size_t value_length;
unsigned int idx = 0; unsigned int idx = 0;
char *value; char *value= NULL, *direct_md5;
void *xipt = NULL; void *xipt = NULL;
static char *cx_names = "isofs.cx"; static char *cx_names = "isofs.cx";
static size_t cx_value_lengths[1] = {0}; static size_t cx_value_lengths[1] = {0};
@ -978,10 +978,17 @@ int checksum_prepare_nodes(Ecma119Image *target, IsoNode *node, int flag)
if (file->from_old_session && target->appendable) { if (file->from_old_session && target->appendable) {
/* Save MD5 data of files from old image which will not /* Save MD5 data of files from old image which will not
be copied and have an MD5 recorded in the old image. */ be copied and have an MD5 recorded in the old image. */
value= NULL; has_xinfo = iso_node_get_xinfo(node, checksum_md5_xinfo_func,
ret = iso_node_lookup_attr(node, "isofs.cx", &value_length, &xipt);
&value, 0); if (has_xinfo <= 0) {
if (ret == 1 && img->checksum_array == NULL) { ret = iso_node_lookup_attr(node, "isofs.cx", &value_length,
&value, 0);
}
if (has_xinfo > 0) {
/* xinfo MD5 overrides everything else unless data get copied
and checksummed during that copying
*/;
} else if (ret == 1 && img->checksum_array == NULL) {
/* No checksum array loaded. Delete "isofs.cx" */ /* No checksum array loaded. Delete "isofs.cx" */
iso_node_set_attrs(node, (size_t) 1, iso_node_set_attrs(node, (size_t) 1,
&cx_names, cx_value_lengths, &cx_valuept, 4 | 8); &cx_names, cx_value_lengths, &cx_valuept, 4 | 8);
@ -993,7 +1000,7 @@ int checksum_prepare_nodes(Ecma119Image *target, IsoNode *node, int flag)
/* xipt is an int disguised as void pointer */ /* xipt is an int disguised as void pointer */
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
((char *) &xipt)[i] = value[i]; ((char *) &xipt)[i] = value[i];
ret = iso_node_add_xinfo(node, checksum_xinfo_func, ret = iso_node_add_xinfo(node, checksum_cx_xinfo_func,
xipt); xipt);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -1002,8 +1009,10 @@ int checksum_prepare_nodes(Ecma119Image *target, IsoNode *node, int flag)
} else { } else {
no_md5 = 1; no_md5 = 1;
} }
if (value != NULL) if (value != NULL) {
free(value); free(value);
value= NULL;
}
} }
/* Equip nodes with provisory isofs.cx numbers: 4 byte, all 0. /* Equip nodes with provisory isofs.cx numbers: 4 byte, all 0.
Omit those from old image which will not be copied and have no MD5. Omit those from old image which will not be copied and have no MD5.

View File

@ -119,17 +119,21 @@ int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
#ifdef Libisofs_with_checksumS #ifdef Libisofs_with_checksumS
if ((img->md5_file_checksums & 1) && if ((img->md5_file_checksums & 1) &&
file->from_old_session && img->appendable) { file->from_old_session && img->appendable) {
/* Omit MD5 indexing with old image nodes which have no MD5 */ ret = iso_node_get_xinfo((IsoNode *) file, checksum_md5_xinfo_func,
ret = iso_node_get_xinfo((IsoNode *) file, checksum_xinfo_func, &xipt); &xipt);
if (ret <= 0) if (ret <= 0)
ret = iso_node_get_xinfo((IsoNode *) file, checksum_cx_xinfo_func,
&xipt);
if (ret <= 0)
/* Omit MD5 indexing with old image nodes which have no MD5 */
no_md5 = 1; no_md5 = 1;
} }
if ((img->md5_file_checksums & 1) && !no_md5) { if ((img->md5_file_checksums & 1) && !no_md5) {
img->checksum_idx_counter++; img->checksum_idx_counter++;
if (img->checksum_idx_counter < 0x80000000) { if (img->checksum_idx_counter < 0x80000000) {
fsrc->checksum_index= img->checksum_idx_counter; fsrc->checksum_index = img->checksum_idx_counter;
} else { } else {
fsrc->checksum_index= 0; fsrc->checksum_index= 0;
img->checksum_idx_counter= 0x80000000; /* keep from rolling over */ img->checksum_idx_counter= 0x80000000; /* keep from rolling over */
@ -289,29 +293,9 @@ int filesrc_close(IsoFileSrc *file)
static static
int filesrc_read(IsoFileSrc *file, char *buf, size_t count) int filesrc_read(IsoFileSrc *file, char *buf, size_t count)
{ {
size_t bytes = 0; size_t got;
/* loop to ensure the full buffer is filled */ return iso_stream_read_buffer(file->stream, buf, count, &got);
do {
ssize_t result;
result = iso_stream_read(file->stream, buf + bytes, count - bytes);
if (result < 0) {
/* fill buffer with 0s and return */
memset(buf + bytes, 0, count - bytes);
return result;
}
if (result == 0)
break;
bytes += result;
} while (bytes < count);
if (bytes < count) {
/* eof */
memset(buf + bytes, 0, count - bytes);
return 0;
} else {
return 1;
}
} }
#ifdef Libisofs_with_checksumS #ifdef Libisofs_with_checksumS
@ -319,46 +303,12 @@ int filesrc_read(IsoFileSrc *file, char *buf, size_t count)
/* @return 1=ok, md5 is valid, /* @return 1=ok, md5 is valid,
0= not ok, go on, 0= not ok, go on,
<0 fatal error, abort <0 fatal error, abort
*/ */
static static
int filesrc_make_md5(Ecma119Image *t, IsoFileSrc *file, char md5[16], int flag) int filesrc_make_md5(Ecma119Image *t, IsoFileSrc *file, char md5[16], int flag)
{ {
int res, is_open = 0; return iso_stream_make_md5(file->stream, md5, 0);
char buffer[BLOCK_SIZE];
void *ctx= NULL;
off_t file_size;
uint32_t b, nblocks;
if (! iso_stream_is_repeatable(file->stream))
return 0;
res = iso_md5_start(&ctx);
if (res < 0)
return res;
res = filesrc_open(file);
if (res < 0)
return 0;
is_open = 1;
file_size = iso_file_src_get_size(file);
nblocks = DIV_UP(file_size, BLOCK_SIZE);
for (b = 0; b < nblocks; ++b) {
res = filesrc_read(file, buffer, BLOCK_SIZE);
if (res < 0) {
res = 0;
goto ex;
}
if (file_size - b * BLOCK_SIZE > BLOCK_SIZE)
res = BLOCK_SIZE;
else
res = file_size - b * BLOCK_SIZE;
iso_md5_compute(ctx, buffer, res);
}
res = 1;
ex:;
if (is_open)
filesrc_close(file);
if (ctx != NULL)
iso_md5_end(&ctx, md5);
return res;
} }
#endif /* Libisofs_with_checksumS */ #endif /* Libisofs_with_checksumS */

View File

@ -1424,10 +1424,13 @@ int iso_write_opts_set_sort_files(IsoWriteOpts *opts, int sort);
* @param opts * @param opts
* The option set to be manipulated. * The option set to be manipulated.
* @param session * @param session
* If bit0 set: compute session checksum * If bit0 set: Compute session checksum
* @param files * @param files
* If bit0 set: compute a checksum for each single IsoFile object. * If bit0 set: Compute a checksum for each single IsoFile object which
* If bit1 set: check content stability (only with bit0). I.e. before * gets its data content written into the session. Copy
* checksums from files which keep their data in older
* sessions.
* If bit1 set: Check content stability (only with bit0). I.e. before
* writing the file content into to image stream, read it * writing the file content into to image stream, read it
* once and compute a MD5. Do a second reading for writing * once and compute a MD5. Do a second reading for writing
* into the image stream. Afterwards compare both MD5 and * into the image stream. Afterwards compare both MD5 and
@ -5055,6 +5058,28 @@ 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); int iso_file_get_md5(IsoImage *image, IsoFile *file, char md5[16], int flag);
/**
* Read the content of an IsoFile object, compute its MD5 and attach it to
* the IsoFile. It can then be inquired by iso_file_get_md5() and will get
* written into the next session if this is enabled at write time and if the
* image write process does not compute an MD5 from content which it copies.
* So this call can be used to equip nodes from the old image with checksums
* or to make available checksums of newly added files before the session gets
* written.
* @param file
* The file object to read data from and to which to attach the checksum.
* If the file is from the imported image, then its most original stream
* will be checksummed. Else the eventual filter streams will get into
* effect.
* @param flag
* Bitfield for control purposes. Unused yet. Submit 0.
* @return
* 1= ok, MD5 is computed and attached , <0 indicates error
*
* @since 0.6.22
*/
int iso_file_make_md5(IsoFile *file, int flag);
/** /**
* Check a data block whether it is a libisofs session checksum tag and * Check a data block whether it is a libisofs session checksum tag and
* eventually obtain its recorded parameters. These tags get written after * eventually obtain its recorded parameters. These tags get written after

View File

@ -406,13 +406,25 @@ int iso_md5_match(char first_md5[16], char second_md5[16])
* data is supposed to be a 4 byte integer, bit 31 shall be 0, * data is supposed to be a 4 byte integer, bit 31 shall be 0,
* value 0 of this integer means that it is not a valid index. * value 0 of this integer means that it is not a valid index.
*/ */
int checksum_xinfo_func(void *data, int flag) int checksum_cx_xinfo_func(void *data, int flag)
{ {
/* data is an int disguised as pointer. It does not point to memory. */ /* data is an int disguised as pointer. It does not point to memory. */
return 1; return 1;
} }
/* Function to identify and manage md5 sums of unspecified providence stored
* directly in this xinfo.
*/
int checksum_md5_xinfo_func(void *data, int flag)
{
if (data == NULL)
return 1;
free(data);
return 1;
}
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
/* MD5 checksum image writer */ /* MD5 checksum image writer */
@ -432,25 +444,43 @@ int checksum_copy_old_nodes(Ecma119Image *target, IsoNode *node, int flag)
int ret, i; int ret, i;
size_t value_length; size_t value_length;
unsigned int idx = 0, old_idx = 0; unsigned int idx = 0, old_idx = 0;
char *value = NULL; char *value = NULL, *md5_pt = NULL;
void *xipt; void *xipt;
img = target->image; img = target->image;
if (img->checksum_array == NULL || target->checksum_buffer == NULL) if (target->checksum_buffer == NULL)
return 0; return 0;
if (node->type == LIBISO_FILE) { if (node->type == LIBISO_FILE) {
file = (IsoFile *) node; file = (IsoFile *) node;
if (file->from_old_session && target->appendable) { if (file->from_old_session && target->appendable) {
ret = iso_node_get_xinfo(node, checksum_xinfo_func, &xipt); /* Look for checksums at various places */
if (ret <= 0)
return ret;
/* xipt is an int disguised as void pointer */
old_idx = 0;
for (i = 0; i < 4; i++)
old_idx = (old_idx << 8) | ((unsigned char *) &xipt)[i];
if (old_idx == 0 || old_idx > img->checksum_idx_count - 1) /* Try checksum directly stored with node */
if (md5_pt == NULL) {
ret = iso_node_get_xinfo(node, checksum_md5_xinfo_func, &xipt);
if (ret < 0)
return ret;
if (ret == 1)
md5_pt = (char *) xipt;
}
/* Try checksum index to image checksum buffer */
if (md5_pt == NULL && img->checksum_array != NULL) {
ret = iso_node_get_xinfo(node, checksum_cx_xinfo_func, &xipt);
if (ret <= 0)
return ret;
/* xipt is an int disguised as void pointer */
old_idx = 0;
for (i = 0; i < 4; i++)
old_idx = (old_idx << 8) | ((unsigned char *) &xipt)[i];
if (old_idx == 0 || old_idx > img->checksum_idx_count - 1)
return 0;
md5_pt = img->checksum_array + 16 * old_idx;
}
if (md5_pt == NULL)
return 0; return 0;
ret = iso_node_lookup_attr(node, "isofs.cx", &value_length, ret = iso_node_lookup_attr(node, "isofs.cx", &value_length,
@ -459,12 +489,13 @@ int checksum_copy_old_nodes(Ecma119Image *target, IsoNode *node, int flag)
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
idx = (idx << 8) | ((unsigned char *) value)[i]; idx = (idx << 8) | ((unsigned char *) value)[i];
if (idx > 0 && idx <= target->checksum_idx_counter) { if (idx > 0 && idx <= target->checksum_idx_counter) {
memcpy(target->checksum_buffer + 16 * idx, memcpy(target->checksum_buffer + 16 * idx, md5_pt, 16);
img->checksum_array + 16 * old_idx, 16);
} }
} }
if (value != NULL) if (value != NULL)
free(value); free(value);
iso_node_remove_xinfo(node, checksum_md5_xinfo_func);
iso_node_remove_xinfo(node, checksum_cx_xinfo_func);
} }
} else if (node->type == LIBISO_DIR) { } else if (node->type == LIBISO_DIR) {
for (pos = ((IsoDir *) node)->children; pos != NULL; pos = pos->next) { for (pos = ((IsoDir *) node)->children; pos != NULL; pos = pos->next) {

View File

@ -19,13 +19,6 @@
int checksum_writer_create(Ecma119Image *target); int checksum_writer_create(Ecma119Image *target);
/* Function to identify and manage md5sum indice of the old image.
* data is supposed to be a 4 byte integer, bit 31 shall be 0,
* value 0 of this integer means that it is not a valid index.
*/
int checksum_xinfo_func(void *data, int flag);
/* Write stream detectable checksum tag to extra block. /* Write stream detectable checksum tag to extra block.
* All tag ranges start at the beginning of the System Area (i.e. t->ms_block) * All tag ranges start at the beginning of the System Area (i.e. t->ms_block)
* and stem from the same MD5 computation context. Tag types 2 and 3 are * and stem from the same MD5 computation context. Tag types 2 and 3 are

View File

@ -2678,6 +2678,14 @@ int iso_file_get_md5(IsoImage *image, IsoFile *file, char md5[16], int flag)
size_t value_len; size_t value_len;
char *value = NULL; char *value = NULL;
uint32_t idx = 0; uint32_t idx = 0;
void *xipt;
/* xinfo MD5 overrides everything else */
ret = iso_node_get_xinfo((IsoNode *) file, checksum_md5_xinfo_func, &xipt);
if (ret == 1) {
memcpy(md5, (char *) xipt, 16);
return 1;
}
if (image->checksum_array == NULL) if (image->checksum_array == NULL)
return 0; return 0;
@ -2714,3 +2722,40 @@ ex:;
} }
/* API */
int iso_file_make_md5(IsoFile *file, int flag)
{
#ifdef Libisofs_with_checksumS
int ret, dig = 0;
char *md5 = NULL;
if (file->from_old_session)
dig = 1;
md5= calloc(16, 1);
ret = iso_stream_make_md5(file->stream, md5, dig);
if (ret < 0)
goto ex;
iso_node_remove_xinfo((IsoNode *) file, checksum_md5_xinfo_func);
ret = iso_node_add_xinfo((IsoNode *) file, checksum_md5_xinfo_func, md5);
if (ret == 0)
ret = ISO_ERROR; /* should not happen after iso_node_remove_xinfo() */
if (ret < 0) {
free(md5);
goto ex;
}
ret = 1;
ex:;
return ret;
#else
return ISO_ERROR;
#endif /* ! Libisofs_with_checksumS */
}

View File

@ -830,3 +830,96 @@ int iso_stream_cmp_ino(IsoStream *s1, IsoStream *s2, int flag)
return 0; return 0;
} }
/**
* @return
* 1 ok, 0 EOF, < 0 error
*/
int iso_stream_read_buffer(IsoStream *stream, char *buf, size_t count,
size_t *got)
{
ssize_t result;
*got = 0;
do {
result = iso_stream_read(stream, buf + *got, count - *got);
if (result < 0) {
memset(buf + *got, 0, count - *got);
return result;
}
if (result == 0)
break;
*got += result;
} while (*got < count);
if (*got < count) {
/* eof */
memset(buf + *got, 0, count - *got);
return 0;
}
return 1;
}
#ifdef Libisofs_with_checksumS
/* @param flag bit0= dig out most original stream (e.g. because from old image)
@return 1=ok, md5 is valid,
0= not ok,
<0 fatal error, abort
*/
int iso_stream_make_md5(IsoStream *stream, char md5[16], int flag)
{
int res, is_open = 0;
char buffer[2048];
void *ctx= NULL;
off_t file_size;
uint32_t b, nblocks;
size_t got_bytes;
IsoStream *input_stream;
if (flag & 1) {
while(1) {
input_stream = iso_stream_get_input_stream(stream, 0);
if (input_stream == NULL)
break;
stream = input_stream;
}
}
if (! iso_stream_is_repeatable(stream))
return 0;
res = iso_md5_start(&ctx);
if (res < 0)
return res;
res = iso_stream_open(stream);
if (res < 0)
return 0;
is_open = 1;
file_size = iso_stream_get_size(stream);
nblocks = DIV_UP(file_size, 2048);
for (b = 0; b < nblocks; ++b) {
res = iso_stream_read_buffer(stream, buffer, 2048, &got_bytes);
if (res < 0) {
res = 0;
goto ex;
}
/* Do not use got_bytes to stay closer to IsoFileSrc processing */
if (file_size - b * 2048 > 2048)
res = 2048;
else
res = file_size - b * 2048;
iso_md5_compute(ctx, buffer, res);
}
res = 1;
ex:;
if (is_open)
iso_stream_close(stream);
if (ctx != NULL)
iso_md5_end(&ctx, md5);
return res;
}
#endif /* Libisofs_with_checksumS */

View File

@ -83,4 +83,24 @@ int iso_stream_get_src_zf(IsoStream *stream, int *header_size_div4,
int iso_stream_set_image_ino(IsoStream *stream, ino_t ino, int flag); int iso_stream_set_image_ino(IsoStream *stream, ino_t ino, int flag);
/**
* Read the full required amount of data unless error or EOF occurs.
* Fill missing bytes by 0s.
* @param count Required amount
* @param got Returns number of actually read bytes
* @return
* 1 no problem encountered, 0 EOF encountered, < 0 error
*/
int iso_stream_read_buffer(IsoStream *stream, char *buf, size_t count,
size_t *got);
/**
* @return 1=ok, md5 is valid,
* 0= not ok
* <0 fatal error, abort
*/
int iso_stream_make_md5(IsoStream *stream, char md5[16], int flag);
#endif /*STREAM_H_*/ #endif /*STREAM_H_*/

View File

@ -482,4 +482,26 @@ int iso_util_eval_md5_tag(char *block, int desired, uint32_t lba,
int iso_util_tag_magic(int tag_type, char **tag_magic, int *len, int flag); int iso_util_tag_magic(int tag_type, char **tag_magic, int *len, int flag);
/* ------------------------------------------------------------------------- */
/* In md5.h these function prototypes would be neighbors of (Ecma119Image *)
which needs inclusion of ecma119.h and more. So, being generic, they ended
up here.
*/
/* Function to identify and manage md5sum indice of the old image.
* data is supposed to be a 4 byte integer, bit 31 shall be 0,
* value 0 of this integer means that it is not a valid index.
*/
int checksum_cx_xinfo_func(void *data, int flag);
/* Function to identify and manage md5 sums of unspecified providence stored
* directly in this xinfo. This is supposed to override any other recorded
* MD5 of the node unless data get copied and checksummed during that copying.
*/
int checksum_md5_xinfo_func(void *data, int flag);
/* ------------------------------------------------------------------------- */
#endif /*LIBISO_UTIL_H_*/ #endif /*LIBISO_UTIL_H_*/