|
|
|
@ -50,6 +50,9 @@
|
|
|
|
|
extern struct isoburn *isoburn_list_start; /* in isoburn.c */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int isoburn_emulate_toc(struct burn_drive *d, int flag); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int isoburn_initialize(char msg[1024], int flag) |
|
|
|
|
{ |
|
|
|
|
int major, minor, micro, bad_match= 0; |
|
|
|
@ -276,6 +279,12 @@ static int isoburn_welcome_media(struct isoburn **o, struct burn_drive *d,
|
|
|
|
|
(*o)->emulation_mode= -1; |
|
|
|
|
goto ex; |
|
|
|
|
} |
|
|
|
|
/* try to read emulated toc */ |
|
|
|
|
ret= isoburn_emulate_toc(d, 0); |
|
|
|
|
if(ret<0) { |
|
|
|
|
(*o)->emulation_mode= -1; |
|
|
|
|
goto ex; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
|
|
|
|
@ -915,3 +924,372 @@ int isoburn_report_iso_error(int iso_error_code, char msg_text[], int os_errno,
|
|
|
|
|
return(ret); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* @param flag bit0-7: info return mode
|
|
|
|
|
0= do not return anything in info (do not even touch it) |
|
|
|
|
1= return volume id
|
|
|
|
|
@return 1 seems to be a valid ISO image , 0 seems not to be ISO, <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], *data; |
|
|
|
|
int ret, i, info_mode; |
|
|
|
|
off_t data_count; |
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
*image_blocks= data[80] | (data[81]<<8) | (data[82]<<16) | (data[83]<<24); |
|
|
|
|
info_mode= flag&255; |
|
|
|
|
if(info_mode==0) { |
|
|
|
|
; |
|
|
|
|
} else if(info_mode==1) { |
|
|
|
|
strncpy(info, (char *) (data+40), 32); |
|
|
|
|
info[32]= 0; |
|
|
|
|
for(i= strlen(info)-1; i>=0; i--) |
|
|
|
|
if(info[i]!=' ') |
|
|
|
|
break; |
|
|
|
|
else |
|
|
|
|
info[i]= 0; |
|
|
|
|
} else { |
|
|
|
|
burn_msgs_submit(0x00060000, |
|
|
|
|
"Program error: Unknown info mode with isoburn_read_iso_head()", |
|
|
|
|
0, "FATAL", NULL); |
|
|
|
|
return(-1); |
|
|
|
|
} |
|
|
|
|
return(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int isoburn_emulate_toc(struct burn_drive *d, int flag) |
|
|
|
|
{ |
|
|
|
|
int ret, image_size= 0, lba, track_blocks, session_count= 0; |
|
|
|
|
struct isoburn *o; |
|
|
|
|
struct isoburn_toc_entry *item; |
|
|
|
|
char msg[160]; |
|
|
|
|
|
|
|
|
|
/* is the media emulated multi-session ? */ |
|
|
|
|
ret= isoburn_find_emulator(&o, d, 0); |
|
|
|
|
if(ret<0) |
|
|
|
|
return(-1); |
|
|
|
|
if(o==NULL) |
|
|
|
|
return(-1); |
|
|
|
|
if(o->emulation_mode<=0) |
|
|
|
|
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(ret<=0) { |
|
|
|
|
if(session_count>0) { |
|
|
|
|
sprintf(msg, |
|
|
|
|
"Chain of ISO session headers broken at #%d, LBA %ds", |
|
|
|
|
session_count+1, lba); |
|
|
|
|
burn_msgs_submit(0x00060000, msg, 0, "WARNING", NULL); |
|
|
|
|
} |
|
|
|
|
{ret= 0; goto failure;} |
|
|
|
|
} |
|
|
|
|
ret= isoburn_toc_entry_new(&item, o->toc, 0); |
|
|
|
|
if(ret<=0) { |
|
|
|
|
burn_msgs_submit(0x00060000, |
|
|
|
|
"Not enough memory for emulated TOC entry object", |
|
|
|
|
0, "FATAL", NULL); |
|
|
|
|
ret= -1; goto failure; |
|
|
|
|
} |
|
|
|
|
if(o->toc==NULL) |
|
|
|
|
o->toc= item; |
|
|
|
|
session_count++; |
|
|
|
|
item->session= session_count; |
|
|
|
|
item->track_no= session_count; |
|
|
|
|
item->start_lba= lba; |
|
|
|
|
item->track_blocks= track_blocks; |
|
|
|
|
|
|
|
|
|
lba+= track_blocks; |
|
|
|
|
if(lba % Libisoburn_nwa_alignemenT) |
|
|
|
|
lba+= Libisoburn_nwa_alignemenT - (lba % Libisoburn_nwa_alignemenT); |
|
|
|
|
} |
|
|
|
|
sprintf(msg, |
|
|
|
|
"Chain of ISO session headers yielded %d sessions", session_count); |
|
|
|
|
burn_msgs_submit(0x00060000, msg, 0, "DEBUG", NULL); |
|
|
|
|
return(1); |
|
|
|
|
failure:; |
|
|
|
|
isoburn_toc_entry_destroy(&(o->toc), 1); |
|
|
|
|
return(ret); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int isoburn_toc_new_arrays(struct isoburn_toc_disc *o, |
|
|
|
|
int session_count, int track_count, int flag) |
|
|
|
|
{ |
|
|
|
|
int i; |
|
|
|
|
int isoburn_toc_destroy_arrays(struct isoburn_toc_disc *o, int flag); |
|
|
|
|
|
|
|
|
|
o->sessions= calloc(session_count, sizeof(struct isoburn_toc_session)); |
|
|
|
|
o->session_pointers= |
|
|
|
|
calloc(session_count, sizeof(struct isoburn_toc_session *)); |
|
|
|
|
o->tracks= calloc(track_count, sizeof(struct isoburn_toc_track)); |
|
|
|
|
o->track_pointers= calloc(track_count, sizeof(struct isoburn_toc_track *)); |
|
|
|
|
if(o->sessions!=NULL && o->session_pointers!=NULL && |
|
|
|
|
o->tracks!=NULL && o->track_pointers!=NULL) { |
|
|
|
|
for(i= 0; i<session_count; i++) { |
|
|
|
|
o->sessions[i].session= NULL; |
|
|
|
|
o->sessions[i].track_pointers= NULL; |
|
|
|
|
o->sessions[i].track_count= 0; |
|
|
|
|
o->sessions[i].toc_entry= NULL; |
|
|
|
|
o->session_pointers[i]= NULL; |
|
|
|
|
} |
|
|
|
|
for(i= 0; i<track_count; i++) { |
|
|
|
|
o->tracks[i].track= NULL; |
|
|
|
|
o->tracks[i].toc_entry= NULL; |
|
|
|
|
o->track_pointers[i]= NULL; |
|
|
|
|
} |
|
|
|
|
return(1); |
|
|
|
|
} |
|
|
|
|
/* failed */ |
|
|
|
|
isoburn_toc_destroy_arrays(o, 0); |
|
|
|
|
return(-1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int isoburn_toc_destroy_arrays(struct isoburn_toc_disc *o, int flag) |
|
|
|
|
{ |
|
|
|
|
if(o->sessions!=NULL) |
|
|
|
|
free((char *) o->sessions); |
|
|
|
|
o->sessions= NULL; |
|
|
|
|
if(o->session_pointers!=NULL) |
|
|
|
|
free((char *) o->session_pointers); |
|
|
|
|
o->session_pointers= NULL; |
|
|
|
|
if(o->tracks!=NULL) |
|
|
|
|
free((char *) o->tracks); |
|
|
|
|
o->tracks= NULL; |
|
|
|
|
if(o->track_pointers!=NULL) |
|
|
|
|
free((char *) o->track_pointers); |
|
|
|
|
o->track_pointers= NULL; |
|
|
|
|
return(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct isoburn_toc_disc *isoburn_toc_drive_get_disc(struct burn_drive *d) |
|
|
|
|
{ |
|
|
|
|
int ret, session_count= 0, track_count= 0, num_tracks= 0, i, j; |
|
|
|
|
struct isoburn *o; |
|
|
|
|
struct isoburn_toc_entry *t; |
|
|
|
|
struct isoburn_toc_disc *toc_disc= NULL; |
|
|
|
|
struct burn_session **s; |
|
|
|
|
struct burn_track **tracks; |
|
|
|
|
|
|
|
|
|
toc_disc= calloc(1, sizeof(struct isoburn_toc_disc)); |
|
|
|
|
if(toc_disc==NULL) |
|
|
|
|
return(NULL); |
|
|
|
|
toc_disc->disc= NULL; |
|
|
|
|
toc_disc->sessions= NULL; |
|
|
|
|
toc_disc->session_pointers= NULL; |
|
|
|
|
toc_disc->tracks= NULL; |
|
|
|
|
toc_disc->track_pointers= NULL; |
|
|
|
|
toc_disc->session_count= 0; |
|
|
|
|
toc_disc->track_count= 0; |
|
|
|
|
toc_disc->toc= NULL;
|
|
|
|
|
|
|
|
|
|
/* is the media emulated multi-session ? */ |
|
|
|
|
ret= isoburn_find_emulator(&o, d, 0); |
|
|
|
|
if(ret<=0) |
|
|
|
|
goto libburn; |
|
|
|
|
if(o->toc==NULL) |
|
|
|
|
goto libburn; |
|
|
|
|
|
|
|
|
|
/* This is an emulated TOC */ |
|
|
|
|
toc_disc->toc= o->toc; |
|
|
|
|
for(t= toc_disc->toc; t!=NULL; t= t->next) |
|
|
|
|
session_count++; |
|
|
|
|
ret= isoburn_toc_new_arrays(toc_disc, session_count, session_count, 0); |
|
|
|
|
if(ret<=0) |
|
|
|
|
goto failure; |
|
|
|
|
t= toc_disc->toc; |
|
|
|
|
for(i= 0; i<session_count; i++) { |
|
|
|
|
toc_disc->sessions[i].track_pointers= toc_disc->track_pointers+i; |
|
|
|
|
toc_disc->sessions[i].track_count= 1; |
|
|
|
|
toc_disc->sessions[i].toc_entry= t; |
|
|
|
|
toc_disc->session_pointers[i]= toc_disc->sessions+i; |
|
|
|
|
toc_disc->tracks[i].toc_entry= t; |
|
|
|
|
toc_disc->track_pointers[i]= toc_disc->tracks+i; |
|
|
|
|
t= t->next; |
|
|
|
|
} |
|
|
|
|
toc_disc->session_count= session_count; |
|
|
|
|
toc_disc->track_count= session_count; |
|
|
|
|
return(toc_disc); |
|
|
|
|
|
|
|
|
|
libburn:; |
|
|
|
|
/* This is a libburn provided TOC */ |
|
|
|
|
toc_disc->disc= burn_drive_get_disc(d); |
|
|
|
|
if(toc_disc->disc == NULL) { |
|
|
|
|
failure:; |
|
|
|
|
free((char *) toc_disc); |
|
|
|
|
return(NULL); |
|
|
|
|
} |
|
|
|
|
s= burn_disc_get_sessions(toc_disc->disc, &session_count); |
|
|
|
|
for(i= 0; i<session_count; i++) { |
|
|
|
|
tracks = burn_session_get_tracks(s[i], &num_tracks); |
|
|
|
|
track_count+= num_tracks; |
|
|
|
|
} |
|
|
|
|
if(session_count<=0 || track_count<=0) |
|
|
|
|
goto failure; |
|
|
|
|
ret= isoburn_toc_new_arrays(toc_disc, session_count, track_count, 0); |
|
|
|
|
if(ret<=0) |
|
|
|
|
goto failure; |
|
|
|
|
track_count= 0; |
|
|
|
|
for(i= 0; i<session_count; i++) { |
|
|
|
|
tracks = burn_session_get_tracks(s[i], &num_tracks); |
|
|
|
|
toc_disc->sessions[i].session= s[i]; |
|
|
|
|
toc_disc->sessions[i].track_pointers= toc_disc->track_pointers+track_count; |
|
|
|
|
toc_disc->sessions[i].track_count= num_tracks; |
|
|
|
|
toc_disc->session_pointers[i]= toc_disc->sessions+i; |
|
|
|
|
for(j= 0; j<num_tracks; j++) { |
|
|
|
|
toc_disc->tracks[track_count+j].track= tracks[j]; |
|
|
|
|
toc_disc->track_pointers[track_count+j]= toc_disc->tracks+(track_count+j); |
|
|
|
|
} |
|
|
|
|
track_count+= num_tracks; |
|
|
|
|
} |
|
|
|
|
toc_disc->session_count= session_count; |
|
|
|
|
toc_disc->track_count= track_count; |
|
|
|
|
return(toc_disc); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int isoburn_toc_disc_get_sectors(struct isoburn_toc_disc *disc) |
|
|
|
|
{ |
|
|
|
|
struct isoburn_toc_entry *t; |
|
|
|
|
int count= 0; |
|
|
|
|
|
|
|
|
|
if(disc==NULL) |
|
|
|
|
return(0); |
|
|
|
|
if(disc->toc!=NULL) { |
|
|
|
|
for(t= disc->toc; t!=NULL; t= t->next) |
|
|
|
|
count+= t->track_blocks; |
|
|
|
|
} else if(disc->disc!=NULL) |
|
|
|
|
count= burn_disc_get_sectors(disc->disc); |
|
|
|
|
return(count); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct isoburn_toc_session **isoburn_toc_disc_get_sessions( |
|
|
|
|
struct isoburn_toc_disc *disc, int *num) |
|
|
|
|
{ |
|
|
|
|
*num= disc->session_count; |
|
|
|
|
return(disc->session_pointers); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int isoburn_toc_session_get_sectors(struct isoburn_toc_session *s) |
|
|
|
|
{ |
|
|
|
|
struct isoburn_toc_entry *t; |
|
|
|
|
int count= 0, i; |
|
|
|
|
|
|
|
|
|
if(s==NULL) |
|
|
|
|
return(0); |
|
|
|
|
if(s->toc_entry!=NULL) { |
|
|
|
|
t= s->toc_entry; |
|
|
|
|
for(i= 0; i<s->track_count; i++) { |
|
|
|
|
count+= t->track_blocks; |
|
|
|
|
t= t->next; |
|
|
|
|
} |
|
|
|
|
} else if(s->session!=NULL) |
|
|
|
|
count= burn_session_get_sectors(s->session); |
|
|
|
|
return(count); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int isoburn_toc_entry_finish(struct burn_toc_entry *entry, |
|
|
|
|
int session_no, int track_no, int flag) |
|
|
|
|
{ |
|
|
|
|
int pmin, psec, pframe; |
|
|
|
|
|
|
|
|
|
entry->extensions_valid= 1; |
|
|
|
|
entry->adr= 1; |
|
|
|
|
entry->control= 4; |
|
|
|
|
entry->session= session_no & 255; |
|
|
|
|
entry->session_msb= (session_no >> 8) & 255; |
|
|
|
|
entry->point= track_no & 255; |
|
|
|
|
entry->point_msb= (track_no >> 8) & 255; |
|
|
|
|
|
|
|
|
|
burn_lba_to_msf(entry->start_lba, &pmin, &psec, &pframe); |
|
|
|
|
if(pmin<=255) |
|
|
|
|
entry->pmin= pmin; |
|
|
|
|
else |
|
|
|
|
entry->pmin= 255; |
|
|
|
|
entry->psec= psec; |
|
|
|
|
entry->pframe= pframe;
|
|
|
|
|
return(1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void isoburn_toc_session_get_leadout_entry(struct isoburn_toc_session *s, |
|
|
|
|
struct burn_toc_entry *entry) |
|
|
|
|
{ |
|
|
|
|
struct isoburn_toc_track *t; |
|
|
|
|
|
|
|
|
|
if(s==NULL) |
|
|
|
|
return; |
|
|
|
|
if(s->session!=NULL && s->toc_entry==NULL) { |
|
|
|
|
burn_session_get_leadout_entry(s->session, entry); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if(s->track_count<=0 || s->track_pointers==NULL || s->toc_entry==NULL) |
|
|
|
|
return; |
|
|
|
|
t= s->track_pointers[s->track_count-1]; |
|
|
|
|
entry->start_lba= t->toc_entry->start_lba + t->toc_entry->track_blocks; |
|
|
|
|
entry->track_blocks= 0; |
|
|
|
|
isoburn_toc_entry_finish(entry, s->toc_entry->session, t->toc_entry->track_no, |
|
|
|
|
0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct isoburn_toc_track **isoburn_toc_session_get_tracks( |
|
|
|
|
struct isoburn_toc_session *s, int *num) |
|
|
|
|
{ |
|
|
|
|
*num= s->track_count; |
|
|
|
|
return(s->track_pointers); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void isoburn_toc_track_get_entry(struct isoburn_toc_track *t, |
|
|
|
|
struct burn_toc_entry *entry) |
|
|
|
|
{ |
|
|
|
|
if(t==0) |
|
|
|
|
return; |
|
|
|
|
if(t->track!=NULL && t->toc_entry==NULL) { |
|
|
|
|
burn_track_get_entry(t->track, entry); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if(t->toc_entry==NULL) |
|
|
|
|
return; |
|
|
|
|
entry->start_lba= t->toc_entry->start_lba; |
|
|
|
|
entry->track_blocks= t->toc_entry->track_blocks; |
|
|
|
|
isoburn_toc_entry_finish(entry, t->toc_entry->session, t->toc_entry->track_no, |
|
|
|
|
0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void isoburn_toc_disc_free(struct isoburn_toc_disc *d) |
|
|
|
|
{ |
|
|
|
|
if(d->disc!=NULL) |
|
|
|
|
burn_disc_free(d->disc); |
|
|
|
|
isoburn_toc_destroy_arrays(d, 0); |
|
|
|
|
free((char *) d); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|