/* cc -g -c \ -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1 -D_LARGEFILE64_SOURCE \ burn_wrap.c */ /* libburn wrappers for libisoburn Copyright 2007 Thomas Schmitt, */ /* <<< A70929 : hardcoded CD-RW with fabricated -msinfo #define Hardcoded_cd_rW 1 #define Hardcoded_cd_rw_c1 12999 #define Hardcoded_cd_rw_nwA 152660 */ #include #include #include #include #include #include #include #include #ifndef Xorriso_standalonE #include #include #else /* ! Xorriso_standalonE */ #include "../libisofs/libisofs.h" #include "../libburn/libburn.h" #endif /* Xorriso_standalonE */ #include "libisoburn.h" #include "isoburn.h" /* The global list of isoburn objects. Usually there is only one. */ extern struct isoburn *isoburn_list_start; /* in isoburn.c */ int isoburn_initialize(char msg[1024], int flag) { int major, minor, micro; msg[0]= 0; if(iso_init()<0) { sprintf(msg+strlen(msg), "Cannot initialize libisofs\n"); return(0); } iso_lib_version(&major, &minor, µ); sprintf(msg+strlen(msg), "libisofs-%d.%d.%d , ", major, minor, micro); if(!burn_initialize()) { sprintf(msg+strlen(msg), "Cannot initialize libburn\n"); return(0); } burn_version(&major, &minor, µ); sprintf(msg+strlen(msg), "libburn-%d.%d.%d , ", major, minor, micro); isoburn_destroy_all(&isoburn_list_start, 0); /* isoburn_list_start= NULL */ isoburn_version(&major, &minor, µ); sprintf(msg+strlen(msg), "libisoburn-%d.%d.%d", major, minor, micro); return(1); } /** Examine the media and sets appropriate emulation if needed. */ static int isoburn_welcome_media(struct isoburn **o, struct burn_drive *d, int flag) { int ret, lba, nwa; struct burn_multi_caps *caps= NULL; 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; ret= isoburn_new(o, 0); if(ret<=0) goto ex; (*o)->drive= d; #ifdef Hardcoded_cd_rW /* <<< A70929 : hardcoded CD-RW with fabricated -msinfo */ caps->start_adr= 0; (*o)->fabricated_disc_status= BURN_DISC_APPENDABLE; #endif if(caps->start_adr) { /* set emulation to overwriteable */ (*o)->emulation_mode= 1; ret= isoburn_start_emulation(*o, 0); if(ret<=0) { (*o)->emulation_mode= -1; goto ex; } } else { /* >>> recognize unsuitable media (but allow read-only media) */; #ifdef Hardcoded_cd_rW (*o)->nwa= Hardcoded_cd_rw_nwA; #else ret= burn_disc_track_lba_nwa(d, NULL, 0, &lba, &nwa); if(ret>0) (*o)->nwa= nwa; #endif } ret= 1; ex: if(caps!=NULL) burn_disc_free_multi_caps(&caps); return(ret); } int isoburn_drive_scan_and_grab(struct burn_drive_info *drive_infos[], char *adr, int load) { int ret, conv_ret, drive_grabbed= 0; char libburn_drive_adr[BURN_DRIVE_ADR_LEN]; struct isoburn *o= NULL; char msg[BURN_MSGS_MESSAGE_LEN+4096]; conv_ret= burn_drive_convert_fs_adr(adr, libburn_drive_adr); if(conv_ret<=0) { sprintf(msg, "Unsuitable drive address: '%s'\n",adr); msg[BURN_MSGS_MESSAGE_LEN-1]= 0; burn_msgs_submit(0, msg, 0, "SORRY", NULL); ret= 0; goto ex; } ret= burn_drive_scan_and_grab(drive_infos, libburn_drive_adr, load); if(ret<=0) goto ex; drive_grabbed= 1; ret= isoburn_welcome_media(&o, (*drive_infos)[0].drive, 0); if(ret<=0) goto ex; ret= 1; ex: if(ret<=0) { if(drive_grabbed) burn_drive_release((*drive_infos)[0].drive, 0); isoburn_destroy(&o, 0); } return(ret); } int isoburn_drive_grab(struct burn_drive *drive, int load) { int ret; struct isoburn *o= NULL; ret= burn_drive_grab(drive, load); if(ret<=0) goto ex; ret= isoburn_welcome_media(&o, drive, 0); if(ret<=0) goto ex; ret= 1; ex: if(ret<=0) isoburn_destroy(&o,0); return(ret); } /** Retrieve media emulation and eventual isoburn emulator of drive. @return -1 unsuitable media, 0 generic media, 1 emulated media. */ int isoburn_find_emulator(struct isoburn **pt, struct burn_drive *drive, int flag) { int ret; ret= isoburn_find_by_drive(pt, drive, 0); if(ret<=0) return(0); if((*pt)->emulation_mode==-1) return(-1); if((*pt)->emulation_mode==0) return(0); return(1); } enum burn_disc_status isoburn_disc_get_status(struct burn_drive *drive) { int ret; struct isoburn *o; ret= isoburn_find_emulator(&o, drive, 0); if(ret<0) return(BURN_DISC_UNSUITABLE); if(o!=NULL) if(o->fabricated_disc_status!=BURN_DISC_UNREADY) return(o->fabricated_disc_status); if(ret==0) return(burn_disc_get_status(drive)); /* emulated status */ if(o->emulation_mode==-1) return(BURN_DISC_UNSUITABLE); if(o->nwa>0) return(BURN_DISC_APPENDABLE); return(BURN_DISC_BLANK); } int isoburn_disc_erasable(struct burn_drive *d) { int ret; struct isoburn *o; ret= isoburn_find_emulator(&o, d, 0); if(ret>0) if(o->emulation_mode==1) return(1); return burn_disc_erasable(d); } void isoburn_disc_erase(struct burn_drive *drive, int fast) { int ret; struct isoburn *o; ret= isoburn_find_emulator(&o, drive, 0); if(ret>0) { if(o->emulation_mode==-1) { /* To cause a negative reply with burn_drive_wrote_well() */ burn_drive_cancel(drive); return; } if(o->emulation_mode>0) { ret= isoburn_invalidate_iso(o, 0); if(ret<=0) burn_drive_cancel(drive); return; } } burn_disc_erase(drive, fast); } int isoburn_disc_get_msc1(struct burn_drive *d, int *start_lba) { int ret; struct isoburn *o; #ifdef Hardcoded_cd_rW /* <<< A70929 : hardcoded CD-RW with fabricated -msinfo */ *start_lba= Hardcoded_cd_rw_c1; return(1); #endif if(isoburn_disc_get_status(d)!=BURN_DISC_APPENDABLE && isoburn_disc_get_status(d)!=BURN_DISC_FULL) return(0); ret= isoburn_find_emulator(&o, d, 0); if(ret<0) return(0); if(ret>0) if(o->emulation_mode>0) { *start_lba= 0; return(1); } return(burn_disc_get_msc1(d, start_lba)); } int isoburn_disc_track_lba_nwa(struct burn_drive *d, struct burn_write_opts *opts, int trackno, int *lba, int *nwa) { int ret; struct isoburn *o; #ifdef Hardcoded_cd_rW /* <<< A70929 : hardcoded CD-RW with fabricated -msinfo */ *lba= Hardcoded_cd_rw_c1; *nwa= Hardcoded_cd_rw_nwA; return(1); #endif *nwa= *lba= 0; ret= isoburn_find_emulator(&o, d, 0); if(ret<0) return(0); if(ret>0) if(o->emulation_mode>0) { *lba= 0; *nwa= o->nwa; return(1); } if(burn_drive_get_drive_role(d) != 1) return(1); return(burn_disc_track_lba_nwa(d, opts, trackno, lba, nwa)); } void isoburn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc) { int ret; struct isoburn *o; struct burn_drive *drive; char reasons[BURN_REASONS_LEN],msg[160+BURN_REASONS_LEN]; enum burn_write_types write_type; drive= burn_write_opts_get_drive(opts); ret= isoburn_find_emulator(&o, drive, 0); if(ret<0) return; if(o!=NULL) { o->wrote_well= -1; 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); } } write_type= burn_write_opts_auto_write_type(opts, disc, reasons, 0); if (write_type == BURN_WRITE_NONE) { sprintf(msg, "Failed to find a suitable write mode:\n%s", reasons); burn_msgs_submit(0, msg, 0, "SORRY", NULL); if(o!=NULL) o->wrote_well= 0; /* To cause a negative reply with burn_drive_wrote_well() */ burn_drive_cancel(drive); 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))); */ #ifdef Hardcoded_cd_rW /* <<< A70929 : hardcoded CD-RW with fabricated -msinfo */ fprintf(stderr, "Setting write address to LBA %d\n", Hardcoded_cd_rw_nwA); burn_write_opts_set_start_byte(opts, ((off_t) Hardcoded_cd_rw_nwA) * (off_t) 2048); #endif burn_disc_write(opts, disc); } void isoburn_drive_release(struct burn_drive *drive, int eject) { int ret; struct isoburn *o; ret= isoburn_find_emulator(&o, drive, 0); if(ret<0) return; if(o!=NULL) { isoburn_destroy(&o, 0); } burn_drive_release(drive, eject); } void isoburn_finish(void) { isoburn_destroy_all(&isoburn_list_start, 0); burn_finish(); iso_finish(); } int isoburn_needs_emulation(struct burn_drive *drive) { int ret; struct isoburn *o; enum burn_disc_status s; s= isoburn_disc_get_status(drive); if(s!=BURN_DISC_BLANK && s!=BURN_DISC_APPENDABLE) return(-1); ret= isoburn_find_emulator(&o, drive, 0); if(ret<0) return(-1); if(ret>0) if(o->emulation_mode>0) return(1); return(0); } int isoburn_set_start_byte(struct isoburn *o, off_t value, int flag) { int ret; struct burn_drive *drive = o->drive; struct burn_multi_caps *caps= NULL; ret= burn_disc_get_multi_caps(drive, BURN_WRITE_NONE, &caps, 0); if(ret<=0) goto ex; if(!caps->start_adr) {ret= 0; goto ex;} o->min_start_byte= value; 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); ret= 1; ex: if(caps!=NULL) burn_disc_free_multi_caps(&caps); return(ret); } int isoburn_get_min_start_byte(struct burn_drive *d, off_t *start_byte, int flag) { int ret; struct isoburn *o; ret= isoburn_find_emulator(&o, d, 0); if(ret<0) return(-1); if(ret==0) return(0); *start_byte= o->min_start_byte; if(o->min_start_byte<=0) return(0); return(1); } int isoburn_drive_wrote_well(struct burn_drive *d) { int ret; struct isoburn *o; ret= isoburn_find_emulator(&o, d, 0); if(ret<0) return(-1); if(o!=NULL) if(o->wrote_well>=0) return(o->wrote_well); ret= burn_drive_wrote_well(d); return ret; } int isoburn_get_fifo_status(struct burn_drive *d, int *size, int *free_bytes, char **status_text) { int ret; struct isoburn *o; #ifdef Libisoburn_no_fifO size_t hsize= 0, hfree_bytes= 0; #endif ret= isoburn_find_emulator(&o, d, 0); if(ret<0) return(-1); if(o==NULL) return(0); #ifdef Libisoburn_no_fifO if(o->iso_source==NULL) return(0); ret= iso_ring_buffer_get_status(o->iso_source, &hsize, &hfree_bytes); if(hsize > 1024*1024*1024) *size= 1024*1024*1024; else *size= hsize; if(hfree_bytes > 1024*1024*1024) *free_bytes= 1024*1024*1024; else *free_bytes= hfree_bytes; *status_text= ""; if(ret==1) *status_text= "active"; else if(ret==2) *status_text= "ending"; else if(ret==3) *status_text= "failing"; else if(ret==5) *status_text= "abandoned"; else if(ret==6) *status_text= "ended"; else if(ret==7) *status_text= "aborted"; #else if(o->fifo==NULL) return(0); ret= burn_fifo_inquire_status(o->fifo, size, free_bytes, status_text); #endif /* ! Libisoburn_no_fifO */ return(ret); }