Try to read header chain from alleged -ROM media (e.g. DVD+RW in -ROM drive)

This commit is contained in:
Thomas Schmitt 2008-05-08 14:10:43 +00:00
parent 252521f930
commit 7f1b8b07a6
4 changed files with 130 additions and 32 deletions

View File

@ -241,16 +241,25 @@ int isoburn_is_intermediate_dvd_rw(struct burn_drive *d, int flag)
/** Examines the media and sets appropriate emulation if needed.
@param flag bit0= pretent blank on overwriteable media
bit3= if the drive reports a -ROM profile then try to read
table of content by scanning for ISO image headers.
*/
static int isoburn_welcome_media(struct isoburn **o, struct burn_drive *d,
int flag)
{
int ret, lba, nwa;
int ret, lba, nwa, profile, readonly= 0;
struct burn_multi_caps *caps= NULL;
char profile_name[80];
profile_name[0]= 0;
ret= burn_disc_get_profile(d, &profile, profile_name);
if(ret<=0)
profile= 0x00;
ret= burn_disc_get_multi_caps(d, BURN_WRITE_NONE, &caps, 0);
if(ret<0) /* == 0 is read-only media, but it is too early to reject it here */
goto ex;
if(ret==0)
readonly= 1;
ret= isoburn_new(o, 0);
if(ret<=0)
goto ex;
@ -286,10 +295,27 @@ static int isoburn_welcome_media(struct isoburn **o, struct burn_drive *d,
goto ex;
}
}
} else {
/* >>> recognize unsuitable media (but allow read-only media) */;
/* >>> recognize unsuitable media (but allow read-only media) */;
if(readonly) {
/* This might be overwriteable media in a -ROM drive */
ret= isoburn_emulate_toc(d, 1);
if(ret<0)
goto ex;
if(ret==0 && profile !=0x08 && (flag&8)) {
/* This might also be multi-session media which do not
get shown with a decent TOC.
CD-R TOC (profile 0x08) can be trusted. Others not.
*/
/* do a scan search of ISO headers */
ret= isoburn_emulate_toc(d, 1|2);
if(ret<0)
goto ex;
}
}
#ifdef Hardcoded_cd_rW
(*o)->nwa= Hardcoded_cd_rw_nwA;
#else
@ -312,6 +338,10 @@ ex:
bit1= regard overwriteable media as blank
bit2= if the drive is a regular disk file: truncate it to
the write start address
bit3= if the drive reports a -ROM profile then try to read
table of content by scanning for ISO image headers.
(depending on media type and drive state this might
help or it might make the resulting toc even worse)
*/
int isoburn_drive_aquire(struct burn_drive_info *drive_infos[],
char *adr, int flag)
@ -333,7 +363,8 @@ int isoburn_drive_aquire(struct burn_drive_info *drive_infos[],
if(ret<=0)
goto ex;
drive_grabbed= 1;
ret= isoburn_welcome_media(&o, (*drive_infos)[0].drive, !!(flag&2));
ret= isoburn_welcome_media(&o, (*drive_infos)[0].drive,
(flag&8) | !!(flag&2));
if(ret<=0)
goto ex;
@ -925,31 +956,24 @@ int isoburn_report_iso_error(int iso_error_code, char msg_text[], int os_errno,
}
/* API
@param flag bit0-7: info return mode
0= do not return anything in info (do not even touch it)
1= return volume id
/* @param flag bit0-7: info return mode
0= do not return anything in info (do not even touch it)
1= return volume id
bit14= -reserved -
bit15= -reserved-
@return 1 seems to be a valid ISO image , 0 format not recognized, <0 error
*/
int isoburn_read_iso_head(struct burn_drive *d, int lba,
int *image_blocks, char *info, int flag)
int isoburn_read_iso_head_parse(struct burn_drive *d, unsigned char *data,
int *image_blocks, char *info, int flag)
{
unsigned char buffer[64*1024], *data;
int ret, i, info_mode;
off_t data_count;
int i, info_mode;
*image_blocks= 0;
ret = burn_read_data(d, ((off_t) lba) * (off_t) 2048, (char *) buffer,
(off_t) 64*1024, &data_count, 2); /* no error messages */
if(ret<=0)
return(0);
data= buffer+32*1024;
/* is this an ISO image ? */
if(data[0]!=1)
return(0);
if(strncmp((char *) (data+1),"CD001",5)!=0)
return(0);
/* believe so */
*image_blocks= data[80] | (data[81]<<8) | (data[82]<<16) | (data[83]<<24);
info_mode= flag&255;
@ -971,11 +995,53 @@ int isoburn_read_iso_head(struct burn_drive *d, int lba,
}
return(1);
}
/* API
@param flag bit0-7: info return mode
0= do not return anything in info (do not even touch it)
1= return volume id
bit14= check both half buffers (not only second)
return 2 if found in first block
bit15= return-1 on read error
@return 1 seems to be a valid ISO image , 2 found in first half buffer,
0 format not recognized, <0 error
*/
int isoburn_read_iso_head(struct burn_drive *d, int lba,
int *image_blocks, char *info, int flag)
{
unsigned char buffer[64*1024];
int ret;
off_t data_count;
*image_blocks= 0;
ret = burn_read_data(d, ((off_t) lba) * (off_t) 2048, (char *) buffer,
(off_t) 64*1024, &data_count, 2); /* no error messages */
if(ret<=0)
return(-1*!!(flag&(1<<15)));
if(flag&(1<<14)) {
ret= isoburn_read_iso_head_parse(d, buffer, image_blocks, info,
flag&255);
if(ret<0)
return(ret);
if(ret>0)
return(2);
}
ret= isoburn_read_iso_head_parse(d, buffer+32*1024, image_blocks, info,
flag&255);
return(ret);
}
/* @param flag bit0= allow unemulated media
bit1= free scanning without enclosing LBA-0-header
@return -1 severe error, 0= no neat header chain, 1= credible chain read
*/
int isoburn_emulate_toc(struct burn_drive *d, int flag)
{
int ret, image_size= 0, lba, track_blocks, session_count= 0;
int ret, image_size= 0, lba, track_blocks, session_count= 0, read_flag= 0;
int scan_start= 0;
struct isoburn *o;
struct isoburn_toc_entry *item;
char msg[160];
@ -986,20 +1052,32 @@ int isoburn_emulate_toc(struct burn_drive *d, int flag)
return(-1);
if(o==NULL)
return(-1);
if(o->emulation_mode<=0)
if(o->emulation_mode<=0 && !(flag&1))
return(0);
lba= 0;
ret= isoburn_read_iso_head(d, lba, &image_size, NULL, 0);
if(ret<=0)
{ret= 0; goto failure;}
lba= Libisoburn_overwriteable_starT;
while(lba<image_size) {
ret= isoburn_read_iso_head(d, lba, &track_blocks, NULL, 0);
if(!(flag&2)) {
ret= isoburn_read_iso_head(d, lba, &image_size, NULL, 0);
if(ret<=0)
{ret= 0; goto failure;}
lba= Libisoburn_overwriteable_starT;
}
while(lba<image_size || (flag&2)) {
read_flag= 0;
if(flag&2)
read_flag= (1<<15)|((session_count>0)<<14);
ret= isoburn_read_iso_head(d, lba, &track_blocks, NULL, read_flag);
if(ret<=0) {
if(session_count>0) {
if(flag&2) {
if(ret==0) {
/* try at next 64 k block (check both 32 k halves) */
lba+= 32;
if(lba-scan_start <= Libisoburn_toc_scan_max_gaP)
continue;
}
break;
}
sprintf(msg,
"Chain of ISO session headers broken at #%d, LBA %ds",
session_count+1, lba);
@ -1007,6 +1085,8 @@ int isoburn_emulate_toc(struct burn_drive *d, int flag)
}
{ret= 0; goto failure;}
}
if(ret==2) /* ISO header was found in first half block */
lba-= 16;
ret= isoburn_toc_entry_new(&item, o->toc, 0);
if(ret<=0) {
burn_msgs_submit(0x00060000,
@ -1025,6 +1105,7 @@ int isoburn_emulate_toc(struct burn_drive *d, int flag)
lba+= track_blocks;
if(lba % Libisoburn_nwa_alignemenT)
lba+= Libisoburn_nwa_alignemenT - (lba % Libisoburn_nwa_alignemenT);
scan_start= lba;
}
sprintf(msg,
"Chain of ISO session headers yielded %d sessions", session_count);
@ -1110,7 +1191,7 @@ struct isoburn_toc_disc *isoburn_toc_drive_get_disc(struct burn_drive *d)
/* is the media emulated multi-session ? */
ret= isoburn_find_emulator(&o, d, 0);
if(ret<=0)
if(ret<0)
goto libburn;
if(o->toc==NULL)
goto libburn;

View File

@ -351,6 +351,19 @@ struct isoburn_imgen_opts {
*/
#define Libisoburn_nwa_alignemenT 32
/* Alignment for outer session scanning with -ROM drives.
(E.g. my DVD-ROM drive shows any DVD type as 0x10 "DVD-ROM" with
more or less false capacity and TOC.)
*/
#define Libisoburn_toc_scan_alignemenT 16
/* Maximum gap to be bridged during a outer TOC scan. Gaps appear between the
end of a session and the start of the next session.
*/
#define Libisoburn_toc_scan_max_gaP 8192
/* Size of target_iso_head which is to be written during
isoburn_activate_session()
*/

View File

@ -330,6 +330,10 @@ int isoburn_drive_scan_and_grab(struct burn_drive_info *drive_infos[],
bit1= regard overwriteable media as blank
bit2= if the drive is a regular disk file: truncate it to
the write start address
bit3= if the drive reports a read-only profile try to read
table of content by scanning for ISO image headers.
(depending on media type and drive this might
help or it might make the resulting toc even worse)
@return 1 = success , 0 = drive not found , <0 = other error
*/
int isoburn_drive_aquire(struct burn_drive_info *drive_infos[],

View File

@ -1 +1 @@
#define Xorriso_timestamP "2008.05.07.214442"
#define Xorriso_timestamP "2008.05.08.141054"