Adapted media evaluation to CD peculiarities

This commit is contained in:
2008-08-11 20:17:09 +00:00
parent ff8bfdaf4c
commit d7cea7d8f1
5 changed files with 633 additions and 39 deletions

View File

@ -6557,18 +6557,21 @@ int Xorriso_msinfo(struct XorrisO *xorriso, int *msc1, int *msc2, int flag)
return(1);
}
/* @return <=0 error, 1= done, 2= aborted due to limit
*/
int Xorriso_check_interval(struct XorrisO *xorriso, struct SpotlisT *spotlist,
struct CheckmediajoB *job,
int from_lba, int block_count,
int read_chunk, int min_block_size, int flag)
{
int i, ret, total_count= 0;
int prev_quality= -1, quality= -1;
int i, j, ret, total_count= 0, sectors= -1, sector_size= -1, skip_reading;
int prev_quality= -1, quality= -1, retry= 0, profile_no, is_cd;
int start_sec, end_sec, first_value;
char profile_name[80];
int start_lba= 0;
struct burn_drive *drive;
struct burn_drive_info *dinfo;
char data[64*1024];
char data[64*1024], sfe[5*SfileadrL];
off_t data_count, to_read;
double pre_read_time, post_read_time, time_diff, total_time_diff= 0;
@ -6576,9 +6579,25 @@ int Xorriso_check_interval(struct XorrisO *xorriso, struct SpotlisT *spotlist,
"on attempt to check media readability", 0);
if(ret<=0)
goto ex;
ret= burn_disc_get_profile(drive, &profile_no, profile_name);
if(ret > 0)
if(profile_no >= 0x08 && profile_no <= 0x0a)
is_cd= 1;
if(job->sector_map != NULL) {
Sectorbitmap_get_layout(job->sector_map, &sectors, &sector_size, 0);
sector_size/= 2048;
}
if(job->retry > 0)
retry= 1;
else if(job-retry == 0 && is_cd)
retry= 1;
start_lba= from_lba;
for(i= 0; i < block_count; i+= read_chunk) {
to_read= read_chunk;
for(i= 0; i < block_count; i+= to_read) {
skip_reading= 0;
if(job->item_limit > 0 &&
Spotlist_count(spotlist, 0) + 2 >= job->item_limit) {
sprintf(xorriso->info_text, "-check_media: Reached item_limit=%d",
@ -6599,7 +6618,7 @@ abort_check:;
if(ret <= 0)
goto ex;
}
ret= Spotlist_add_item(spotlist, i + from_lba, block_count - 1,
ret= Spotlist_add_item(spotlist, i + from_lba, block_count - i,
Xorriso_read_quality_untesteD, 0);
if(ret > 0)
ret= 2;
@ -6608,27 +6627,103 @@ abort_check:;
to_read= read_chunk;
if(i + to_read > block_count)
to_read= block_count - i;
ret= burn_read_data(drive, ((off_t) (i + from_lba)) * (off_t) 2048, data,
to_read * (off_t) 2048, &data_count, 4);
post_read_time= Sfile_microtime(0);
time_diff= post_read_time - pre_read_time;
total_time_diff+= time_diff;
total_count++;
if(ret <= 0) {
Xorriso_process_msg_queues(xorriso,0);
quality= Xorriso_read_quality_unreadablE;
if(read_chunk > min_block_size) {
if(is_cd && i + to_read + 2 >= block_count) {
/* Read last 2 blocks of CD track separately, because with TAO tracks
they are always unreadable but with SAO tracks they contain data.
*/
if(to_read > 2)
to_read-= 2;
else if(to_read > 1)
to_read--;
}
/* >>> evaluate min blocks */;
#ifdef NIX
/* >>> this is not yet suitable for min_block_size */
#endif
if(sector_size == read_chunk && from_lba % read_chunk == 0) {
if(Sectorbitmap_is_set(job->sector_map, (i + from_lba) / read_chunk, 0)) {
quality= Xorriso_read_quality_valiD;
skip_reading= 1;
}
} else if(sector_size > 0) {
start_sec= (i + from_lba) / sector_size;
end_sec= (i + to_read + from_lba) / sector_size;
first_value= Sectorbitmap_is_set(job->sector_map, start_sec, 0);
for(j= start_sec; j < end_sec; j++)
if(Sectorbitmap_is_set(job->sector_map, j, 0) != first_value)
break;
to_read= j * sector_size - i - from_lba;
skip_reading= !!first_value;
if(skip_reading)
quality= Xorriso_read_quality_valiD;
}
if(skip_reading) {
pre_read_time= post_read_time= Sfile_microtime(0);
} else {
quality= Xorriso_read_quality_gooD;
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);
post_read_time= Sfile_microtime(0);
time_diff= post_read_time - pre_read_time;
total_time_diff+= time_diff;
total_count++;
if(ret <= 0) {
Xorriso_process_msg_queues(xorriso,0);
/* >>> find better threshold than 1.0 */
if(data_count > 0 && retry) {
if(prev_quality >= 0) {
ret= Spotlist_add_item(spotlist, 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,
Xorriso_read_quality_partiaL, 0);
if(ret <= 0)
goto ex;
start_lba= i + from_lba + data_count / 2048;
prev_quality= Xorriso_read_quality_unreadablE;
}
quality= Xorriso_read_quality_unreadablE;
if(time_diff > 1.0 && i > 0)
quality= Xorriso_read_quality_sloW;
#ifdef NIX
if(read_chunk > min_block_size) {
/* >>> evaluate min blocks */;
}
#endif
} else {
quality= Xorriso_read_quality_gooD;
/* >>> find better threshold than 1.0 */
if(time_diff > 1.0 && i > 0)
quality= Xorriso_read_quality_sloW;
}
if(data_count > 0) {
if(job->data_to_fd >= 0) {
ret= lseek(job->data_to_fd, ((off_t) (i + from_lba)) * (off_t) 2048,
SEEK_SET);
if(ret == -1) {
failed_to_write:;
sprintf(xorriso->info_text, "Cannot write %d bytes to lba %d of %s",
(int) data_count, i + from_lba,
Text_shellsafe(job->data_to_path, sfe, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno,
"FAILURE", 0);
{ret= 0; goto ex;}
}
ret= write(job->data_to_fd, data, data_count);
if(ret == -1)
goto failed_to_write;
}
}
}
if(quality != prev_quality) {
if(prev_quality >= 0) {
@ -6669,10 +6764,17 @@ int Xorriso_check_media(struct XorrisO *xorriso, struct SpotlisT **spotlist,
struct CheckmediajoB *job, int flag)
{
int media_blocks= 0, read_chunk= 16, ret, mode, min_block_size, start_lba= 0;
int blocks;
int blocks, os_errno, i, j, last_track_end= -1, track_blocks, track_lba;
int num_sessions, num_tracks, declare_untested= 0, sector_size, count;
int lba, quality;
char sfe[5*SfileadrL];
struct burn_drive *drive;
struct burn_drive_info *dinfo;
struct isoburn_toc_disc *isoburn_disc= NULL;
struct isoburn_toc_session **isoburn_sessions;
struct isoburn_toc_track **iso_burn_tracks;
struct burn_toc_entry isoburn_entry;
struct stat stbuf;
*spotlist= NULL;
@ -6692,6 +6794,30 @@ int Xorriso_check_media(struct XorrisO *xorriso, struct SpotlisT **spotlist,
if(ret <= 0)
{ret= -1; goto ex;}
if(job->sector_map_path[0]) {
Sectorbitmap_destroy(&(job->sector_map), 0);
if(stat(job->sector_map_path, &stbuf) != -1) {
ret= Sectorbitmap_from_file(&(job->sector_map), job->sector_map_path,
xorriso->info_text, &os_errno, 0);
if(ret <= 0) {
if(xorriso->info_text[0])
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, os_errno,
"FAILURE", 0);
goto ex;
}
}
}
if(job->data_to_path[0]) {
job->data_to_fd= open(job->data_to_path, O_WRONLY | O_CREAT,
S_IRUSR | S_IWUSR);
if(job->data_to_fd == -1) {
sprintf(xorriso->info_text, "Cannot open path %s",
Text_shellsafe(job->data_to_path, sfe, 0));
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
{ret= 0; goto ex;}
}
}
Xorriso_pacifier_reset(xorriso, 0);
job->start_time= time(NULL);
mode= job->mode;
@ -6705,11 +6831,55 @@ int Xorriso_check_media(struct XorrisO *xorriso, struct SpotlisT **spotlist,
if(ret <= 0)
goto ex;
} else if(mode == 0) {
} else if(mode == 0) { /* track by track */
isoburn_disc= isoburn_toc_drive_get_disc(drive);
if(isoburn_disc == NULL)
goto no_content_visible;
isoburn_sessions=
isoburn_toc_disc_get_sessions(isoburn_disc, &num_sessions);
for(i= 0; i < num_sessions; i++) {
iso_burn_tracks= isoburn_toc_session_get_tracks(isoburn_sessions[i],
&num_tracks);
for(j= 0; j < num_tracks; j++) {
isoburn_toc_track_get_entry(iso_burn_tracks[j], &isoburn_entry);
if(!(isoburn_entry.extensions_valid & 1)) /* should not happen */
continue;
track_lba= isoburn_entry.start_lba;
track_blocks= isoburn_entry.track_blocks;
if(last_track_end >= 0 && last_track_end < track_lba &&
last_track_end >= start_lba) {
ret= Spotlist_add_item(*spotlist, last_track_end,
track_lba - last_track_end,
Xorriso_read_quality_off_tracK, 0);
if(ret <= 0)
goto ex;
}
last_track_end= track_lba + track_blocks;
/* >>> track by track */;
if(track_lba < start_lba) {
track_blocks-= start_lba - track_lba;
track_lba= start_lba;
}
if(track_blocks <= 0)
continue;
if(declare_untested) {
ret= Spotlist_add_item(*spotlist, track_lba, track_blocks,
Xorriso_read_quality_untesteD, 0);
if(ret <= 0)
goto ex;
} else {
ret= Xorriso_check_interval(xorriso, *spotlist, job,
track_lba, track_blocks,
read_chunk, min_block_size, 0);
if(ret <= 0)
goto ex;
if(ret == 2)
declare_untested= 1;
}
}
}
} else if(mode == 1) {
} else if(mode == 1) { /* isoburn disc capacity */
isoburn_disc= isoburn_toc_drive_get_disc(drive);
if(isoburn_disc == NULL) {
no_content_visible:;
@ -6738,6 +6908,32 @@ no_content_visible:;
xorriso->pacifier_count, xorriso->pacifier_total, "", 1);
ret= 1;
ex:;
if(job->data_to_fd != -1)
close(job->data_to_fd);
if(ret > 0 && job->sector_map_path[0]) {
sector_size= read_chunk * 2048;
count= Spotlist_count(*spotlist, 0);
for(i= 0; i < count; i++) {
ret= Spotlist_get_item(*spotlist, i, &lba, &blocks, &quality, 0);
if(ret <= 0)
continue;
if(lba % read_chunk) {
sector_size= 2048;
break;
}
}
ret= Xorriso_spotlist_to_sectormap(xorriso, *spotlist, sector_size,
&(job->sector_map), 0);
if(ret > 0) {
ret= Sectorbitmap_to_file(job->sector_map, job->sector_map_path,
xorriso->info_text, &os_errno, 0);
if(ret <= 0) {
if(xorriso->info_text[0])
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, os_errno,
"FAILURE", 0);
}
}
}
if(ret < 0)
Spotlist_destroy(spotlist, 0);
return(ret);