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;
IsoFile *file;
IsoImage *img;
int ret, i, no_md5 = 0;
int ret, i, no_md5 = 0, has_xinfo = 0;
size_t value_length;
unsigned int idx = 0;
char *value;
char *value= NULL, *direct_md5;
void *xipt = NULL;
static char *cx_names = "isofs.cx";
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) {
/* Save MD5 data of files from old image which will not
be copied and have an MD5 recorded in the old image. */
value= NULL;
has_xinfo = iso_node_get_xinfo(node, checksum_md5_xinfo_func,
&xipt);
if (has_xinfo <= 0) {
ret = iso_node_lookup_attr(node, "isofs.cx", &value_length,
&value, 0);
if (ret == 1 && img->checksum_array == NULL) {
}
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" */
iso_node_set_attrs(node, (size_t) 1,
&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 */
for (i = 0; i < 4; 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);
if (ret < 0)
return ret;
@ -1002,8 +1009,10 @@ int checksum_prepare_nodes(Ecma119Image *target, IsoNode *node, int flag)
} else {
no_md5 = 1;
}
if (value != NULL)
if (value != NULL) {
free(value);
value= NULL;
}
}
/* 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.

View File

@ -120,16 +120,20 @@ int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
if ((img->md5_file_checksums & 1) &&
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_xinfo_func, &xipt);
ret = iso_node_get_xinfo((IsoNode *) file, checksum_md5_xinfo_func,
&xipt);
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;
}
if ((img->md5_file_checksums & 1) && !no_md5) {
img->checksum_idx_counter++;
if (img->checksum_idx_counter < 0x80000000) {
fsrc->checksum_index= img->checksum_idx_counter;
fsrc->checksum_index = img->checksum_idx_counter;
} else {
fsrc->checksum_index= 0;
img->checksum_idx_counter= 0x80000000; /* keep from rolling over */
@ -289,29 +293,9 @@ int filesrc_close(IsoFileSrc *file)
static
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 */
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;
}
return iso_stream_read_buffer(file->stream, buf, count, &got);
}
#ifdef Libisofs_with_checksumS
@ -320,45 +304,11 @@ int filesrc_read(IsoFileSrc *file, char *buf, size_t count)
0= not ok, go on,
<0 fatal error, abort
*/
static
int filesrc_make_md5(Ecma119Image *t, IsoFileSrc *file, char md5[16], int flag)
{
int res, is_open = 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;
return iso_stream_make_md5(file->stream, md5, 0);
}
#endif /* Libisofs_with_checksumS */

View File

@ -1424,10 +1424,13 @@ int iso_write_opts_set_sort_files(IsoWriteOpts *opts, int sort);
* @param opts
* The option set to be manipulated.
* @param session
* If bit0 set: compute session checksum
* If bit0 set: Compute session checksum
* @param files
* If bit0 set: compute a checksum for each single IsoFile object.
* If bit1 set: check content stability (only with bit0). I.e. before
* If bit0 set: Compute a checksum for each single IsoFile object which
* 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
* once and compute a MD5. Do a second reading for writing
* 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);
/**
* 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
* 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,
* 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. */
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 */
@ -432,17 +444,30 @@ int checksum_copy_old_nodes(Ecma119Image *target, IsoNode *node, int flag)
int ret, i;
size_t value_length;
unsigned int idx = 0, old_idx = 0;
char *value = NULL;
char *value = NULL, *md5_pt = NULL;
void *xipt;
img = target->image;
if (img->checksum_array == NULL || target->checksum_buffer == NULL)
if (target->checksum_buffer == NULL)
return 0;
if (node->type == LIBISO_FILE) {
file = (IsoFile *) node;
if (file->from_old_session && target->appendable) {
ret = iso_node_get_xinfo(node, checksum_xinfo_func, &xipt);
/* Look for checksums at various places */
/* 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 */
@ -452,6 +477,11 @@ int checksum_copy_old_nodes(Ecma119Image *target, IsoNode *node, int flag)
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;
ret = iso_node_lookup_attr(node, "isofs.cx", &value_length,
&value, 0);
@ -459,12 +489,13 @@ int checksum_copy_old_nodes(Ecma119Image *target, IsoNode *node, int flag)
for (i = 0; i < 4; i++)
idx = (idx << 8) | ((unsigned char *) value)[i];
if (idx > 0 && idx <= target->checksum_idx_counter) {
memcpy(target->checksum_buffer + 16 * idx,
img->checksum_array + 16 * old_idx, 16);
memcpy(target->checksum_buffer + 16 * idx, md5_pt, 16);
}
}
if (value != NULL)
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) {
for (pos = ((IsoDir *) node)->children; pos != NULL; pos = pos->next) {

View File

@ -19,13 +19,6 @@
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.
* 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

View File

@ -2678,6 +2678,14 @@ int iso_file_get_md5(IsoImage *image, IsoFile *file, char md5[16], int flag)
size_t value_len;
char *value = NULL;
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)
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
* 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);
/**
* 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_*/

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);
/* ------------------------------------------------------------------------- */
/* 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_*/