Introduced file content stability check with iso_write_opts_set_record_md5().
This commit is contained in:
parent
363a39af3e
commit
62edebad06
@ -19,10 +19,11 @@ is enabled by iso_read_opts_set_no_md5(). Loaded checksums can be inquired by
|
|||||||
iso_image_get_session_md5() and iso_file_get_md5().
|
iso_image_get_session_md5() and iso_file_get_md5().
|
||||||
|
|
||||||
Stream recognizable checksum tags occupy exactly one block each. They can
|
Stream recognizable checksum tags occupy exactly one block each. They can
|
||||||
be detected by submitting a read-in block to iso_util_decode_md5_tag().
|
be detected by submitting a block to iso_util_decode_md5_tag().
|
||||||
|
|
||||||
libisofs has own MD5 computation functions:
|
libisofs has own MD5 computation functions:
|
||||||
iso_md5_start(), iso_md5_compute(), iso_md5_clone(), iso_md5_end()
|
iso_md5_start(), iso_md5_compute(), iso_md5_clone(), iso_md5_end(),
|
||||||
|
iso_md5_match()
|
||||||
|
|
||||||
|
|
||||||
Representation in the Image
|
Representation in the Image
|
||||||
|
@ -1135,7 +1135,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
|
|||||||
|
|
||||||
#ifdef Libisofs_with_checksumS
|
#ifdef Libisofs_with_checksumS
|
||||||
|
|
||||||
if (target->md5_file_checksums || target->md5_session_checksum) {
|
if ((target->md5_file_checksums & 1) || target->md5_session_checksum) {
|
||||||
nwriters++;
|
nwriters++;
|
||||||
ret = checksum_prepare_image(src, 0);
|
ret = checksum_prepare_image(src, 0);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -1213,7 +1213,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
|
|||||||
|
|
||||||
#ifdef Libisofs_with_checksumS
|
#ifdef Libisofs_with_checksumS
|
||||||
|
|
||||||
if (target->md5_file_checksums || target->md5_session_checksum) {
|
if ((target->md5_file_checksums & 1) || target->md5_session_checksum) {
|
||||||
ret = checksum_writer_create(target);
|
ret = checksum_writer_create(target);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto target_cleanup;
|
goto target_cleanup;
|
||||||
@ -1805,8 +1805,8 @@ int iso_write_opts_set_record_md5(IsoWriteOpts *opts, int session, int files)
|
|||||||
|
|
||||||
#ifdef Libisofs_with_checksumS
|
#ifdef Libisofs_with_checksumS
|
||||||
|
|
||||||
opts->md5_session_checksum = !!session;
|
opts->md5_session_checksum = session & 1;
|
||||||
opts->md5_file_checksums = !!files;
|
opts->md5_file_checksums = files & 3;
|
||||||
|
|
||||||
#endif /* Libisofs_with_checksumS */
|
#endif /* Libisofs_with_checksumS */
|
||||||
|
|
||||||
|
@ -163,8 +163,11 @@ struct iso_write_opts {
|
|||||||
* blocks will be recorded in xattr "isofs.ca" of the root node.
|
* blocks will be recorded in xattr "isofs.ca" of the root node.
|
||||||
* The indice of the MD5 sums will be recorded with the IsoFile directory
|
* The indice of the MD5 sums will be recorded with the IsoFile directory
|
||||||
* entries as xattr "isofs.cx". See also API call iso_file_get_md5().
|
* entries as xattr "isofs.cx". See also API call iso_file_get_md5().
|
||||||
|
* bit0= compute individual checksums
|
||||||
|
* bit1= pre-compute checksum and compare it with actual one.
|
||||||
|
* Raise MISHAP if mismatch.
|
||||||
*/
|
*/
|
||||||
unsigned int md5_file_checksums :1;
|
unsigned int md5_file_checksums :2;
|
||||||
|
|
||||||
#endif /* Libisofs_with_checksumS */
|
#endif /* Libisofs_with_checksumS */
|
||||||
|
|
||||||
@ -336,7 +339,7 @@ struct ecma119_image
|
|||||||
#ifdef Libisofs_with_checksumS
|
#ifdef Libisofs_with_checksumS
|
||||||
|
|
||||||
unsigned int md5_session_checksum :1;
|
unsigned int md5_session_checksum :1;
|
||||||
unsigned int md5_file_checksums :1;
|
unsigned int md5_file_checksums :2;
|
||||||
|
|
||||||
#endif /* Libisofs_with_checksumS */
|
#endif /* Libisofs_with_checksumS */
|
||||||
|
|
||||||
|
@ -118,14 +118,15 @@ int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
|
|||||||
|
|
||||||
#ifdef Libisofs_with_checksumS
|
#ifdef Libisofs_with_checksumS
|
||||||
|
|
||||||
if (img->md5_file_checksums && file->from_old_session && img->appendable) {
|
if ((img->md5_file_checksums & 1) &&
|
||||||
|
file->from_old_session && img->appendable) {
|
||||||
/* Omit MD5 indexing with old image nodes which have no MD5 */
|
/* 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_xinfo_func, &xipt);
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
no_md5 = 1;
|
no_md5 = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (img->md5_file_checksums && !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;
|
||||||
@ -313,10 +314,59 @@ int filesrc_read(IsoFileSrc *file, char *buf, size_t count)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef Libisofs_with_checksumS
|
||||||
|
|
||||||
|
/* @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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* Libisofs_with_checksumS */
|
||||||
|
|
||||||
static
|
static
|
||||||
int filesrc_writer_write_data(IsoImageWriter *writer)
|
int filesrc_writer_write_data(IsoImageWriter *writer)
|
||||||
{
|
{
|
||||||
int res, ret;
|
int res, ret, was_error;
|
||||||
size_t i, b;
|
size_t i, b;
|
||||||
Ecma119Image *t;
|
Ecma119Image *t;
|
||||||
IsoFileSrc *file;
|
IsoFileSrc *file;
|
||||||
@ -328,7 +378,8 @@ int filesrc_writer_write_data(IsoImageWriter *writer)
|
|||||||
|
|
||||||
#ifdef Libisofs_with_checksumS
|
#ifdef Libisofs_with_checksumS
|
||||||
void *ctx= NULL;
|
void *ctx= NULL;
|
||||||
char md5[16];
|
char md5[16], pre_md5[16];
|
||||||
|
int pre_md5_valid = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -343,10 +394,19 @@ int filesrc_writer_write_data(IsoImageWriter *writer)
|
|||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
while ((file = filelist[i++]) != NULL) {
|
while ((file = filelist[i++]) != NULL) {
|
||||||
|
was_error = 0;
|
||||||
file_size = iso_file_src_get_size(file);
|
file_size = iso_file_src_get_size(file);
|
||||||
nblocks = DIV_UP(file_size, BLOCK_SIZE);
|
nblocks = DIV_UP(file_size, BLOCK_SIZE);
|
||||||
|
|
||||||
/* >>> Eventually obtain an MD5 of content by a first read pass */;
|
#ifdef Libisofs_with_checksumS
|
||||||
|
|
||||||
|
pre_md5_valid = 0;
|
||||||
|
if (file->checksum_index > 0 && (t->md5_file_checksums & 2)) {
|
||||||
|
/* Obtain an MD5 of content by a first read pass */
|
||||||
|
pre_md5_valid = filesrc_make_md5(t, file, pre_md5, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* Libisofs_with_checksumS */
|
||||||
|
|
||||||
res = filesrc_open(file);
|
res = filesrc_open(file);
|
||||||
iso_stream_get_file_name(file->stream, name);
|
iso_stream_get_file_name(file->stream, name);
|
||||||
@ -356,6 +416,7 @@ int filesrc_writer_write_data(IsoImageWriter *writer)
|
|||||||
* 0's to image
|
* 0's to image
|
||||||
*/
|
*/
|
||||||
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
|
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
|
||||||
|
was_error = 1;
|
||||||
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res,
|
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res,
|
||||||
"File \"%s\" can't be opened. Filling with 0s.", name);
|
"File \"%s\" can't be opened. Filling with 0s.", name);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
@ -374,6 +435,7 @@ int filesrc_writer_write_data(IsoImageWriter *writer)
|
|||||||
continue;
|
continue;
|
||||||
} else if (res > 1) {
|
} else if (res > 1) {
|
||||||
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
|
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
|
||||||
|
was_error = 1;
|
||||||
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0,
|
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0,
|
||||||
"Size of file \"%s\" has changed. It will be %s", name,
|
"Size of file \"%s\" has changed. It will be %s", name,
|
||||||
(res == 2 ? "truncated" : "padded with 0's"));
|
(res == 2 ? "truncated" : "padded with 0's"));
|
||||||
@ -421,9 +483,10 @@ int filesrc_writer_write_data(IsoImageWriter *writer)
|
|||||||
|
|
||||||
if (file->checksum_index > 0) {
|
if (file->checksum_index > 0) {
|
||||||
/* Add to file checksum */
|
/* Add to file checksum */
|
||||||
res = file_size - b * BLOCK_SIZE;
|
if (file_size - b * BLOCK_SIZE > BLOCK_SIZE)
|
||||||
if (res > BLOCK_SIZE)
|
|
||||||
res = BLOCK_SIZE;
|
res = BLOCK_SIZE;
|
||||||
|
else
|
||||||
|
res = file_size - b * BLOCK_SIZE;
|
||||||
res = iso_md5_compute(ctx, buffer, res);
|
res = iso_md5_compute(ctx, buffer, res);
|
||||||
if (res <= 0)
|
if (res <= 0)
|
||||||
file->checksum_index = 0;
|
file->checksum_index = 0;
|
||||||
@ -438,6 +501,7 @@ int filesrc_writer_write_data(IsoImageWriter *writer)
|
|||||||
if (b < nblocks) {
|
if (b < nblocks) {
|
||||||
/* premature end of file, due to error or eof */
|
/* premature end of file, due to error or eof */
|
||||||
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
|
iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
|
||||||
|
was_error = 1;
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
/* error */
|
/* error */
|
||||||
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res,
|
res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res,
|
||||||
@ -469,9 +533,10 @@ int filesrc_writer_write_data(IsoImageWriter *writer)
|
|||||||
|
|
||||||
if (file->checksum_index > 0) {
|
if (file->checksum_index > 0) {
|
||||||
/* Add to file checksum */
|
/* Add to file checksum */
|
||||||
res = file_size - b * BLOCK_SIZE;
|
if (file_size - b * BLOCK_SIZE > BLOCK_SIZE)
|
||||||
if (res > BLOCK_SIZE)
|
|
||||||
res = BLOCK_SIZE;
|
res = BLOCK_SIZE;
|
||||||
|
else
|
||||||
|
res = file_size - b * BLOCK_SIZE;
|
||||||
res = iso_md5_compute(ctx, buffer, res);
|
res = iso_md5_compute(ctx, buffer, res);
|
||||||
if (res <= 0)
|
if (res <= 0)
|
||||||
file->checksum_index = 0;
|
file->checksum_index = 0;
|
||||||
@ -489,10 +554,21 @@ int filesrc_writer_write_data(IsoImageWriter *writer)
|
|||||||
res = iso_md5_end(&ctx, md5);
|
res = iso_md5_end(&ctx, md5);
|
||||||
if (res <= 0)
|
if (res <= 0)
|
||||||
file->checksum_index = 0;
|
file->checksum_index = 0;
|
||||||
|
if ((t->md5_file_checksums & 2) && pre_md5_valid > 0 &&
|
||||||
/* >>> Eventually compare with MD5 of first read pass
|
!was_error) {
|
||||||
and issue error if mismatch */;
|
if (! iso_md5_match(md5, pre_md5)) {
|
||||||
|
/* Issue MISHAP event */
|
||||||
|
iso_report_errfile(name, ISO_MD5_STREAM_CHANGE, 0, 0);
|
||||||
|
was_error = 1;
|
||||||
|
res = iso_msg_submit(t->image->id, ISO_MD5_STREAM_CHANGE,0,
|
||||||
|
"Content of file '%s' changed while it was written into the image.",
|
||||||
|
name);
|
||||||
|
if (res < 0) {
|
||||||
|
ret = res; /* aborted due to error severity */
|
||||||
|
goto ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
/* Write md5 into checksum buffer at file->checksum_index */
|
/* Write md5 into checksum buffer at file->checksum_index */
|
||||||
memcpy(t->checksum_buffer + 16 * file->checksum_index, md5, 16);
|
memcpy(t->checksum_buffer + 16 * file->checksum_index, md5, 16);
|
||||||
}
|
}
|
||||||
|
@ -1424,9 +1424,21 @@ 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 not 0: compute session checksum
|
* If bit0 set: compute session checksum
|
||||||
* @param files
|
* @param files
|
||||||
* If not 0: compute a checksum for each single IsoFile object.
|
* If bit0 set: compute a checksum for each single IsoFile object.
|
||||||
|
* 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
|
||||||
|
* issue a MISHAP event ISO_MD5_STREAM_CHANGE if they do not
|
||||||
|
* match.
|
||||||
|
* Such a mismatch indicates content changes between the
|
||||||
|
* time point when the first MD5 reading started and the
|
||||||
|
* time point when the last block was read for writing.
|
||||||
|
* So there is high risk that the image stream was fed from
|
||||||
|
* changing and possibly inconsistent file content.
|
||||||
|
*
|
||||||
* @since 0.6.22
|
* @since 0.6.22
|
||||||
*/
|
*/
|
||||||
int iso_write_opts_set_record_md5(IsoWriteOpts *opts, int session, int files);
|
int iso_write_opts_set_record_md5(IsoWriteOpts *opts, int session, int files);
|
||||||
@ -5478,6 +5490,13 @@ int iso_md5_match(char first_md5[16], char second_md5[16]);
|
|||||||
*/
|
*/
|
||||||
#define ISO_MD5_TAG_OTHER_RANGE 0xD030FE9B
|
#define ISO_MD5_TAG_OTHER_RANGE 0xD030FE9B
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detected file content changes while it was written into the image.
|
||||||
|
* (MISHAP, HIGH, -358)
|
||||||
|
* @since 0.6.22
|
||||||
|
*/
|
||||||
|
#define ISO_MD5_STREAM_CHANGE 0xE430FE9A
|
||||||
|
|
||||||
|
|
||||||
/* ! PLACE NEW ERROR CODES HERE ! */
|
/* ! PLACE NEW ERROR CODES HERE ! */
|
||||||
|
|
||||||
|
@ -272,6 +272,8 @@ const char *iso_error_to_msg(int errcode)
|
|||||||
return "Misplaced checksum tag type encountered";
|
return "Misplaced checksum tag type encountered";
|
||||||
case ISO_MD5_TAG_OTHER_RANGE:
|
case ISO_MD5_TAG_OTHER_RANGE:
|
||||||
return "Checksum tag with unexpected address range encountered";
|
return "Checksum tag with unexpected address range encountered";
|
||||||
|
case ISO_MD5_STREAM_CHANGE:
|
||||||
|
return "Detected file content changes while it was written into the image";
|
||||||
default:
|
default:
|
||||||
return "Unknown error";
|
return "Unknown error";
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user