diff --git a/libisoburn/burn_wrap.c b/libisoburn/burn_wrap.c index abe00807..677e21c9 100644 --- a/libisoburn/burn_wrap.c +++ b/libisoburn/burn_wrap.c @@ -213,7 +213,27 @@ int isoburn_libburn_req(int *major, int *minor, int *micro) } -/** Examine the media and sets appropriate emulation if needed. +int isoburn_is_intermediate_dvd_rw(struct burn_drive *d, int flag) +{ + int profile, ret= 0, format_status, num_formats; + char profile_name[80]; + enum burn_disc_status s; + off_t format_size= -1; + unsigned bl_sas; + + s= isoburn_disc_get_status(d); + ret= burn_disc_get_profile(d, &profile, profile_name); + if(ret>0 && profile==0x13) + ret= burn_disc_get_formats(d, &format_status, &format_size, + &bl_sas, &num_formats); + if(ret>0 && profile==0x13 && s==BURN_DISC_BLANK && + format_status==BURN_FORMAT_IS_UNKNOWN) + return(1); + return(0); +} + + +/** Examines the media and sets appropriate emulation if needed. @param flag bit0= pretent blank on overwriteable media */ static int isoburn_welcome_media(struct isoburn **o, struct burn_drive *d, @@ -238,9 +258,14 @@ static int isoburn_welcome_media(struct isoburn **o, struct burn_drive *d, if(caps->start_adr) { /* set emulation to overwriteable */ (*o)->emulation_mode= 1; - - if(flag&1) { + ret= isoburn_is_intermediate_dvd_rw(d, 0); + if(ret>0) { + (*o)->min_start_byte= 0; (*o)->nwa= 0; + (*o)->zero_nwa= 0; + } + if(flag&1) { + (*o)->nwa= (*o)->zero_nwa; (*o)->fabricated_disc_status= BURN_DISC_BLANK; } else { ret= isoburn_start_emulation(*o, 0); @@ -386,7 +411,7 @@ enum burn_disc_status isoburn_disc_get_status(struct burn_drive *drive) /* emulated status */ if(o->emulation_mode==-1) return(BURN_DISC_UNSUITABLE); - if(o->nwa>0) + if(o->nwa>o->zero_nwa) return(BURN_DISC_APPENDABLE); return(BURN_DISC_BLANK); } @@ -520,6 +545,16 @@ void isoburn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc) enum burn_write_types write_type; struct stat stbuf; +#ifdef NIX + /* <<< now in isoburn_is_intermediate_dvd_rw() + */ + int profile, format_status, num_formats; + unsigned bl_sas; + off_t format_size= -1; + char profile_name[80]; + enum burn_disc_status s; +#endif + drive= burn_write_opts_get_drive(opts); ret= isoburn_find_emulator(&o, drive, 0); if(ret<0) @@ -529,8 +564,52 @@ void isoburn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc) if(o->emulation_mode!=0) { burn_write_opts_set_multi(opts, 0); if(o->emulation_mode>0 && o->nwa >= 0) { - burn_write_opts_set_start_byte(opts, ((off_t) o->nwa) * (off_t) 2048); nwa= o->nwa; + + /* This caters for unwritten formatted DVD-RW. They need to be written + sequentially on the first use. Only written areas are random access. + If the first session is not written to LBA 0, then re-opening of + formatting and padding is needed. + This can be done. But when the track gets closed after padding, + this lasts a long time. There is a high risk that an app will not + poll the message queue while waiting for isoburn_disc_write() to + return. The pacifier loop usually happens only afterwards. + So automatic formatting might cause a nervous clueless user. + */ + +#ifdef NIX + /* <<< now in isoburn_is_intermediate_dvd_rw() + */ + s= isoburn_disc_get_status(drive); + ret= burn_disc_get_profile(drive, &profile, profile_name); + if(ret>0 && profile==0x13) + ret= burn_disc_get_formats(drive, &format_status, &format_size, + &bl_sas, &num_formats); + if(ret>0 && profile==0x13 && s==BURN_DISC_BLANK && nwa>0 && + nwa <= o->zero_nwa && format_status==BURN_FORMAT_IS_UNKNOWN) { + +#else + + ret= isoburn_is_intermediate_dvd_rw(drive, 0); + if(ret>0 && nwa>0 && nwa <= o->zero_nwa) { + +#endif /* ! NIX */ + + /* actually this should not happen since such media get recognized + by isoburn_welcome_media and o->zero_nwa gets set to 0 + */ + sprintf(msg, + "DVD-RW insufficiently formatted. (Intermediate State, size unknown)"); + burn_msgs_submit(0x00060000, msg, 0, "FAILURE", NULL); + sprintf(msg, + "It might help to first deformat it and then format it again"); + burn_msgs_submit(0x00060000, msg, 0, "HINT", NULL); + burn_drive_cancel(drive); /* mark run as failure */ + return; + } + /* end of DVD-RW oriented check */ + + burn_write_opts_set_start_byte(opts, nwa * (off_t) 2048); } } } @@ -546,12 +625,11 @@ void isoburn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc) return; } -/* sprintf(reasons, "%d", (int) write_type); - fprintf(stderr, "isoburn_EXPERIMENTAL: write_type = %s\n", - (write_type == BURN_WRITE_SAO ? "SAO" : - (write_type == BURN_WRITE_TAO ? "TAO" : reasons))); -*/ + sprintf(msg, "Write_type = %s\n", + (write_type == BURN_WRITE_SAO ? "SAO" : + (write_type == BURN_WRITE_TAO ? "TAO" : reasons))); + burn_msgs_submit(0x00060000, msg, 0, "DEBUG", NULL); #ifdef Hardcoded_cd_rW /* <<< A70929 : hardcoded CD-RW with fabricated -msinfo */ @@ -638,9 +716,10 @@ int isoburn_set_start_byte(struct isoburn *o, off_t value, int flag) if(value % caps->start_alignment) value+= caps->start_alignment - (value % caps->start_alignment); o->nwa= value/2048; - /* If suitable for alignment, round up to full 16 sector addresses */ - if((o->nwa%16) && ((16*2048) % caps->start_alignment)==0 ) - o->nwa+= 16 - (o->nwa%16); + /* If suitable for media alignment, round up to Libisoburn_nwa_alignemenT */ + if((o->nwa % Libisoburn_nwa_alignemenT) && + ((Libisoburn_nwa_alignemenT*2048) % caps->start_alignment)==0 ) + o->nwa+= Libisoburn_nwa_alignemenT - (o->nwa % Libisoburn_nwa_alignemenT); ret= 1; ex: if(caps!=NULL) diff --git a/libisoburn/isoburn.c b/libisoburn/isoburn.c index 3af7a1f6..29bc23c2 100644 --- a/libisoburn/isoburn.c +++ b/libisoburn/isoburn.c @@ -42,6 +42,51 @@ #include "../version.h" */ +/* ----------------------- isoburn_toc_entry ---------------------- */ + + +int isoburn_toc_entry_new(struct isoburn_toc_entry **objpt, + struct isoburn_toc_entry *boss, int flag) +{ + struct isoburn_toc_entry *o, *s; + + *objpt= o= (struct isoburn_toc_entry *) + malloc(sizeof(struct isoburn_toc_entry)); + if(o==NULL) { + burn_msgs_submit(0x00060000, + "Cannot allocate memory for isoburn toc entry", + 0, "FATAL", NULL); + return(-1); + } + o->session= 0; + o->track_no= 0; + o->start_lba= -1; + o->track_blocks= 0; + o->next= NULL; + if(boss!=NULL) { + for(s= boss; s->next!=NULL; s= s->next); + s->next= o; + } + return(1); +} + + +/* @param flag bit0= delete all subordinates too +*/ +int isoburn_toc_entry_destroy(struct isoburn_toc_entry **o, int flag) +{ + if(*o==NULL) + return(0); + if(flag&1) + isoburn_toc_entry_destroy(&((*o)->next), flag); + free((char *) (*o)); + *o= NULL; + return(1); +} + + +/* --------------------- end isoburn_toc_entry -------------------- */ + /* -------------------------- isoburn ----------------------- */ @@ -67,8 +112,9 @@ int isoburn_new(struct isoburn **objpt, int flag) o->drive= NULL; o->emulation_mode= 0; - o->min_start_byte= 0; - o->nwa= 0; + o->zero_nwa= Libisoburn_overwriteable_starT; + o->min_start_byte= o->zero_nwa * 2048; + o->nwa= o->zero_nwa; o->truncate= 0; #ifdef Libisoburn_no_fifO @@ -77,8 +123,9 @@ int isoburn_new(struct isoburn **objpt, int flag) o->fifo= NULL; #endif - o->wrote_well= -1; o->fabricated_disc_status= BURN_DISC_UNREADY; + o->toc= NULL; + o->wrote_well= -1; for(i=0;i<65536;i++) o->target_iso_head[i]= 0; o->image= NULL; @@ -121,6 +168,8 @@ int isoburn_destroy(struct isoburn **objpt, int flag) if(o->image!=NULL) iso_image_unref(o->image); + if(o->toc!=NULL) + isoburn_toc_entry_destroy(&(o->toc), 1); /* all */ #ifdef Libisoburn_no_fifO if(o->iso_source!=NULL) burn_source_free(o->iso_source); @@ -339,8 +388,9 @@ int isoburn_prepare_disc_aux(struct burn_drive *d, struct burn_disc **disc, } if (nwa == 0 && state == BURN_DISC_APPENDABLE) { /* invalid nwa */ - burn_msgs_submit(0x00060000, "Encountered 0 as next writeable address", 0, - "FAILURE", NULL); + burn_msgs_submit(0x00060000, + "Encountered 0 as next writeable address of appendable", + 0, "FAILURE", NULL); {ret= -4; goto ex;} } iso_write_opts_set_ms_block(wopts, nwa); diff --git a/libisoburn/isoburn.h b/libisoburn/isoburn.h index e22ee55c..5ccd5e3d 100644 --- a/libisoburn/isoburn.h +++ b/libisoburn/isoburn.h @@ -17,6 +17,18 @@ /* for uint8_t */ #include +/* For emulated TOC of overwriteable media. + Provides minimal info for faking a struct burn_toc_entry. +*/ +struct isoburn_toc_entry { + int session; + int track_no; /* point */ + int start_lba; + int track_blocks; + + struct isoburn_toc_entry *next; +}; + struct isoburn { @@ -36,6 +48,11 @@ struct isoburn { struct isoburn *next; + /* The nwa to be used for a first session on the present kind of overwriteable + media (usually Libisoburn_overwriteable_starT, but might be forced to 0) + */ + int zero_nwa; + /* Start address as given by image examination (bytes, not blocks) */ off_t min_start_byte; @@ -51,6 +68,11 @@ struct isoburn { */ enum burn_disc_status fabricated_disc_status; + /* Eventual emulated table of content read from the chain of ISO headers + on overwriteable media. + */ + struct isoburn_toc_entry *toc; + #ifndef Libisoburn_no_fifO /* The fifo which is installed between track and libisofs burn_source */ @@ -328,5 +350,34 @@ struct isoburn_imgen_opts { int effective_lba; }; + +/* Alignment for session starts on overwriteable media. + (Increased from 16 to 32 blocks for aligning to BD-RE clusters.) +*/ +#define Libisoburn_nwa_alignemenT 32 + +/* Size of target_iso_head which is to be written during + isoburn_activate_session() +*/ +#define Libisoburn_target_head_sizE (32*2048) + +/* >>> Experiment to create a chain of image headers which form a TOC: + + The header of the first session is written after the LBA 0 header. + So it persists and can give the end of its session. By help of + Libisoburn_nwa_alignemenT it should be possible to predict the start + of the next session header. + The LBA 0 header is written by isoburn_activate_session() already + with the first session. So the media is mountable. + A problem arises with DVD-RW in Intermediate State. They cannot be + written by random access before they were written sequentially. + In this case, no copy of the session 1 header is maintained and no TOC + will be possible. Thus writing begins sequentially at LBA 0. +*/ +#define Libisoburn_overwriteable_starT \ + ((off_t) (Libisoburn_target_head_sizE/2048)) + + + #endif /* Isoburn_includeD */ diff --git a/libisoburn/isofs_wrap.c b/libisoburn/isofs_wrap.c index 58e98748..f6d03eb4 100644 --- a/libisoburn/isofs_wrap.c +++ b/libisoburn/isofs_wrap.c @@ -26,7 +26,6 @@ #endif /* Xorriso_standalonE */ - #include "isoburn.h" #include "libisoburn.h" @@ -281,11 +280,13 @@ int isoburn_activate_session(struct burn_drive *drive) if (o->emulation_mode != 1) return 1; /* don't need to activate session */ - if (o->fabricated_disc_status != BURN_DISC_APPENDABLE) + if (!(o->fabricated_disc_status == BURN_DISC_APPENDABLE || + (o->fabricated_disc_status == BURN_DISC_BLANK && + o->zero_nwa > 0))) return 1; ret = burn_random_access_write(drive, 0, (char*)o->target_iso_head, - 32*2048, 1); + Libisoburn_target_head_sizE, 1); return ret; } @@ -356,7 +357,7 @@ int isoburn_start_emulation(struct isoburn *o, int flag) } else if (!strncmp((char*)pvm->std_identifier, "CDXX1", 5)) { /* empty image */ - isoburn_set_start_byte(o, (off_t) 0, 0); + isoburn_set_start_byte(o, o->zero_nwa * 2048, 0); o->fabricated_disc_status= BURN_DISC_BLANK; } else { /* treat any disc in an unknown format as full */ diff --git a/xorriso/xorriso_timestamp.h b/xorriso/xorriso_timestamp.h index 455ba0a8..78521c2b 100644 --- a/xorriso/xorriso_timestamp.h +++ b/xorriso/xorriso_timestamp.h @@ -1 +1 @@ -#define Xorriso_timestamP "2008.05.06.084439" +#define Xorriso_timestamP "2008.05.06.144606"