New option -check_media

This commit is contained in:
Thomas Schmitt 2008-08-14 22:15:35 +00:00
parent 8ab1fcd4f5
commit b5d7d75598
7 changed files with 204 additions and 80 deletions

View File

@ -2,7 +2,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 "Jul, 17, 2008"
.TH XORRISO 1 "Aug 14, 2008"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
@ -147,11 +147,11 @@ useful to store intermediate states and to continue with image manipulations.
.B Media types and states:
There are two families of media in the MMC standard:
.br
\fBMulti-session\fR media are CD-R, CD-RW, DVD-R, DVD+R, DVD+R/DL, and
\fBMulti-session media\fR are CD-R, CD-RW, DVD-R, DVD+R, DVD+R/DL, and
unformatted DVD-RW. These media provide a table of content which
describes their existing sessions. See option \fB-toc\fR.
.br
\fBOverwriteable\fR media are DVD-RAM, DVD+RW, BD-RE, and formatted DVD-RW.
\fBOverwriteable media\fR are DVD-RAM, DVD+RW, BD-RE, and formatted DVD-RW.
They allow random write access but do not provide information about their
session history. If they contain one or more ISO 9660 sessions and if the
first session was written by xorriso, then a table of content can
@ -210,7 +210,7 @@ blank state if it was not blank already.
.PP
If there is a input drive with a valid ISO image, then this image gets loaded
as foundation for manipulations and extension. The constellation of input
and output drive determines which of two write methods will be used.
and output drive determines which write method will be used.
They have quite different capabilities and constraints.
.PP
The method of \fBgrowing\fR adds new data to the existing media. These
@ -551,11 +551,8 @@ If other file types collide then the setting of command
decides.
.br
Renaming of files has similar collision handling, but directories can only
be replaced, not merged. Directories can hardly collide on renaming because
of the shell-like behavior of -mv: if a file object hits an existing directory
then it gets inserted rather than trying to replace that directory.
Nevertheless, the overwriting rules apply if an operation of xorriso
ever attempts to do such a replacement.
be replaced, not merged. Note that -mv inserts the source objects into an
eventual existing target directory rather than attempting to replace it.
.PP
The commands in this section alter the ISO image and not the local filesystem.
.TP
@ -1645,9 +1642,78 @@ addresses get compared whether they have counterparts below the other address
and whether both counterparts match.
.TP
\fB\-compare_l\fR disk_prefix iso_rr_prefix disk_path [***]
Performs -compare_r with each of the disk_path arguments. iso_rr_path will be
Perform -compare_r with each of the disk_path arguments. iso_rr_path will be
composed from disk_path by replacing disk_prefix by iso_rr_prefix.
.TP
.B Evaluation of readability and recovery:
.PP
It is not uncommon that optical media produce read errors. The reasons may be
various and get obscured by error correction which is performed by the drives
and based on extra data on the media. If a drive returns data then one can
quite trust that they are valid. But at some degree of read problems the
correction will fail and the drive is supposed to indicate error.
.br
xorriso can scan the media for readable data blocks, classify them according
to their read speed, save them to a file, and keep track of successfuly saved
blocks for further tries on the same media.
.TP
\fB\-check_media\fR [option [option ...]] --
Try to read data blocks from the indev drive and finally report about the
encountered quality. Several options may be used to modify the default
behavior.
.br
An option consists of a keyword, a "=" character, and a value.
.br
Default is:
.br
use=indev what=tracks min_lba=-1 max_lba=-1 retry=default
time_limit=-1 item_limit=-1
.br
abort_file=/var/opt/xorriso/do_abort_check_media
.br
data_to= sector_map= map_with_volid=off
.br
Non-default settings:
.br
"use=outdev" reads from the output drive instead of the input drive. This
avoids reading of the ISO image tree from media.
.br
"what=disc" scans the payload range of a media without respecting track gaps.
.br
"min_lba=" omits all blocks with addresses lower than the option value.
.br
"max_lba=" switches to what=disc and omits all blocks above its option value.
.br
"retry=on" forces read retries with single blocks when the normal block
chunk produces a read error. By default, retries are only enabled with CD
media. "retry=off" forbits retries for all media types.
.br
"abort_file=" gives the path of the file which may abort a scan run. Abort
happens if the file exists and its mtime is not older than the start time
of the run. Use shell command "touch" to trigger this.
Other than an aborted program run, this will report the tested and untested
blocks and go on with running xorriso.
.br
"time_limit=" gives the number of seconds after which the scan shall be
aborted. This is useful for unattended scanning of media which may else
overwork the drive in its effort to squeeze out some readable blocks.
Abort may be delayed by the drive gnawing on the last single read operation.
.br
"item_limit=" gives the number of report list items after which to abort.
.br
"data_to=" copies the valid blocks to the file which is given as option value.
.br
"sector_map=" tries to read the file given by option value as
"xorriso sector bitmap" and to store such a map file after the scan run.
The bitmap tells which blocks have been read successfully in previous runs.
It allows to do several scans on the same media, eventually with intermediate
eject, in order to collect readable blocks whenever the drive is lucky enough
to produce them. The stored file also contains a human readable TOC of tracks
and their start block addresses.
.br
"map_with_volid=on" examines tracks whether they are ISO images and eventually
prints their volume ids into the human readable TOC of sector_map=.
.TP
.B osirrox restore options:
.PP
Normally xorriso only writes to disk files which were given as stdio:
@ -2341,6 +2407,12 @@ to read and execute lines from the following files:
.br
The files are read in the sequence given above, but none of them is required
for xorriso to function properly.
.TP
.B Runtime control files:
.br
The default setting of -check_media abort_file= is:
.br
/var/opt/xorriso/do_abort_check_media
.br
.SH SEE ALSO
.TP

View File

@ -1720,6 +1720,8 @@ int Xorriso_lst_destroy_all(struct Xorriso_lsT **lstring, int flag)
{
struct Xorriso_lsT *s,*next;
if(lstring==NULL)
return(-1);
if((*lstring)==NULL)
return(0);
for(s= *lstring; s->prev!=NULL; s= s->prev);
@ -2734,6 +2736,7 @@ int Spotlist_add_item(struct SpotlisT *o, int start_lba, int blocks,
{
int ret;
struct SpotlistiteM *li;
static int debug_verbous= 0;
ret= Spotlistitem_new(&li, start_lba, blocks, quality, 0);
if(ret <= 0)
@ -2745,11 +2748,10 @@ int Spotlist_add_item(struct SpotlisT *o, int start_lba, int blocks,
o->list_start= li;
(o->list_count)++;
/* <<< */
{char quality_name[80];
fprintf(stderr, "debug: lba %10d , size %10d , quality %s\n",
start_lba, blocks, Spotlist__quality_name(quality, quality_name, 0));
}
if(debug_verbous) {char quality_name[80];
fprintf(stderr, "debug: lba %10d , size %10d , quality %s\n",
start_lba, blocks, Spotlist__quality_name(quality, quality_name, 0));
}
return(1);
}
@ -2799,6 +2801,8 @@ char *Spotlist__quality_name(int quality, char name[80], int flag)
strcpy(name, "valid");
else if(quality == Xorriso_read_quality_invaliD)
strcpy(name, "invalid");
else if(quality == Xorriso_read_quality_tao_enD)
strcpy(name, "tao end");
else if(quality == Xorriso_read_quality_off_tracK)
strcpy(name, "off track");
else if(quality == Xorriso_read_quality_untesteD)
@ -2806,7 +2810,7 @@ char *Spotlist__quality_name(int quality, char name[80], int flag)
else if(quality == Xorriso_read_quality_unreadablE)
strcpy(name, "unreadable");
else
sprintf(name, "0x%8.8X\n", (unsigned) quality);
sprintf(name, "0x%8.8X", (unsigned) quality);
return(name);
}
@ -3114,6 +3118,7 @@ int Checkmediajob_new(struct CheckmediajoB **o, int flag)
if(m==NULL)
return(-1);
*o= m;
m->use_outdev= 0;
m->min_lba= -1;
m->max_lba= -1;
m->min_block_size= 16;
@ -3121,6 +3126,7 @@ int Checkmediajob_new(struct CheckmediajoB **o, int flag)
m->start_time= time(NULL);
m->time_limit= -1;
m->item_limit= -1;
strcpy(m->abort_file_path, "/var/opt/xorriso/do_abort_check_media");
m->data_to_path[0]= 0;
m->data_to_fd= -1;
m->sector_map_path[0]= 0;
@ -8779,6 +8785,8 @@ int Xorriso_spotlist_to_sectormap(struct XorrisO *xorriso,
for(i= 0; i < count; i++) {
ret= Spotlist_get_item(spotlist, i, &lba, &blocks, &quality, 0);
if(ret <= 0)
continue;
if(quality == Xorriso_read_quality_untesteD)
continue;
Sectorbitmap_set_range(m, lba / sector_blocks, blocks / sector_blocks,
quality >= Xorriso_read_quality_valiD);
@ -9385,7 +9393,11 @@ int Xorriso_option_check_media(struct XorrisO *xorriso,
goto ex;
for(i= old_idx; i < end_idx; i++) {
if(strncmp(argv[i], "data_to=", 8) == 0) {
if(strncmp(argv[i], "abort_file=", 11) == 0) {
ret= Sfile_str(job->abort_file_path, argv[i] + 11, 0);
if(ret <= 0)
goto ex;
} else if(strncmp(argv[i], "data_to=", 8) == 0) {
ret= Sfile_str(job->data_to_path, argv[i] + 8, 0);
if(ret <= 0)
goto ex;
@ -9429,6 +9441,13 @@ int Xorriso_option_check_media(struct XorrisO *xorriso,
job->time_limit= num;
else
job->item_limit= num;
} else if(strncmp(argv[i], "use=", 4) == 0) {
if(strcmp(argv[i] + 4, "outdev") == 0)
job->use_outdev= 1;
else if(strcmp(argv[i] + 4, "indev") == 0)
job->use_outdev= 0;
else
goto unknown_value;
} else if(strncmp(argv[i], "what=", 5) == 0) {
if(strcmp(argv[i]+5, "tracks") == 0)
job->mode= 0;
@ -9447,7 +9466,6 @@ unknown_value:;
ret= 0; goto ex;
}
}
ret= Xorriso_check_media(xorriso, &spotlist, job, 0);
if(ret <= 0)
goto ex;
@ -10974,8 +10992,9 @@ int Xorriso_option_help(struct XorrisO *xorriso, int flag)
" -check_media [options] --",
" Try to read data blocks from media and report about the",
" outcome. Several options modify the behavior:",
" what=track|session , min_lba=blockadr , max_lba=blockadr ,",
" time_limit=seconds , item_limit=number ,",
" use=indev|outdev , what=track|session ,",
" min_lba=blockadr , max_lba=blockadr ,",
" abort_file=path , time_limit=seconds , item_limit=number ,",
" retry=on|off|default , data_to=filepath ,",
" sector_map=filepath , map_with_volid=on|off",
"",

View File

@ -154,6 +154,7 @@ int Xorriso_process_msg_queues(struct XorrisO *xorriso, int flag);
their normal channels into a pair of string lists which can at some
later time be retrieved by the application.
These redirection caches can be stacked to allow stacked applications.
xorriso itself uses them for internal purposes.
*/
/* A list item able of forming double chained lists */
@ -180,7 +181,8 @@ int Xorriso_push_outlists(struct XorrisO *xorriso, int *stack_handle,
/** Disable the redirection given by stack_handle. If it was the current
receiver of messages then switch output to the next older redirection.
receiver of messages then switch output to the next older redirection
resp. to the normal channels if no redirections are stacked any more.
The messages collected by the disabled redirection are handed out as
two lists. Both lists have to be disposed via Xorriso_lst_destroy_all()
when they are no longer needed.
@ -201,7 +203,7 @@ int Xorriso_pull_outlists(struct XorrisO *xorriso, int stack_handle,
/** Obtain the text message from the current list item.
@param entry The current list item
@param flag unused yet, submit 0
@return pointer to the text content of the list item.
@return Pointer to the text content of the list item.
This pointer does not have to be freed.
*/
char *Xorriso_lst_get_text(struct Xorriso_lsT *entry, int flag);
@ -213,7 +215,7 @@ char *Xorriso_lst_get_text(struct Xorriso_lsT *entry, int flag);
NULL.
@param entry The current list item
@param flag unused yet, submit 0
@return pointer to the next list item or NULL if end of list
@return Pointer to the next list item or NULL if end of list.
This pointer does not have to be freed.
*/
struct Xorriso_lsT *Xorriso_lst_get_next(struct Xorriso_lsT *entry, int flag);
@ -222,7 +224,7 @@ struct Xorriso_lsT *Xorriso_lst_get_next(struct Xorriso_lsT *entry, int flag);
/** Obtain the address of the previous item in the chain of messages.
@param entry The current list item
@param flag unused yet, submit 0
@return pointer to the previous list item or NULL if start of list
@return Pointer to the previous list item or NULL if start of list.
This pointer does not have to be freed.
*/
struct Xorriso_lsT *Xorriso_lst_get_prev(struct Xorriso_lsT *entry, int flag);
@ -232,9 +234,12 @@ struct Xorriso_lsT *Xorriso_lst_get_prev(struct Xorriso_lsT *entry, int flag);
the given link item.
Apply this to each of the two list handles obtained by
Xorriso_pull_outlists() when the lists are no longer needed.
@param lstring pointer to the pointer to be freed and set to NULL
@param lstring *lstring will be freed and set to NULL.
It is not dangerous to submit a pointer to a NULL-pointer.
@param flag unused yet, submit 0
@return 0= *lstring was alredy NULL, 1= ok
@return -1= lstring was NULL (i.e. wrong use of this call),
0= *lstring was already NULL,
1= item actually disposed
*/
int Xorriso_lst_destroy_all(struct Xorriso_lsT **lstring, int flag);
@ -293,6 +298,10 @@ int Xorriso_option_cdi(struct XorrisO *xorriso, char *iso_rr_path, int flag);
/* Option -cdx */
int Xorriso_option_cdx(struct XorrisO *xorriso, char *disk_path, int flag);
/* Option -check_media */
int Xorriso_option_check_media(struct XorrisO *xorriso,
int argc, char **argv, int *idx, int flag);
/* Option -chgrp alias -chgrpi , chgrp_r alias chgrpi */
/* @param flag bit0=recursive (-chgrp_r)
*/

View File

@ -677,9 +677,10 @@ char *Spotlist__quality_name(int quality, char name[80], int flag);
#define Xorriso_read_quality_sloW 0x60000000
#define Xorriso_read_quality_partiaL 0x50000000
#define Xorriso_read_quality_valiD 0x40000000
#define Xorriso_read_quality_invaliD 0x3fffffff
#define Xorriso_read_quality_untesteD 0x3fffffff
#define Xorriso_read_quality_invaliD 0x3ffffffe
#define Xorriso_read_quality_tao_enD 0x28000000
#define Xorriso_read_quality_off_tracK 0x20000000
#define Xorriso_read_quality_untesteD 0x10000000
#define Xorriso_read_quality_unreadablE 0x00000000

View File

@ -1 +1 @@
#define Xorriso_timestamP "2008.08.14.220520"
#define Xorriso_timestamP "2008.08.14.221412"

View File

@ -6569,16 +6569,17 @@ int Xorriso_msinfo(struct XorrisO *xorriso, int *msc1, int *msc2, int flag)
return(1);
}
/* @return <=0 error, 1= done, 2= aborted due to limit
/* @param flag bit0= this is a follow-up session (i.e. on CD: TAO)
@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 from_lba, int block_count, int read_chunk,
int flag)
{
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;
int start_sec, end_sec, first_value, fret;
char profile_name[80];
int start_lba= 0;
struct burn_drive *drive;
@ -6586,9 +6587,12 @@ int Xorriso_check_interval(struct XorrisO *xorriso, struct SpotlisT *spotlist,
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;
double last_abort_file_time= 0;
struct stat stbuf;
ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
"on attempt to check media readability", 0);
"on attempt to check media readability",
!!job->use_outdev);
if(ret<=0)
goto ex;
ret= burn_disc_get_profile(drive, &profile_no, profile_name);
@ -6603,13 +6607,29 @@ int Xorriso_check_interval(struct XorrisO *xorriso, struct SpotlisT *spotlist,
if(job->retry > 0)
retry= 1;
else if(job-retry == 0 && is_cd)
else if(job->retry == 0 && is_cd)
retry= 1;
start_lba= from_lba;
to_read= read_chunk;
post_read_time= Sfile_microtime(0);
for(i= 0; i < block_count; i+= to_read) {
skip_reading= 0;
if(job->abort_file_path[0]) {
if(post_read_time - last_abort_file_time >= 0.1) {
if(stat(job->abort_file_path, &stbuf) != -1) {
if(stbuf.st_mtime >= xorriso->start_time) {
sprintf(xorriso->info_text,
"-check_media: Found fresh abort_file=%s",
job->abort_file_path);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
goto abort_check;
}
}
last_abort_file_time= post_read_time;
}
}
if(job->item_limit > 0 &&
Spotlist_count(spotlist, 0) + 2 >= job->item_limit) {
sprintf(xorriso->info_text, "-check_media: Reached item_limit=%d",
@ -6636,6 +6656,7 @@ abort_check:;
ret= 2;
goto ex;
}
to_read= read_chunk;
if(i + to_read > block_count)
to_read= block_count - i;
@ -6645,20 +6666,22 @@ abort_check:;
*/
if(to_read > 2)
to_read-= 2;
else if(to_read > 1)
to_read--;
else if(to_read > 1) {
if(flag & 1) {
quality= Xorriso_read_quality_tao_enD;
skip_reading= 1;
} else
to_read--;
}
}
#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)) {
if(sector_size == read_chunk && from_lba % read_chunk == 0
&& !skip_reading) {
if(Sectorbitmap_is_set(job->sector_map, (i + from_lba) / sector_size, 0)){
quality= Xorriso_read_quality_valiD;
skip_reading= 1;
}
} else if(sector_size > 0) {
} else if(sector_size > 0 && !skip_reading) {
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);
@ -6684,32 +6707,29 @@ abort_check:;
total_count++;
if(ret <= 0) {
Xorriso_process_msg_queues(xorriso,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;
if(data_count / 2048 < to_read) {
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;
}
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;
#ifdef NIX
if(read_chunk > min_block_size) {
/* >>> evaluate min blocks */;
}
#endif
quality= Xorriso_read_quality_unreadablE;
if(retry)
to_read= data_count / 2048 + 1;
} else
quality= Xorriso_read_quality_partiaL;
fret= Xorriso_eval_problem_status(xorriso, ret, 1|2);
if(fret<0)
goto ex;
} else {
quality= Xorriso_read_quality_gooD;
@ -6775,7 +6795,7 @@ ex:
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 media_blocks= 0, read_chunk= 16, ret, mode, start_lba= 0;
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;
@ -6791,17 +6811,16 @@ int Xorriso_check_media(struct XorrisO *xorriso, struct SpotlisT **spotlist,
*spotlist= NULL;
ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
"on attempt to check media readability", 0);
"on attempt to check media readability",
!!job->use_outdev);
if(ret<=0)
goto ex;
/* >>> determine media type dependent blocking factor:
2 kB for CD and disk , 32 kB for DVD, 64 kB for BD
eventually adjust min_block_size and read_chunk
32 kB for CD (with 2kB retry) iand DVD, 64 kB for BD
eventually adjust read_chunk
*/;
/* <<< */
min_block_size= read_chunk;
ret= Spotlist_new(spotlist, 0);
if(ret <= 0)
@ -6841,7 +6860,7 @@ int Xorriso_check_media(struct XorrisO *xorriso, struct SpotlisT **spotlist,
blocks= job->max_lba - start_lba;
xorriso->pacifier_total= blocks;
ret= Xorriso_check_interval(xorriso, *spotlist, job, start_lba, blocks,
read_chunk, min_block_size, 0);
read_chunk, 0);
if(ret <= 0)
goto ex;
@ -6867,6 +6886,7 @@ int Xorriso_check_media(struct XorrisO *xorriso, struct SpotlisT **spotlist,
Xorriso_read_quality_off_tracK, 0);
if(ret <= 0)
goto ex;
xorriso->pacifier_count+= track_lba - last_track_end;
}
last_track_end= track_lba + track_blocks;
@ -6882,9 +6902,8 @@ int Xorriso_check_media(struct XorrisO *xorriso, struct SpotlisT **spotlist,
if(ret <= 0)
goto ex;
} else {
ret= Xorriso_check_interval(xorriso, *spotlist, job,
track_lba, track_blocks,
read_chunk, min_block_size, 0);
ret= Xorriso_check_interval(xorriso, *spotlist, job, track_lba,
track_blocks, read_chunk, i > 0);
if(ret <= 0)
goto ex;
if(ret == 2)
@ -6909,7 +6928,7 @@ no_content_visible:;
goto no_content_visible;
xorriso->pacifier_total= blocks;
ret= Xorriso_check_interval(xorriso, *spotlist, job, start_lba, blocks,
read_chunk, min_block_size, 0);
read_chunk, 0);
if(ret <= 0)
goto ex;
} else if(mode == 2) {

View File

@ -279,6 +279,8 @@ int Xorriso_msinfo(struct XorrisO *xorriso, int *msc1, int *msc2, int flag);
struct CheckmediajoB {
int use_outdev; /* 0= use indev , 1= use outdev */
int min_lba; /* if >=0 : begin checking at this address */
int max_lba; /* if >=0 : read up to this address, else use mode */
@ -294,6 +296,8 @@ struct CheckmediajoB {
int item_limit; /* Maximum number of media check list items as result */
char abort_file_path[SfileadrL];
char data_to_path[SfileadrL];
int data_to_fd;