New API call iso_file_make_md5() to equip old file nodes with MD5.
This commit is contained in:
parent
cadd77776b
commit
3f918d1acb
@ -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;
|
||||
ret = iso_node_lookup_attr(node, "isofs.cx", &value_length,
|
||||
&value, 0);
|
||||
if (ret == 1 && img->checksum_array == 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 (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.
|
||||
|
@ -119,17 +119,21 @@ int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
|
||||
#ifdef Libisofs_with_checksumS
|
||||
|
||||
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);
|
||||
file->from_old_session && img->appendable) {
|
||||
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
|
||||
@ -319,46 +303,12 @@ int filesrc_read(IsoFileSrc *file, char *buf, size_t count)
|
||||
/* @return 1=ok, md5 is valid,
|
||||
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 */
|
||||
|
@ -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
|
||||
|
@ -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,25 +444,43 @@ 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);
|
||||
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];
|
||||
/* Look for checksums at various places */
|
||||
|
||||
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;
|
||||
|
||||
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++)
|
||||
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) {
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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_*/
|
||||
|
@ -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_*/
|
||||
|
Loading…
Reference in New Issue
Block a user