/* 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, */ #include #include #include #include #include #include #include #include #include #include #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(void) { if(!iso_init()) return(0); if(!burn_initialize()) return(0); isoburn_destroy_all(&isoburn_list_start, 0); /* isoburn_list_start= NULL */ 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; struct burn_multi_caps *caps= NULL; ret= burn_disc_get_multi_caps(d, BURN_WRITE_NONE, &caps, 0); if(ret<=0) goto ex; ret= isoburn_new(o, 0); if(ret<=0) goto ex; (*o)->drive= d; 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 */; } /* <<< now planned to be done by app ret = isoburn_read_volset(*o); if(ret<=0) { (*o)->emulation_mode= -1; goto ex; } */ 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, treatment= 0, conv_ret; struct stat stbuf; char libburn_drive_adr[BURN_DRIVE_ADR_LEN], *adrpt, *stdio_adr= NULL; struct isoburn *o= NULL; /* Treatment decision criteria Prefixes "grow:" leads to: treatment 1, image growing Prefix "modify:" leads to: treatment 2, image modification Anything else is decided automatically If suitable as libburn drive address: treatment 1 ("stdio:" fits here) else if non-existent or regular file: treatment 2 else if block device : treatment 1 else : unsuitable target */ adrpt= adr; if(strncmp(adr, "grow:", 5)==0) { treatment= 1; adrpt+= 5; if(stat(adrpt,&stbuf)!=-1) { if(S_ISREG(stbuf.st_mode) || S_ISBLK(stbuf.st_mode)) { stdio_adr= calloc(strlen(adrpt)+6+1, 1); if(stdio_adr==NULL) {ret= -1; goto ex;} sprintf(stdio_adr, "stdio:%s", adrpt); /* use pseudo-drive */ adrpt= stdio_adr; } } } else if(strncmp(adr, "modify:", 7)==0) { adrpt+= 7; treatment= 2; if(stat(adrpt,&stbuf)!=-1) { if(! S_ISREG(stbuf.st_mode)) { /* >>> we need a gateway to the libisofs/libburn message system */; fprintf(stderr, "LIBISOBURN: unsuitable target for modify: '%s'\n",adr); ret= 0; goto ex; } } sprintf(stdio_adr, "stdio:%s", adrpt); /* use pseudo-drive */ adrpt= stdio_adr; } else { /* >>> interpret "read:" , "write:" for modification on MMC drives */; } conv_ret= burn_drive_convert_fs_adr(adrpt, libburn_drive_adr); if(treatment==0) { /* undecided yet, make a decision or declare failure */ if(conv_ret>0) treatment= 1; /* Device file leading to MMC drive or "stdio:" address */ else { if(stat(adrpt,&stbuf)==-1) { /* burn_drive_scan_and_grab() will check whether the directory exists */ treatment= 2; } else if(S_ISREG(stbuf.st_mode)) treatment= 2; else if(S_ISBLK(stbuf.st_mode)) treatment= 1; if(treatment>=0) { sprintf(stdio_adr, "stdio:%s", adrpt); /* use pseudo-drive */ adrpt= stdio_adr; conv_ret= 1; /* All "stdio:" addresses are ok for now */ } } } if(conv_ret<=0 || treatment<=0) { /* Failure */ /* >>> we need a gateway to the libisofs/libburn message system */; fprintf(stderr, "LIBISOBURN: unsuitable drive address: '%s'\n", adrpt); ret= 0; goto ex; } ret= burn_drive_scan_and_grab(drive_infos, adrpt, load); if(ret<=0) goto ex; ret= isoburn_welcome_media(&o, (*drive_infos)[0].drive, 0); if(ret<=0) goto ex; if(o!=NULL) o->treatment= treatment; ret= 1; ex: if(ret<=0) isoburn_destroy(&o,0); if(stdio_adr!=NULL) free(stdio_adr); 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; if(isoburn_disc_get_status(d)!=BURN_DISC_APPENDABLE) 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; 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); } 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, multi= 1; struct isoburn *o; struct burn_drive *drive; drive= burn_write_opts_get_drive(opts); ret= isoburn_find_emulator(&o, drive, 0); if(ret<0) return; if(o!=NULL) { if(o->emulation_mode!=0) { multi= 0; if(o->emulation_mode>0 && o->nwa >= 0) burn_write_opts_set_start_byte(opts, ((off_t) o->nwa) * (off_t) 2048); } } burn_write_opts_set_multi(opts, multi); 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; ret= 1; ex: if(caps!=NULL) burn_disc_free_multi_caps(&caps); return(ret); } #ifdef Libburn_obsoleted_on_its_way_ouT void isoburn_write_opts_set_start_byte(struct burn_write_opts *opts, off_t value) { int ret; struct isoburn *o; struct burn_drive *drive; drive= burn_write_opts_get_drive(opts); ret= isoburn_find_emulator(&o, drive, 0); if(ret<=0) /* no emulation, no burn_write_opts_set_start_byte() */ return; ret = isoburn_set_start_byte(o, value, 0); if(ret<=0) return; burn_write_opts_set_start_byte(opts, ((off_t) o->nwa) * (off_t) 2048); } #endif /* Libburn_obsoleted_on_its_way_ouT */