New -check_media option async_chunks=
This commit is contained in:
parent
917b487343
commit
6668ab7d32
@ -571,6 +571,7 @@ int Checkmediajob_new(struct CheckmediajoB **o, int flag)
|
||||
m->min_lba= -1;
|
||||
m->max_lba= -1;
|
||||
m->min_block_size= 0;
|
||||
m->async_chunks= 0;
|
||||
m->mode= 0;
|
||||
m->start_time= time(NULL);
|
||||
m->time_limit= 28800;
|
||||
@ -655,6 +656,12 @@ int Xorriso_check_media_setup_job(struct XorrisO *xorriso,
|
||||
ret= Sfile_str(job->abort_file_path, argv[i] + 11, 0);
|
||||
if(ret <= 0)
|
||||
goto ex;
|
||||
} else if(strncmp(argv[i], "async_chunks=", 13) == 0) {
|
||||
num= Scanf_io_size(argv[i] + 13, 1);
|
||||
if(num >= 0 && num <= 1024)
|
||||
job->async_chunks= num;
|
||||
else
|
||||
goto bad_value;
|
||||
} else if(strncmp(argv[i], "bad_limit=", 10) == 0) {
|
||||
if(strcmp(argv[i] + 10, "good") == 0)
|
||||
xorriso->check_media_bad_limit= Xorriso_read_quality_gooD;
|
||||
@ -689,7 +696,7 @@ int Xorriso_check_media_setup_job(struct XorrisO *xorriso,
|
||||
if(num >= 2048 || num == 0)
|
||||
job->min_block_size= num / 2048;
|
||||
else
|
||||
goto unknown_value;
|
||||
goto bad_value;
|
||||
} else if(strncmp(argv[i], "event=", 6) == 0) {
|
||||
strncpy(sev_text, argv[i] + 6, 19);
|
||||
sev_text[19]= 0;
|
||||
@ -731,7 +738,7 @@ int Xorriso_check_media_setup_job(struct XorrisO *xorriso,
|
||||
num= -1;
|
||||
sscanf(argv[i] + 11, "%lf", &num);
|
||||
if(num > 0x7fffffff || num < 0)
|
||||
goto unknown_value;
|
||||
goto bad_value;
|
||||
job->patch_lba0_msc1= num;
|
||||
job->patch_lba0= (num >= 32) + (strstr(argv[i] + 11, ":force") != NULL);
|
||||
} else
|
||||
@ -815,6 +822,11 @@ unknown_value:;
|
||||
"-check_media: Unknown value with option %s", argv[i]);
|
||||
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
|
||||
ret= 0; goto ex;
|
||||
bad_value:;
|
||||
sprintf(xorriso->info_text,
|
||||
"-check_media: Unsuitable value with option %s", argv[i]);
|
||||
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
|
||||
ret= 0; goto ex;
|
||||
}
|
||||
} else {
|
||||
sprintf(xorriso->info_text, "-check_media: Unknown option '%s'", argv[i]);
|
||||
|
@ -99,7 +99,10 @@ struct CheckmediajoB {
|
||||
int max_lba; /* if >=0 : read up to this address, else use mode */
|
||||
|
||||
int min_block_size; /* granularity desired by user
|
||||
*/
|
||||
*/
|
||||
int async_chunks; /* >= 2 : run MD5 thread, use given number of chunks
|
||||
else : synchronous
|
||||
*/
|
||||
int mode; /* 0= track by track
|
||||
1= single sweep over libisoburn medium capacity
|
||||
2= single sweep over libburn medium capacity
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
#include "xorriso.h"
|
||||
@ -2106,6 +2107,312 @@ int Xorriso_check_for_abort(struct XorrisO *xorriso,
|
||||
}
|
||||
|
||||
|
||||
struct xorriso_md5_state {
|
||||
|
||||
/* Resources */
|
||||
struct XorrisO *xorriso;
|
||||
void *ctx;
|
||||
struct SpotlisT *spotlist;
|
||||
pthread_mutex_t spot_mutex;
|
||||
|
||||
/* Checksum tag cursor */
|
||||
uint32_t md5_start;
|
||||
uint32_t next_tag;
|
||||
int chain_broken;
|
||||
int in_track_gap;
|
||||
int was_sb_tag;
|
||||
int md5_spot_value;
|
||||
uint32_t md5_spot_lba;
|
||||
|
||||
/* Asynchronous operation */
|
||||
|
||||
int slave_state; /* Operated by slave
|
||||
0= not yet started
|
||||
1= slave is started
|
||||
2= slave has reached its end
|
||||
3= slave failed to start
|
||||
*/
|
||||
int chunk_size;
|
||||
int num_chunks;
|
||||
char **chunk;
|
||||
int *chunk_state; /* 0= content invalid (set by boss at creation time),
|
||||
1= content readable (set by boss),
|
||||
2= content was read (set by MD5 slave),
|
||||
3= end-of-processing (set by boss when done)
|
||||
*/
|
||||
int *chunk_fill; /* Actual number of valid bytes in chunk */
|
||||
uint32_t *chunk_lba;
|
||||
int chunk_w_idx; /* Write index. Operated by boss */
|
||||
int chunk_r_idx; /* Read index. Operated by MD5 slave */
|
||||
|
||||
off_t w_sleeps;
|
||||
off_t r_sleeps;
|
||||
|
||||
};
|
||||
|
||||
|
||||
int Xorriso__add_spot(struct xorriso_md5_state *state,
|
||||
int start_lba, int blocks, int quality, int flag)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if(state->chunk != NULL) {
|
||||
ret= pthread_mutex_lock(&(state->spot_mutex));
|
||||
if(ret != 0)
|
||||
return(0);
|
||||
}
|
||||
ret= Spotlist_add_item(state->spotlist, start_lba, blocks, quality, 0);
|
||||
if(state->chunk != NULL)
|
||||
pthread_mutex_unlock(&(state->spot_mutex));
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
int Xorriso_chunk_md5(struct XorrisO *xorriso, char *data, int to_read,
|
||||
uint32_t from_lba, struct xorriso_md5_state *state, int flag)
|
||||
{
|
||||
int j, ret= 0, valid, tag_type;
|
||||
uint32_t lba, pos, range_start, range_size;
|
||||
char md5[16], tag_md5[16], *tag_type_name= "", *comparison, *sev_text;
|
||||
void *cloned_ctx= NULL;
|
||||
|
||||
for(j= 0; j < to_read; j++) {
|
||||
lba= j + from_lba;
|
||||
if(lba < state->md5_start)
|
||||
continue;
|
||||
ret= 0;
|
||||
if(lba > state->md5_start + 16 &&
|
||||
(state->next_tag == 0 || state->chain_broken || lba == state->next_tag)){
|
||||
ret= iso_util_decode_md5_tag(data + j * 2048, &tag_type,
|
||||
&pos, &range_start, &range_size,
|
||||
&(state->next_tag), tag_md5,
|
||||
!!state->chain_broken);
|
||||
}
|
||||
valid= (ret == 1 || ret == (int) ISO_MD5_AREA_CORRUPTED) && pos == lba;
|
||||
if(valid && tag_type == 2 && (lba < state->md5_start + 32 ||
|
||||
state->in_track_gap)){
|
||||
tag_type_name= "superblock";
|
||||
state->was_sb_tag= 1;
|
||||
if(state->in_track_gap && range_start != state->md5_start &&
|
||||
range_start < lba && lba - range_start <= (uint32_t) j) {
|
||||
/* Looking for next session : start computing in hindsight.
|
||||
Session start and superblock tag are supposed to be in the
|
||||
same 64 kB chunk.
|
||||
*/
|
||||
iso_md5_end(&(state->ctx), md5);
|
||||
ret= iso_md5_start(&(state->ctx));
|
||||
if(ret < 0) {
|
||||
Xorriso_no_malloc_memory(xorriso, NULL, 0);
|
||||
ret= -1; goto ex;
|
||||
}
|
||||
iso_md5_compute(&(state->ctx), data + (j - (lba - range_start)) * 2048,
|
||||
(lba - range_start) * 2048);
|
||||
state->md5_start= range_start;
|
||||
state->in_track_gap= 0;
|
||||
}
|
||||
} else if(valid && tag_type == 4 && lba < 32) {
|
||||
tag_type_name= "relocated 64kB superblock";
|
||||
}else if(valid && tag_type == 3 && state->was_sb_tag) {
|
||||
tag_type_name= "tree";
|
||||
}else if(valid && tag_type == 1) {
|
||||
|
||||
/* >>> ??? allow this without superblock and tree tag ? */
|
||||
|
||||
tag_type_name= "session";
|
||||
} else {
|
||||
tag_type_name= "";
|
||||
}
|
||||
if (tag_type_name[0]) {
|
||||
if(range_start != state->md5_start) {
|
||||
sprintf(xorriso->info_text,
|
||||
"Found MD5 %s tag which covers different data range", tag_type_name);
|
||||
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE",0);
|
||||
sprintf(xorriso->info_text, " Expected: %u Found: %u",
|
||||
(unsigned int) state->md5_start, range_start);
|
||||
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE",0);
|
||||
state->chain_broken= 1;
|
||||
valid= 0;
|
||||
} else {
|
||||
ret= iso_md5_clone(state->ctx, &cloned_ctx);
|
||||
if(ret <= 0) {
|
||||
Xorriso_no_malloc_memory(xorriso, NULL, 0);
|
||||
ret= -1; goto ex;
|
||||
}
|
||||
iso_md5_end(&cloned_ctx, md5);
|
||||
|
||||
if(ret == (int) ISO_MD5_AREA_CORRUPTED) {
|
||||
comparison= "CORRUPTED";
|
||||
sev_text= "WARNING";
|
||||
state->md5_spot_value= Xorriso_read_quality_md5_mismatcH;
|
||||
state->chain_broken= 1;
|
||||
} else if(! iso_md5_match(tag_md5, md5)) {
|
||||
comparison= "NON-MATCHING";
|
||||
sev_text= "WARNING";
|
||||
state->md5_spot_value= Xorriso_read_quality_md5_mismatcH;
|
||||
state->chain_broken= 1;
|
||||
} else {
|
||||
comparison= "matching";
|
||||
sev_text= "UPDATE";
|
||||
state->md5_spot_value= Xorriso_read_quality_md5_matcH;
|
||||
}
|
||||
state->md5_spot_lba= lba;
|
||||
sprintf(xorriso->info_text,
|
||||
"Found %s MD5 %s tag: start=%d size=%d",
|
||||
comparison, tag_type_name, state->md5_start,
|
||||
lba - state->md5_start);
|
||||
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, sev_text, 0);
|
||||
}
|
||||
if(valid && (tag_type == 1 || (tag_type == 4 && pos == lba && lba < 32))){
|
||||
if(state->md5_spot_value != Xorriso_read_quality_untesteD) {
|
||||
ret= Xorriso__add_spot(state, state->md5_start,
|
||||
state->md5_spot_lba - state->md5_start, state->md5_spot_value, 0);
|
||||
if(ret <= 0)
|
||||
goto ex;
|
||||
}
|
||||
state->md5_spot_value= Xorriso_read_quality_untesteD;
|
||||
state->md5_start = lba + 1;
|
||||
if(state->md5_start % 32)
|
||||
state->md5_start= state->md5_start + (32 - (state->md5_start % 32));
|
||||
state->next_tag= 0;
|
||||
|
||||
iso_md5_end(&(state->ctx), md5);
|
||||
ret= iso_md5_start(&(state->ctx));
|
||||
if(ret < 0) {
|
||||
Xorriso_no_malloc_memory(xorriso, NULL, 0);
|
||||
ret= -1; goto ex;
|
||||
}
|
||||
if(tag_type == 1)
|
||||
state->in_track_gap= 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
iso_md5_compute(state->ctx, data + j * 2048, 2048);
|
||||
}
|
||||
ret= 1;
|
||||
ex:;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
static void *Xorriso__md5_slave(void *state_pt)
|
||||
{
|
||||
struct xorriso_md5_state *state;
|
||||
int ret, c_state, c_idx;
|
||||
static int u_wait= 1;
|
||||
|
||||
state= state_pt;
|
||||
state->slave_state= 1;
|
||||
|
||||
while(1) {
|
||||
c_idx= state->chunk_r_idx;
|
||||
c_state= state->chunk_state[c_idx];
|
||||
if(c_state == 1) {
|
||||
ret= Xorriso_chunk_md5(state->xorriso, state->chunk[c_idx],
|
||||
state->chunk_fill[c_idx], state->chunk_lba[c_idx],
|
||||
state, 0);
|
||||
if(ret <= 0)
|
||||
goto ex;
|
||||
state->chunk_state[c_idx]= 2;
|
||||
state->chunk_r_idx= (c_idx + 1) % state->num_chunks;
|
||||
} else if(c_state == 3) {
|
||||
goto ex;
|
||||
} else {
|
||||
|
||||
/* >>> have a timeout ? */;
|
||||
|
||||
if(u_wait > 0)
|
||||
usleep(u_wait);
|
||||
state->r_sleeps++;
|
||||
}
|
||||
}
|
||||
|
||||
ex:;
|
||||
state->slave_state= 2;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int Xorriso_start_chunk_md5(struct XorrisO *xorriso,
|
||||
struct xorriso_md5_state *state, int flag)
|
||||
{
|
||||
int ret, u_wait= 1000;
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_t *attr_pt = NULL;
|
||||
pthread_t thread;
|
||||
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
attr_pt= &attr;
|
||||
|
||||
ret= pthread_create(&thread, attr_pt, Xorriso__md5_slave, state);
|
||||
if(ret != 0) {
|
||||
sprintf(xorriso->info_text,
|
||||
"-check_media: Cannot create thread for MD5 computation");
|
||||
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
|
||||
ret= 0; goto ex;
|
||||
}
|
||||
|
||||
while(state->slave_state != 1) {
|
||||
|
||||
/* >>> have a timeout ? */;
|
||||
/* >>> if this fails set state->slave_state= 3 */
|
||||
|
||||
usleep(u_wait);
|
||||
}
|
||||
ret= 1;
|
||||
ex:;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
int Xorriso__wait_chunk_md5(struct xorriso_md5_state *state,
|
||||
int u_wait, int flag)
|
||||
{
|
||||
while(state->chunk_state[state->chunk_w_idx] == 1) {
|
||||
|
||||
/* >>> have a timeout ? */;
|
||||
|
||||
usleep(u_wait);
|
||||
state->w_sleeps++;
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
int Xorriso__wait_slave_md5_end(struct xorriso_md5_state *state,
|
||||
int u_wait, int flag)
|
||||
{
|
||||
while(state->slave_state == 1) {
|
||||
|
||||
/* >>> have a timeout ? */;
|
||||
|
||||
usleep(u_wait);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
int Xorriso__end_slave_md5(struct xorriso_md5_state *state,
|
||||
int u_wait, int flag)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
/* Tell slave thread to end */
|
||||
for(i= 0; i < state->num_chunks; i++) {
|
||||
ret= Xorriso__wait_chunk_md5(state, 10000, 0);
|
||||
if(ret <= 0)
|
||||
return(ret);
|
||||
state->chunk_state[state->chunk_w_idx]= 3;
|
||||
state->chunk_w_idx= (state->chunk_w_idx + 1) % state->num_chunks;
|
||||
}
|
||||
/* Wait for slave to end */
|
||||
ret= Xorriso__wait_slave_md5_end(state, 10000, 0);
|
||||
if(ret <= 0)
|
||||
return(ret);
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
/* @param flag bit0= this is a follow-up session (i.e. on CD: TAO)
|
||||
bit1= no pacifier messages
|
||||
bit2= compute stream MD5 and look out for checksum tag
|
||||
@ -2123,23 +2430,40 @@ int Xorriso_check_interval(struct XorrisO *xorriso, struct SpotlisT *spotlist,
|
||||
int start_lba= 0;
|
||||
struct burn_drive *drive;
|
||||
struct burn_drive_info *dinfo;
|
||||
char *data= NULL;
|
||||
char *data= NULL, *data_pt;
|
||||
off_t data_count, to_read, read_count= 0, write_amount;
|
||||
double pre_read_time, post_read_time, time_diff, total_time_diff= 0;
|
||||
double last_abort_file_time= 0;
|
||||
void *ctx= NULL, *cloned_ctx= NULL;
|
||||
char md5[16], tag_md5[16];
|
||||
uint32_t pos, range_start, range_size, next_tag= 0, lba, md5_spot_lba= 0;
|
||||
int md5_spot_value= Xorriso_read_quality_untesteD, chain_broken= 0;
|
||||
int tag_type= 0, valid, was_sb_tag= 0, in_track_gap= 0;
|
||||
char *comparison= "", *sev_text= "DEBUG", *tag_type_name= "";
|
||||
void *ctx= NULL;
|
||||
char md5[16];
|
||||
size_t data_size;
|
||||
struct xorriso_md5_state state;
|
||||
int num_chunks, async_md5;
|
||||
static off_t chunks_limit= 256 * 1024 * 1024;
|
||||
|
||||
memset(&state, 0, sizeof(state));
|
||||
state.chunk= NULL;
|
||||
state.chunk_state= NULL;
|
||||
state.chunk_fill= NULL;
|
||||
state.chunk_lba= NULL;
|
||||
state.spotlist= spotlist;
|
||||
|
||||
if(read_chunk > 1024)
|
||||
read_chunk= 1024;
|
||||
else if(read_chunk < 1)
|
||||
read_chunk= 1;
|
||||
Xorriso_alloc_meM(data, char, 2 * read_chunk * 1024);
|
||||
|
||||
num_chunks= job->async_chunks;
|
||||
if(((off_t) num_chunks) * ((off_t) read_chunk) > chunks_limit)
|
||||
num_chunks= chunks_limit / read_chunk;
|
||||
async_md5= (num_chunks >= 2);
|
||||
|
||||
if(async_md5)
|
||||
data_size= num_chunks * read_chunk * 2048;
|
||||
else
|
||||
data_size= read_chunk * 2048;
|
||||
Xorriso_alloc_meM(data, char, data_size);
|
||||
data_pt= data;
|
||||
|
||||
ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
|
||||
"on attempt to check media readability",
|
||||
@ -2171,6 +2495,50 @@ int Xorriso_check_interval(struct XorrisO *xorriso, struct SpotlisT *spotlist,
|
||||
}
|
||||
}
|
||||
|
||||
state.xorriso= xorriso;
|
||||
state.ctx= ctx;
|
||||
state.spotlist= spotlist;
|
||||
state.md5_start= md5_start;
|
||||
state.next_tag= 0;
|
||||
state.chain_broken= 0;
|
||||
state.in_track_gap= 0;
|
||||
state.was_sb_tag= 0;
|
||||
state.md5_spot_value= Xorriso_read_quality_untesteD;
|
||||
state.md5_spot_lba= 0;
|
||||
state.slave_state= 0;
|
||||
state.chunk_size= read_chunk;
|
||||
if(async_md5) {
|
||||
state.num_chunks= num_chunks;
|
||||
Xorriso_alloc_meM(state.chunk, char *, num_chunks);
|
||||
Xorriso_alloc_meM(state.chunk_state, int, num_chunks);
|
||||
Xorriso_alloc_meM(state.chunk_fill, int, num_chunks);
|
||||
Xorriso_alloc_meM(state.chunk_lba, uint32_t, num_chunks);
|
||||
for(i= 0; i < state.num_chunks; i++) {
|
||||
state.chunk[i]= data + read_chunk * i * 2048;
|
||||
state.chunk_state[i]= 0;
|
||||
state.chunk_fill[i]= 0;
|
||||
state.chunk_lba[i]= 0;
|
||||
}
|
||||
ret= pthread_mutex_init(&(state.spot_mutex), NULL);
|
||||
if(ret != 0) {
|
||||
sprintf(xorriso->info_text,
|
||||
"-check_media: Cannot initialize thread mutex");
|
||||
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
|
||||
goto ex;
|
||||
}
|
||||
} else
|
||||
state.num_chunks= 0;
|
||||
state.chunk_w_idx= 0;
|
||||
state.chunk_r_idx= 0;
|
||||
state.w_sleeps= 0;
|
||||
state.r_sleeps= 0;
|
||||
|
||||
if(async_md5) {
|
||||
ret= Xorriso_start_chunk_md5(xorriso, &state, 0);
|
||||
if(ret <= 0)
|
||||
goto ex;
|
||||
}
|
||||
|
||||
start_lba= from_lba;
|
||||
to_read= read_chunk;
|
||||
post_read_time= Sfile_microtime(0);
|
||||
@ -2195,12 +2563,12 @@ int Xorriso_check_interval(struct XorrisO *xorriso, struct SpotlisT *spotlist,
|
||||
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
|
||||
abort_check:;
|
||||
if(prev_quality >= 0) {
|
||||
ret= Spotlist_add_item(spotlist, start_lba, i + from_lba - start_lba,
|
||||
ret= Xorriso__add_spot(&state, start_lba, i + from_lba - start_lba,
|
||||
prev_quality, 0);
|
||||
if(ret <= 0)
|
||||
goto ex;
|
||||
}
|
||||
ret= Spotlist_add_item(spotlist, i + from_lba, block_count - i,
|
||||
ret= Xorriso__add_spot(&state, i + from_lba, block_count - i,
|
||||
Xorriso_read_quality_untesteD, 0);
|
||||
if(ret > 0)
|
||||
ret= 2;
|
||||
@ -2249,8 +2617,16 @@ abort_check:;
|
||||
} else {
|
||||
data_count= 0;
|
||||
pre_read_time= Sfile_microtime(0);
|
||||
ret= burn_read_data(drive, ((off_t) (i + from_lba)) * (off_t) 2048, data,
|
||||
to_read * (off_t) 2048, &data_count, 4 * !retry);
|
||||
|
||||
if(async_md5) {
|
||||
ret= Xorriso__wait_chunk_md5(&state, 1, 0);
|
||||
if(ret <= 0)
|
||||
goto ex;
|
||||
data_pt= state.chunk[state.chunk_w_idx];
|
||||
}
|
||||
|
||||
ret= burn_read_data(drive, ((off_t) (i + from_lba)) * (off_t) 2048,
|
||||
data_pt, to_read * (off_t) 2048, &data_count, 4 * !retry);
|
||||
post_read_time= Sfile_microtime(0);
|
||||
time_diff= post_read_time - pre_read_time;
|
||||
total_time_diff+= time_diff;
|
||||
@ -2260,12 +2636,12 @@ abort_check:;
|
||||
if(data_count / 2048 < to_read) {
|
||||
if(data_count > 0 && retry) {
|
||||
if(prev_quality >= 0) {
|
||||
ret= Spotlist_add_item(spotlist, start_lba,
|
||||
ret= Xorriso__add_spot(&state, start_lba,
|
||||
i + from_lba - start_lba, prev_quality, 0);
|
||||
if(ret <= 0)
|
||||
goto ex;
|
||||
}
|
||||
ret= Spotlist_add_item(spotlist, i + from_lba, data_count / 2048,
|
||||
ret= Xorriso__add_spot(&state, i + from_lba, data_count / 2048,
|
||||
Xorriso_read_quality_partiaL, 0);
|
||||
if(ret <= 0)
|
||||
goto ex;
|
||||
@ -2289,120 +2665,18 @@ abort_check:;
|
||||
|
||||
/* MD5 checksumming */
|
||||
if(ctx != NULL) {
|
||||
for(j= 0; j < to_read; j++) {
|
||||
lba= i + j + from_lba;
|
||||
if(lba < (uint32_t) md5_start)
|
||||
continue;
|
||||
ret= 0;
|
||||
if(lba > (uint32_t) (md5_start) + 16 &&
|
||||
(next_tag == 0 || chain_broken || lba == next_tag)) {
|
||||
ret= iso_util_decode_md5_tag(data + j * 2048, &tag_type,
|
||||
&pos, &range_start, &range_size,
|
||||
&next_tag, tag_md5, !!chain_broken);
|
||||
}
|
||||
valid= (ret == 1 || ret == (int) ISO_MD5_AREA_CORRUPTED) &&
|
||||
pos == lba;
|
||||
if(valid && tag_type == 2 && (lba < ((uint32_t) md5_start) + 32 ||
|
||||
in_track_gap)) {
|
||||
tag_type_name= "superblock";
|
||||
was_sb_tag= 1;
|
||||
if(in_track_gap && range_start != ((uint32_t) md5_start) &&
|
||||
range_start < lba && lba - range_start <= (uint32_t) j) {
|
||||
/* Looking for next session : start computing in hindsight.
|
||||
Session start and superblock tag are supposed to be in the
|
||||
same 64 kB chunk.
|
||||
*/
|
||||
iso_md5_end(&ctx, md5);
|
||||
ret= iso_md5_start(&ctx);
|
||||
if(ret < 0) {
|
||||
Xorriso_no_malloc_memory(xorriso, NULL, 0);
|
||||
ret= -1; goto ex;
|
||||
}
|
||||
iso_md5_compute(&ctx, data + (j - (lba - range_start)) * 2048,
|
||||
(lba - range_start) * 2048);
|
||||
md5_start= range_start;
|
||||
in_track_gap= 0;
|
||||
}
|
||||
} else if(valid && tag_type == 4 && lba < 32) {
|
||||
tag_type_name= "relocated 64kB superblock";
|
||||
}else if(valid && tag_type == 3 && was_sb_tag) {
|
||||
tag_type_name= "tree";
|
||||
}else if(valid && tag_type == 1) {
|
||||
if(async_md5) {
|
||||
state.chunk_fill[state.chunk_w_idx]= to_read;
|
||||
state.chunk_lba[state.chunk_w_idx]= i + from_lba;
|
||||
state.chunk_state[state.chunk_w_idx]= 1;
|
||||
/* The MD5 thread will call Xorriso_chunk_md5() */
|
||||
|
||||
/* >>> ??? allow this without superblock and tree tag ? */
|
||||
|
||||
tag_type_name= "session";
|
||||
} else {
|
||||
tag_type_name= "";
|
||||
}
|
||||
if (tag_type_name[0]) {
|
||||
if(range_start != (uint32_t) md5_start) {
|
||||
sprintf(xorriso->info_text,
|
||||
"Found MD5 %s tag which covers different data range",
|
||||
tag_type_name);
|
||||
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE",0);
|
||||
sprintf(xorriso->info_text,
|
||||
" Expected: %u Found: %u",
|
||||
(unsigned int) md5_start, range_start);
|
||||
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE",0);
|
||||
chain_broken= 1;
|
||||
valid= 0;
|
||||
} else {
|
||||
ret= iso_md5_clone(ctx, &cloned_ctx);
|
||||
if(ret <= 0) {
|
||||
Xorriso_no_malloc_memory(xorriso, NULL, 0);
|
||||
ret= -1; goto ex;
|
||||
}
|
||||
iso_md5_end(&cloned_ctx, md5);
|
||||
|
||||
if(ret == (int) ISO_MD5_AREA_CORRUPTED) {
|
||||
comparison= "CORRUPTED";
|
||||
sev_text= "WARNING";
|
||||
md5_spot_value= Xorriso_read_quality_md5_mismatcH;
|
||||
chain_broken= 1;
|
||||
} else if(! iso_md5_match(tag_md5, md5)) {
|
||||
comparison= "NON-MATCHING";
|
||||
sev_text= "WARNING";
|
||||
md5_spot_value= Xorriso_read_quality_md5_mismatcH;
|
||||
chain_broken= 1;
|
||||
} else {
|
||||
comparison= "matching";
|
||||
sev_text= "UPDATE";
|
||||
md5_spot_value= Xorriso_read_quality_md5_matcH;
|
||||
}
|
||||
md5_spot_lba= lba;
|
||||
sprintf(xorriso->info_text,
|
||||
"Found %s MD5 %s tag: start=%d size=%d",
|
||||
comparison, tag_type_name, md5_start, lba - md5_start);
|
||||
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0,
|
||||
sev_text, 0);
|
||||
}
|
||||
if(valid && (tag_type == 1 ||
|
||||
(tag_type == 4 && pos == lba && lba < 32))) {
|
||||
if(md5_spot_value != Xorriso_read_quality_untesteD) {
|
||||
ret= Spotlist_add_item(spotlist, md5_start,
|
||||
md5_spot_lba - md5_start, md5_spot_value, 0);
|
||||
if(ret <= 0)
|
||||
goto ex;
|
||||
}
|
||||
md5_spot_value= Xorriso_read_quality_untesteD;
|
||||
md5_start = lba + 1;
|
||||
if (md5_start % 32)
|
||||
md5_start= md5_start + (32 - (md5_start % 32));
|
||||
next_tag= 0;
|
||||
|
||||
iso_md5_end(&ctx, md5);
|
||||
ret= iso_md5_start(&ctx);
|
||||
if(ret < 0) {
|
||||
Xorriso_no_malloc_memory(xorriso, NULL, 0);
|
||||
ret= -1; goto ex;
|
||||
}
|
||||
if(tag_type == 1)
|
||||
in_track_gap= 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
iso_md5_compute(ctx, data + j * 2048, 2048);
|
||||
state.chunk_w_idx= (state.chunk_w_idx + 1) % state.num_chunks;
|
||||
} else {
|
||||
ret= Xorriso_chunk_md5(xorriso, data_pt, to_read,
|
||||
(uint32_t) (i + from_lba), &state, 0);
|
||||
if(ret <= 0)
|
||||
goto ex;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2426,7 +2700,7 @@ failed_to_write:;
|
||||
"FAILURE", 0);
|
||||
{ret= 0; goto ex;}
|
||||
}
|
||||
ret= write(job->data_to_fd, data, write_amount);
|
||||
ret= write(job->data_to_fd, data_pt, write_amount);
|
||||
if(ret == -1)
|
||||
goto failed_to_write;
|
||||
}
|
||||
@ -2434,8 +2708,8 @@ failed_to_write:;
|
||||
}
|
||||
if(quality != prev_quality) {
|
||||
if(prev_quality >= 0) {
|
||||
ret= Spotlist_add_item(spotlist, start_lba, i + from_lba - start_lba,
|
||||
prev_quality, 0);
|
||||
ret= Xorriso__add_spot(&state, start_lba,
|
||||
i + from_lba - start_lba, prev_quality, 0);
|
||||
if(ret <= 0)
|
||||
goto ex;
|
||||
}
|
||||
@ -2452,7 +2726,7 @@ failed_to_write:;
|
||||
}
|
||||
}
|
||||
if(prev_quality >= 0) {
|
||||
ret= Spotlist_add_item(spotlist, start_lba,
|
||||
ret= Xorriso__add_spot(&state, start_lba,
|
||||
block_count + from_lba - start_lba, prev_quality, 0);
|
||||
if(ret <= 0)
|
||||
goto ex;
|
||||
@ -2467,28 +2741,48 @@ failed_to_write:;
|
||||
|
||||
|
||||
/* MD5 checksumming : register result */
|
||||
if(async_md5) {
|
||||
ret= Xorriso__end_slave_md5(&state, 10000, 0);
|
||||
if(ret <= 0)
|
||||
goto ex;
|
||||
}
|
||||
|
||||
/* >>> ??? allow chain_broken to be a match ? */
|
||||
|
||||
if(next_tag > 0) {
|
||||
if(state.next_tag > 0) {
|
||||
sprintf(xorriso->info_text, "Missing announced MD5 tag: start=%d pos=%d",
|
||||
md5_start, next_tag);
|
||||
state.md5_start, state.next_tag);
|
||||
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
|
||||
md5_spot_value= Xorriso_read_quality_md5_mismatcH;
|
||||
md5_spot_lba= next_tag;
|
||||
state.md5_spot_value= Xorriso_read_quality_md5_mismatcH;
|
||||
state.md5_spot_lba= state.next_tag;
|
||||
}
|
||||
if(md5_spot_value != Xorriso_read_quality_untesteD) {
|
||||
ret= Spotlist_add_item(spotlist, md5_start, md5_spot_lba - md5_start,
|
||||
md5_spot_value, 0);
|
||||
if(state.md5_spot_value != Xorriso_read_quality_untesteD) {
|
||||
ret= Xorriso__add_spot(&state, state.md5_start,
|
||||
state.md5_spot_lba - state.md5_start, state.md5_spot_value, 0);
|
||||
if(ret <= 0)
|
||||
goto ex;
|
||||
}
|
||||
|
||||
ret= 1;
|
||||
ex:
|
||||
if(ctx != NULL)
|
||||
iso_md5_end(&ctx, md5);
|
||||
ex:;
|
||||
if(async_md5) {
|
||||
Xorriso__end_slave_md5(&state, 10000, 0);
|
||||
sprintf(xorriso->info_text,
|
||||
"async_chunks=%d , chunk_size=%d , w_sleeps: %.f , r_sleeps: %.f",
|
||||
state.num_chunks, read_chunk, (double) state.w_sleeps,
|
||||
(double) state.r_sleeps);
|
||||
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
|
||||
if(state.chunk != NULL)
|
||||
pthread_mutex_destroy(&(state.spot_mutex));
|
||||
Xorriso_free_meM(state.chunk);
|
||||
Xorriso_free_meM(state.chunk_state);
|
||||
Xorriso_free_meM(state.chunk_fill);
|
||||
Xorriso_free_meM(state.chunk_lba);
|
||||
}
|
||||
Xorriso_free_meM(data);
|
||||
if(state.ctx != NULL)
|
||||
iso_md5_end(&(state.ctx), md5);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
@ -2519,10 +2813,11 @@ int Xorriso_check_media(struct XorrisO *xorriso, struct SpotlisT **spotlist,
|
||||
if(ret<=0)
|
||||
goto ex;
|
||||
|
||||
/* >>> determine medium type dependent blocking factor:
|
||||
32 kB for CD (with 2kB retry) and DVD, 64 kB for BD
|
||||
eventually adjust read_chunk
|
||||
*/;
|
||||
ret = burn_disc_get_profile(drive, &profile_no, profile_name);
|
||||
if(ret <= 0)
|
||||
profile_no= 0;
|
||||
if(profile_no >= 0x40 && profile_no <= 0x43) /* BD-ROM, BD-R, BD-RE */
|
||||
read_chunk= 32;
|
||||
if(job->min_block_size != 0)
|
||||
read_chunk= job->min_block_size;
|
||||
|
||||
@ -2568,9 +2863,6 @@ int Xorriso_check_media(struct XorrisO *xorriso, struct SpotlisT **spotlist,
|
||||
ret= burn_get_read_capacity(drive, &read_capacity, 0);
|
||||
if(ret <= 0)
|
||||
read_capacity= -1;
|
||||
ret = burn_disc_get_profile(drive, &profile_no, profile_name);
|
||||
if(ret <= 0)
|
||||
profile_no= 0;
|
||||
|
||||
if(job->max_lba >= 0) {
|
||||
blocks= job->max_lba + 1 - start_lba;
|
||||
|
@ -9,7 +9,7 @@
|
||||
.\" First parameter, NAME, should be all caps
|
||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||
.\" other parameters are allowed: see man(7), man(1)
|
||||
.TH XORRISO 1 "Version 1.2.3, Apr 02, 2012"
|
||||
.TH XORRISO 1 "Version 1.2.3, Mai 01, 2012"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.\"
|
||||
.\" Some roff macros, for reference:
|
||||
@ -3549,7 +3549,7 @@ abort_file=/var/opt/xorriso/do_abort_check_media
|
||||
.br
|
||||
sector_map='' map_with_volid=off patch_lba0=off report=blocks
|
||||
.br
|
||||
bad_limit=valid slow_limit=1.0 chunk_size=0s
|
||||
bad_limit=valid slow_limit=1.0 chunk_size=0s async_chunks=0
|
||||
.br
|
||||
Option "reset=now" restores these startup defaults.
|
||||
.br
|
||||
@ -3657,6 +3657,11 @@ slow. This may be a fractional number like 0.1 or 1.5.
|
||||
\fBchunk_size=size\fR
|
||||
sets the number of bytes to be read in one read operation.
|
||||
This gets rounded down to full blocks of 2048 bytes. 0 means automatic size.
|
||||
.br
|
||||
\fBasync_chunks=number\fR
|
||||
enables asynchronous MD5 processing if number is 2 or larger.
|
||||
In this case the given number of read chunks is allocated as fifo buffer.
|
||||
On very fast MMC drives try: chunk_size=32s async_chunks=16.
|
||||
.TP
|
||||
\fB\-check_md5\fR severity iso_rr_path [***]
|
||||
Compare the data content of the given files in the loaded image with their
|
||||
|
@ -3128,7 +3128,7 @@ transmission errors.
|
||||
time_limit=28800 item_limit=100000 data_to=" event=ALL
|
||||
abort_file=/var/opt/xorriso/do_abort_check_media
|
||||
sector_map=" map_with_volid=off patch_lba0=off report=blocks
|
||||
bad_limit=valid slow_limit=1.0 chunk_size=0s
|
||||
bad_limit=valid slow_limit=1.0 chunk_size=0s async_chunks=0
|
||||
Option "reset=now" restores these startup defaults.
|
||||
Non-default options are:
|
||||
|
||||
@ -3224,6 +3224,11 @@ transmission errors.
|
||||
sets the number of bytes to be read in one read operation.
|
||||
This gets rounded down to full blocks of 2048 bytes. 0 means
|
||||
automatic size.
|
||||
async_chunks=number
|
||||
enables asynchronous MD5 processing if number is 2 or larger.
|
||||
In this case the given number of read chunks is allocated as
|
||||
fifo buffer. On very fast MMC drives try: chunk_size=32s
|
||||
async_chunks=16.
|
||||
|
||||
-check_md5 severity iso_rr_path [***]
|
||||
Compare the data content of the given files in the loaded image
|
||||
@ -4381,8 +4386,8 @@ File: xorriso.info, Node: CommandIdx, Next: ConceptIdx, Prev: Legal, Up: Top
|
||||
* -cdx sets working directory on disk: Navigate. (line 16)
|
||||
* -changes_pending overrides change status: Writing. (line 13)
|
||||
* -charset sets input/output character set: Charset. (line 43)
|
||||
* -check_md5 verifies file checksum: Verify. (line 148)
|
||||
* -check_md5_r verifies file tree checksums: Verify. (line 164)
|
||||
* -check_md5 verifies file checksum: Verify. (line 153)
|
||||
* -check_md5_r verifies file tree checksums: Verify. (line 169)
|
||||
* -check_media reads media block by block: Verify. (line 21)
|
||||
* -check_media_defaults sets -check_media options: Verify. (line 41)
|
||||
* -chgrp sets group in ISO image: Manip. (line 50)
|
||||
@ -4813,8 +4818,8 @@ File: xorriso.info, Node: ConceptIdx, Prev: CommandIdx, Up: Top
|
||||
* Verify, compare ISO and disk file, -compare: Navigate. (line 146)
|
||||
* Verify, compare ISO and disk tree, -compare_r: Navigate. (line 159)
|
||||
* Verify, compare ISO and disk, -compare_l: Navigate. (line 164)
|
||||
* Verify, file checksum, -check_md5: Verify. (line 148)
|
||||
* Verify, file tree checksums, -check_md5_r: Verify. (line 164)
|
||||
* Verify, file checksum, -check_md5: Verify. (line 153)
|
||||
* Verify, file tree checksums, -check_md5_r: Verify. (line 169)
|
||||
* Verify, preset -check_media, -check_media_defaults: Verify. (line 41)
|
||||
* Write, block size, -dvd_obs: SetWrite. (line 265)
|
||||
* Write, bootability, -boot_image: Bootable. (line 26)
|
||||
@ -4871,32 +4876,32 @@ Node: DialogCtl139832
|
||||
Node: Inquiry142429
|
||||
Node: Navigate147295
|
||||
Node: Verify155556
|
||||
Node: Restore164245
|
||||
Node: Emulation171154
|
||||
Node: Scripting180965
|
||||
Node: Frontend188125
|
||||
Node: Examples189425
|
||||
Node: ExDevices190602
|
||||
Node: ExCreate191261
|
||||
Node: ExDialog192546
|
||||
Node: ExGrowing193811
|
||||
Node: ExModifying194616
|
||||
Node: ExBootable195120
|
||||
Node: ExCharset195672
|
||||
Node: ExPseudo196493
|
||||
Node: ExCdrecord197391
|
||||
Node: ExMkisofs197708
|
||||
Node: ExGrowisofs199048
|
||||
Node: ExException200183
|
||||
Node: ExTime200637
|
||||
Node: ExIncBackup201096
|
||||
Node: ExRestore205087
|
||||
Node: ExRecovery206047
|
||||
Node: Files206617
|
||||
Node: Seealso207916
|
||||
Node: Bugreport208639
|
||||
Node: Legal209220
|
||||
Node: CommandIdx210150
|
||||
Node: ConceptIdx225738
|
||||
Node: Restore164522
|
||||
Node: Emulation171431
|
||||
Node: Scripting181242
|
||||
Node: Frontend188402
|
||||
Node: Examples189702
|
||||
Node: ExDevices190879
|
||||
Node: ExCreate191538
|
||||
Node: ExDialog192823
|
||||
Node: ExGrowing194088
|
||||
Node: ExModifying194893
|
||||
Node: ExBootable195397
|
||||
Node: ExCharset195949
|
||||
Node: ExPseudo196770
|
||||
Node: ExCdrecord197668
|
||||
Node: ExMkisofs197985
|
||||
Node: ExGrowisofs199325
|
||||
Node: ExException200460
|
||||
Node: ExTime200914
|
||||
Node: ExIncBackup201373
|
||||
Node: ExRestore205364
|
||||
Node: ExRecovery206324
|
||||
Node: Files206894
|
||||
Node: Seealso208193
|
||||
Node: Bugreport208916
|
||||
Node: Legal209497
|
||||
Node: CommandIdx210427
|
||||
Node: ConceptIdx226015
|
||||
|
||||
End Tag Table
|
||||
|
@ -50,7 +50,7 @@
|
||||
@c man .\" First parameter, NAME, should be all caps
|
||||
@c man .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||
@c man .\" other parameters are allowed: see man(7), man(1)
|
||||
@c man .TH XORRISO 1 "Version 1.2.3, Apr 02, 2012"
|
||||
@c man .TH XORRISO 1 "Version 1.2.3, Mai 01, 2012"
|
||||
@c man .\" Please adjust this date whenever revising the manpage.
|
||||
@c man .\"
|
||||
@c man .\" Some roff macros, for reference:
|
||||
@ -4199,7 +4199,7 @@ abort_file=/var/opt/xorriso/do_abort_check_media
|
||||
@*
|
||||
sector_map='' map_with_volid=off patch_lba0=off report=blocks
|
||||
@*
|
||||
bad_limit=valid slow_limit=1.0 chunk_size=0s
|
||||
bad_limit=valid slow_limit=1.0 chunk_size=0s async_chunks=0
|
||||
@*
|
||||
Option "reset=now" restores these startup defaults.
|
||||
@*
|
||||
@ -4309,6 +4309,11 @@ slow. This may be a fractional number like 0.1 or 1.5.
|
||||
@item chunk_size=size
|
||||
sets the number of bytes to be read in one read operation.
|
||||
This gets rounded down to full blocks of 2048 bytes. 0 means automatic size.
|
||||
@*
|
||||
@item async_chunks=number
|
||||
enables asynchronous MD5 processing if number is 2 or larger.
|
||||
In this case the given number of read chunks is allocated as fifo buffer.
|
||||
On very fast MMC drives try: chunk_size=32s async_chunks=16.
|
||||
@end table
|
||||
@c man .TP
|
||||
@kindex -check_md5 verifies file checksum
|
||||
|
@ -1 +1 @@
|
||||
#define Xorriso_timestamP "2012.04.28.161532"
|
||||
#define Xorriso_timestamP "2012.05.01.075022"
|
||||
|
Loading…
Reference in New Issue
Block a user