diff --git a/cdrskin/cdrskin.1 b/cdrskin/cdrskin.1 index 00f391d..21fba8b 100644 --- a/cdrskin/cdrskin.1 +++ b/cdrskin/cdrskin.1 @@ -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 CDRSKIN 1 "February 8, 2007" +.TH CDRSKIN 1 "February 14, 2007" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: @@ -370,8 +370,8 @@ Note: msifile=path is actually an option of wodim and not of cdrecord. .BI \-msinfo Retrieve multi-session info for preparing a follow-up session by option -C of programs mkisofs or genisoimage. Print result to standard output. -This option redirects to stderr all -message output besides its own result string, which consists of two numbers. +This option redirects to stderr all message output except the one of option +--tell_media_space and its own result string, which consists of two numbers. The result string shall be used as argument of option -C with said programs. It gives the start address of the most recent session and the predicted start address of the next session to be appended. The string is empty if @@ -591,6 +591,24 @@ for best DVD-ROM compatibility. If the track source delivers less bytes than announced then the missing ones will be filled with zeros. .TP +.BI --tell_media_space +Prepare a recording session, do not perform it but rather inquire the +maximum number of 2048 byte data blocks which may be written in +the current state of media with the prepared setup. So this option disables +recording of data. It does allow blanking, though, and will measure space +afterwards. +.br +It is not mandatory to give track sources but their nature may influence +the available capacity. So for most realistic results one may set up +the full burn session and add --tell_media_space. But if one has to expect +a cdrskin version prior to 0.3.3 no track source should be given in order +to start no involuntary burn session. +In this case set at least -sao or -tao explicitely. +.br +The result gets printed to standard output. +This option redirects to stderr all message output except its own result +string and eventual output of -msinfo. +.TP .BI write_start_address= byte_offset Set the address on media where to start writing the track. With DVD+RW or DVD-RAM byte_offset must be aligned to 2 KB blocks, but better is 32 kB. @@ -642,6 +660,15 @@ Disable fifo despite any fs=. .BI \--fifo_per_track Use a separate fifo for each track. .TP +.BI \--fill_up_media +.B Caution: +Option is still immature and likely to change. +Problems arose with sequential DVD-RW. +.br +Expand the last track of the session to occupy all remaining free space on +the media. +This option overrides option -multi. +.TP .BI grab_drive_and_wait= seconds Open the addressed drive, wait the given number of seconds, release the drive, and do normal work as indicated by the other options used. This option helps diff --git a/cdrskin/cdrskin.c b/cdrskin/cdrskin.c index 3f706c3..b0c2a17 100644 --- a/cdrskin/cdrskin.c +++ b/cdrskin/cdrskin.c @@ -131,7 +131,8 @@ or /* Place novelty switch macros here. Move them down to Cdrskin_libburn_from_pykix_svN on version leap */ -/* no novelties yet */ +#define Cdrskin_libburn_has_set_filluP 1 +#define Cdrskin_libburn_has_get_spacE 1 #endif /* Cdrskin_libburn_0_3_3 */ @@ -1307,6 +1308,12 @@ int Cdrtrack_activate_tao_tsize(struct CdrtracK *track, int flag) } +int Cdrtrack_get_sectors(struct CdrtracK *track, int flag) +{ + return(burn_track_get_sectors(track->libburn_track)); +} + + #ifndef Cdrskin_extra_leaN /** Try to read bytes from the track's fifo outlet and eventually discard @@ -2002,6 +2009,9 @@ set_dev:; " fifo_start_at= do not wait for full fifo but start burning\n"); printf( " as soon as the given number of bytes is read\n"); +#ifdef Cdrskin_libburn_has_set_filluP + printf(" --fill_up_media cause the last track to have maximum size\n"); +#endif printf( " grab_drive_and_wait= grab drive, wait given number of\n"); printf( @@ -2035,6 +2045,11 @@ set_dev:; printf(" (set tao_to_sao_tsize=0 to disable it)\n"); #endif +#ifdef Cdrskin_libburn_has_get_spacE + printf( + " --tell_media_space prints maximum number of writeable data blocks\n"); +#endif + printf( " write_start_address= write to given byte address (DVD+RW)\n"); printf( @@ -2310,9 +2325,12 @@ ex:; */ -/** Limit to prevent int rollovers within libburn as long as not everything is - changed to 64 bit off_t : 2 GB minus 800 MB for eventual computations. */ +/** <<< Hopefully obsolete: + Limit to prevent int rollovers within libburn as long as not everything is + changed to 64 bit off_t : 2 GB minus 800 MB for eventual computations. #define Cdrskin_tracksize_maX 1308622848 +*/ +#define Cdrskin_tracksize_maX 1024.0*1024.0*1024.0*1024.0 /* Some constants obtained by hearsay and experiments */ @@ -2384,6 +2402,7 @@ struct CdrskiN { double blank_format_size; /* to be used with burn_disc_format() */ int do_burn; + int tell_media_space; /* actually do not burn but tell the available space */ int burnfree; /** The write mode (like SAO or RAW96/R). See libburn. Controled by preskin->write_mode_name */ @@ -2405,6 +2424,7 @@ struct CdrskiN { double fixed_size; double padding; int set_by_padsize; + int fill_up_media; /** track_type may be set to BURN_MODE1, BURN_AUDIO, etc. */ int track_type; @@ -2509,6 +2529,7 @@ int Cdrskin_new(struct CdrskiN **skin, struct CdrpreskiN *preskin, int flag) o->blank_format_type= 0; o->blank_format_size= 0.0; o->do_burn= 0; + o->tell_media_space= 0; o->write_type= BURN_WRITE_SAO; o->block_type= BURN_BLOCK_SAO; o->multi= 0; @@ -2520,6 +2541,7 @@ int Cdrskin_new(struct CdrskiN **skin, struct CdrpreskiN *preskin, int flag) o->fixed_size= 0.0; o->padding= 0.0; o->set_by_padsize= 0; + o->fill_up_media= 0; o->track_type= BURN_MODE1; o->swap_audio_bytes= 1; /* cdrecord default is big-endian (msb_first) */ o->track_type_by_default= 1; @@ -3493,125 +3515,6 @@ int Cdrskin_obtain_nwa(struct CdrskiN *skin, int *nwa, int flag) } -/** Print lba of first track of last session and Next Writeable Address of - the next unwritten session. -*/ -int Cdrskin_msinfo(struct CdrskiN *skin, int flag) -{ - int num_sessions, session_no, ret, num_tracks; - int nwa= -123456789, lba= -123456789, aux_lba; - char msg[80]; - enum burn_disc_status s; - struct burn_drive *drive; - struct burn_disc *disc= NULL; - struct burn_session **sessions= NULL; - struct burn_track **tracks; - struct burn_toc_entry toc_entry; - - ret= Cdrskin_grab_drive(skin,0); - if(ret<=0) - return(ret); - drive= skin->drives[skin->driveno].drive; - s= burn_disc_get_status(drive); - if(s!=BURN_DISC_APPENDABLE) { - Cdrskin_report_disc_status(skin,s,0); - fprintf(stderr,"cdrskin: FATAL : -msinfo can only operate on appendable (i.e. -multi) discs\n"); - {ret= 0; goto ex;} - } - disc= burn_drive_get_disc(drive); - if(disc==NULL) { - -#ifdef Cdrskin_libburn_has_get_msc1 - /* No TOC available. Try to inquire directly. */ - ret= burn_disc_get_msc1(drive,&lba); - if(ret>0) - goto obtain_nwa; -#endif /* Cdrskin_libburn_has_get_msc1 */ - - fprintf(stderr,"cdrskin: FATAL : Cannot obtain info about CD content\n"); - {ret= 0; goto ex;} - } - sessions= burn_disc_get_sessions(disc,&num_sessions); - for(session_no= 0; session_no0) - nwa= aux_lba+6900; - else - nwa= aux_lba+11400; - } - if(skin->msinfo_fd>=0) { - sprintf(msg,"%d,%d\n",lba,nwa); - write(skin->msinfo_fd,msg,strlen(msg)); - } else - printf("%d,%d\n",lba,nwa); - - if(strlen(skin->msifile)) { - FILE *fp; - - fp = fopen(skin->msifile, "w"); - if(fp==NULL) { - if(errno>0) - fprintf(stderr,"cdrskin: %s (errno=%d)\n", strerror(errno), errno); - fprintf(stderr,"cdrskin: FATAL : Cannot write msinfo to file '%s'\n", - skin->msifile); - {ret= 0; goto ex;} - } - fprintf(fp,"%d,%d",lba,nwa); - fclose(fp); - } - ret= 1; -ex:; - - /* must calm down my NEC ND-4570A afterwards */ - if(skin->verbosity>=Cdrskin_verbose_debuG) - ClN(fprintf(stderr,"cdrskin_debug: doing extra release-grab cycle\n")); - Cdrskin_release_drive(skin,0); - Cdrskin_grab_drive(skin,0); - - Cdrskin_release_drive(skin,0); - return(ret); -} - - /** Perform -toc under control of Cdrskin_atip(). @param flag Bitfield for control purposes: bit0= do not list sessions separately (do it cdrecord style) @@ -4378,10 +4281,10 @@ thank_you_for_patience:; fixed_size= skin->fixed_size; padding= skin->padding; } - if(fixed_size) { - sprintf(mb_text,"%4d of %4d", - (int) (written_total_bytes/1024.0/1024.0), - (int) ((fixed_size+padding)/1024.0/1024.0)); + if(fixed_size || (skin->fill_up_media && + skin->supposed_track_idx==skin->track_counter-1)) { + sprintf(mb_text,"%4d of %4d",(int) (written_total_bytes/1024.0/1024.0), + Cdrtrack_get_sectors(skin->tracklist[skin->supposed_track_idx],0)/512); } else sprintf(mb_text,"%4d",(int) (written_total_bytes/1024.0/1024.0)); speed_factor= Cdrskin_speed_factoR*sector_size/2048; @@ -4678,8 +4581,13 @@ int Cdrskin_burn(struct CdrskiN *skin, int flag) double total_count= 0.0,last_count= 0.0,size,padding,sector_size= 2048.0; double sectors; - printf("cdrskin: beginning to burn disk\n"); - + printf("cdrskin: beginning to %s disc\n", + skin->tell_media_space?"estimate":"burn"); + if(skin->fill_up_media && skin->multi) { + fprintf(stderr, + "cdrskin: NOTE : Option --fill_up_media disabled option -multi\n"); + skin->multi= 0; + } ret= Cdrskin_grab_drive(skin,0); if(ret<=0) goto burn_failed; @@ -4790,11 +4698,13 @@ burn_failed:; } } - Cdrskin_wait_before_action(skin,0); - ret= Cdrskin_fill_fifo(skin,0); - if(ret<=0) { - fprintf(stderr,"cdrskin: FATAL : filling of fifo failed\n"); - goto ex; + if(!skin->tell_media_space) { + Cdrskin_wait_before_action(skin,0); + ret= Cdrskin_fill_fifo(skin,0); + if(ret<=0) { + fprintf(stderr,"cdrskin: FATAL : filling of fifo failed\n"); + goto ex; + } } #endif /* ! Cdrskin_extra_leaN */ @@ -4806,10 +4716,12 @@ burn_failed:; #ifdef Cdrskin_libburn_has_multI burn_write_opts_set_multi(o,skin->multi); #endif - #ifdef Cdrskin_libburn_has_set_start_bytE burn_write_opts_set_start_byte(o, skin->write_start_address); #endif +#ifdef Cdrskin_libburn_has_set_filluP + burn_write_opts_set_fillup(o, skin->fill_up_media); +#endif burn_write_opts_set_write_type(o,skin->write_type,skin->block_type); if(skin->dummy_mode) { @@ -4819,6 +4731,27 @@ burn_failed:; } burn_write_opts_set_underrun_proof(o,skin->burnfree); + + if(skin->tell_media_space || skin->track_counter<=0) { + /* write capacity estimation and return without actual burning */ +#ifdef Cdrskin_libburn_has_get_spacE + off_t free_space; + char msg[80]; + + free_space= burn_disc_available_space(drive,o); + sprintf(msg,"%d\n",(int) (free_space/(off_t) 2048)); + if(skin->msinfo_fd>=0) { + write(skin->msinfo_fd,msg,strlen(msg)); + } else + printf("%s",msg); +#endif /* Cdrskin_libburn_has_get_spacE */ + if(skin->track_counter>0) + fprintf(stderr, + "cdrskin: NOTE : Burn run suppressed by option --tell_media_space\n"); + {ret= 1; goto ex;} + } + + Cdrskin_adjust_speed(skin,0); if(skin->verbosity>=Cdrskin_verbose_progresS) { ret= Cdrskin_obtain_nwa(skin, &nwa,0); @@ -5018,6 +4951,125 @@ ex:; } +/** Print lba of first track of last session and Next Writeable Address of + the next unwritten session. +*/ +int Cdrskin_msinfo(struct CdrskiN *skin, int flag) +{ + int num_sessions, session_no, ret, num_tracks; + int nwa= -123456789, lba= -123456789, aux_lba; + char msg[80]; + enum burn_disc_status s; + struct burn_drive *drive; + struct burn_disc *disc= NULL; + struct burn_session **sessions= NULL; + struct burn_track **tracks; + struct burn_toc_entry toc_entry; + + ret= Cdrskin_grab_drive(skin,0); + if(ret<=0) + return(ret); + drive= skin->drives[skin->driveno].drive; + s= burn_disc_get_status(drive); + if(s!=BURN_DISC_APPENDABLE) { + Cdrskin_report_disc_status(skin,s,0); + fprintf(stderr,"cdrskin: FATAL : -msinfo can only operate on appendable (i.e. -multi) discs\n"); + {ret= 0; goto ex;} + } + disc= burn_drive_get_disc(drive); + if(disc==NULL) { + +#ifdef Cdrskin_libburn_has_get_msc1 + /* No TOC available. Try to inquire directly. */ + ret= burn_disc_get_msc1(drive,&lba); + if(ret>0) + goto obtain_nwa; +#endif /* Cdrskin_libburn_has_get_msc1 */ + + fprintf(stderr,"cdrskin: FATAL : Cannot obtain info about CD content\n"); + {ret= 0; goto ex;} + } + sessions= burn_disc_get_sessions(disc,&num_sessions); + for(session_no= 0; session_no0) + nwa= aux_lba+6900; + else + nwa= aux_lba+11400; + } + if(skin->msinfo_fd>=0) { + sprintf(msg,"%d,%d\n",lba,nwa); + write(skin->msinfo_fd,msg,strlen(msg)); + } else + printf("%d,%d\n",lba,nwa); + + if(strlen(skin->msifile)) { + FILE *fp; + + fp = fopen(skin->msifile, "w"); + if(fp==NULL) { + if(errno>0) + fprintf(stderr,"cdrskin: %s (errno=%d)\n", strerror(errno), errno); + fprintf(stderr,"cdrskin: FATAL : Cannot write msinfo to file '%s'\n", + skin->msifile); + {ret= 0; goto ex;} + } + fprintf(fp,"%d,%d",lba,nwa); + fclose(fp); + } + ret= 1; +ex:; + + /* must calm down my NEC ND-4570A afterwards */ + if(skin->verbosity>=Cdrskin_verbose_debuG) + ClN(fprintf(stderr,"cdrskin_debug: doing extra release-grab cycle\n")); + Cdrskin_release_drive(skin,0); + Cdrskin_grab_drive(skin,0); + + Cdrskin_release_drive(skin,0); + return(ret); +} + + /** Work around the failure of libburn to eject the tray. This employs a system(2) call and is therefore an absolute no-no for any pseudo user identities. @@ -5432,6 +5484,13 @@ set_driveropts:; } else if(strcmp(argv[i],"--fifo_per_track")==0) { skin->fifo_per_track= 1; +#ifdef Cdrskin_libburn_has_set_filluP + } else if(strcmp(argv[i],"--fill_up_media")==0) { + skin->fill_up_media= 1; + if(skin->verbosity>=Cdrskin_verbose_cmD) + printf("cdrskin: will fill up last track to full free media space\n"); +#endif + } else if(strcmp(argv[i],"-force")==0) { skin->force_is_set= 1; @@ -5641,6 +5700,11 @@ set_speed:; #endif skin->tao_to_sao_tsize); +#ifdef Cdrskin_libburn_has_get_spacE + } else if(strcmp(argv[i],"--tell_media_space")==0) { + skin->tell_media_space= 1; +#endif + } else if(strcmp(argv[i],"-toc")==0) { skin->do_atip= 2; if(skin->verbosity>=Cdrskin_verbose_cmD) @@ -5949,7 +6013,7 @@ int Cdrskin_run(struct CdrskiN *skin, int *exit_value, int flag) if(ret<=0) {*exit_value= 8; goto ex;} } - if(skin->do_burn) { + if(skin->do_burn || skin->tell_media_space) { if(skin->n_drives<=0) {*exit_value= 10; goto no_drive;} ret= Cdrskin_burn(skin,0); @@ -5976,7 +6040,7 @@ int main(int argc, char **argv) /* For -msinfo: Redirect normal stdout to stderr */ for(i=1; i