From 244f89e27513c14fac6ee4a932d29099ba63bf88 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Sat, 1 Sep 2007 18:20:53 +0000 Subject: [PATCH] Initial content of libisoburn --- libisoburn/burn_wrap.c | 328 ++++++++++++++++++++++++++++++++++++++++ libisoburn/isoburn.c | 231 ++++++++++++++++++++++++++++ libisoburn/isoburn.h | 91 +++++++++++ libisoburn/isofs_wrap.c | 91 +++++++++++ libisoburn/libisoburn.h | 157 +++++++++++++++++++ 5 files changed, 898 insertions(+) create mode 100644 libisoburn/burn_wrap.c create mode 100644 libisoburn/isoburn.c create mode 100644 libisoburn/isoburn.h create mode 100644 libisoburn/isofs_wrap.c create mode 100644 libisoburn/libisoburn.h diff --git a/libisoburn/burn_wrap.c b/libisoburn/burn_wrap.c new file mode 100644 index 00000000..db88a956 --- /dev/null +++ b/libisoburn/burn_wrap.c @@ -0,0 +1,328 @@ + +/* + cc -g -c burn_wrap.c +*/ +/* libburn wrappers for libisoburn + + Copyright 2007 Thomas Schmitt, +*/ + + +#include +#include +#include +#include +#include +#include +#include + + +#include "../libburn/libburn.h" +#include "../libisofs/libisofs.h" +#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) +{ + int ret; + + if(!iso_init()) + return(0); + if(!burn_initialize()) + return(0); + isoburn_destroy_all(&isoburn_list_start, 0); /* isoburn_list_start= NULL */ + + reurn(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; + if(caps->start_adr) { /* set emulation to overwriteable */ + ret= isoburn_new(o, 0); + if(ret<=0) + goto ex; + (*o)->emulation_mode= 1; + (*o)->drive= d; + ret= isoburn_start_emulation(*o, 0); + if(ret<=0) + 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; + struct stat stbuf; + char libburn_drive_adr[BURN_DRIVE_ADR_LEN]; + struct isoburn *o= NULL; + + ret= burn_drive_convert_fs_adr(adr, libburn_drive_adr); + if(ret<0) + return(ret); + if(ret==0) { + if(stat(adr,&stbuf)!=-1) { + if(S_ISREG(stbuf.st_mode) || S_ISBLK(stbuf.st_mode)) { + + return(0); + /* >>> would be acceptable in future */; + + /* >>> create null-drive */; + /* >>> set emulation to standard i/o */; + + } else { + + /* >>> unsuitable file type */; + + return(0); + } + } else { + + /* >>> file not found */; + + return(0); + } + } else { + ret= burn_drive_scan_and_grab(drive_infos, adr, load); + if(ret<=0) + goto ex; + ret= isoburn_examine_media(&o, (*drive_infos)[0].drive, 0); + if(ret<=0) + goto ex; + } + + ret= 1; +ex: + if(ret<=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_examine_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. +*/ +static 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(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); +} + + +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) { + + /* >>> influence wrote_well reply or have wrote_well wrapper ? */ + + return; + } + if(o->emulation_mode>0) { + ret= isoburn_invalidate_iso(o, 0); + + /* >>> influence wrote_well reply or have wrote_well wrapper ? */ + + 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) + return(burn_disc_get_msc1(d, start_lba)); + *start_lba= 0; + return(1); +} + + +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) + return(burn_disc_track_lba_nwa(d, opts, trackno, lba, nwa)); + *lba= 0; + *nwa= o->nwa; + return(1); +} + + +int isoburn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc) +{ + 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) + return(0); + if(o->emulation_mode==2) { + + return(0); + /* >>> implement an asynchronous standard i/o writer */; + + } + burn_disc_write(opts, disc); +} + + +void isoburn_drive_release(struct burn_drive *drive, int eject) +{ + int ret, no_drive_release= 0; + 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); +} + + +void isoburn_write_opts_set_start_byte(struct burn_write_opts *opts, + off_t value) +{ + int ret; + struct isoburn *o; + struct burn_drive *drive; + struct burn_multi_caps *caps= NULL; + + drive= burn_write_opts_get_drive(opts); + ret= isoburn_find_emulator(&o, drive, 0); + if(ret<=0) + goto ex; + ret= burn_disc_get_multi_caps(drive, BURN_WRITE_NONE, &caps, 0); + if(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; + burn_write_opts_set_start_byte(opts, value); +ex: + if(caps!=NULL) + burn_disc_free_multi_caps(&caps); +} + + diff --git a/libisoburn/isoburn.c b/libisoburn/isoburn.c new file mode 100644 index 00000000..89026d76 --- /dev/null +++ b/libisoburn/isoburn.c @@ -0,0 +1,231 @@ + +/* + cc -g -c isoburn.c +*/ + +/* + Class core of libisoburn. + + Copyright 2007 Vreixo Formoso Lopez + and Thomas Schmitt +*/ + +/* ( derived from stub generated by CgeN on Sat, 01 Sep 2007 12:04:36 GMT ) */ + +#include +#include +#include +#include +#include + +#include "isoburn.h" + + + +/* -------------------------- isoburn ----------------------- */ + + +/* The global list of isoburn objects. Usually there is only one. + >>> we are not ready for multiple control threads yet. See >>> mutex . + Multiple burns under one control thread should work. +*/ +struct isoburn *isoburn_list_start= NULL; + + +int isoburn_new(struct isoburn **objpt, int flag) +{ + struct isoburn *o; + int i; + int isoburn_new_rwopts(struct isoburn *o); + + *objpt= o= (struct isoburn *) malloc(sizeof(struct isoburn)); + if(o==NULL) + return(-1); + + o->drive= NULL; + o->emulation_mode= 0; + o->min_start_byte= 0; + o->nwa= 0; + o->target_ropts= NULL; + o->new_wopts= NULL; + for(i=0;i<65536;i++) + o->target_iso_head[i]= 0; + o->target_volset= NULL; + o->prev= NULL; + o->next= NULL; + if(isoburn_new_rwopts(o)<=0) + goto failed; + + isoburn_link(o, isoburn_list_start, 1); + return(1); +failed:; + isoburn_destroy(objpt,0); + return(-1); +} + + +int isoburn_destroy(struct isoburn **objpt, int flag) +{ + struct isoburn *o; + int isoburn_free_rwopts(struct isoburn *o); + + o= *objpt; + if(o==NULL) + return(0); + + /* >>> mutex */ + + if(o==isoburn_list_start) + isoburn_list_start= o->next; + if(o->prev!=NULL) + o->prev->next= o->next; + if(o->next!=NULL) + o->next->prev= o->prev; + + /* >>> end mutex */ + + if(o->drive!=NULL) + burn_drive_release(o->drive, 0); + isoburn_free_rwopts(o); + if(o->target_volset!=NULL) + iso_volset_free(o->target_volset); + + free((char *) o); + *objpt= NULL; + return(1); +} + + +int isoburn_destroy_all(struct isoburn **objpt, int flag) +{ + struct isoburn *o,*n; + + o= *objpt; + if(o==NULL) + return(0); + for(;o->prev!=NULL;o= o->prev); + for(;o!=NULL;o= n) { + n= o->next; + isoburn_destroy(&o,0); + } + *objpt= NULL; + return(1); +} + + +int isoburn_get_emulation_mode(struct isoburn *o, int *pt, int flag) +{ + *pt= o->emulation_mode; + return(1); +} + + +int isoburn_get_target_volset(struct isoburn *o, struct volset **pt, int flag) +{ + *pt= o->target_volset; + return(1); +} + + +int isoburn_get_prev(struct isoburn *o, struct isoburn **pt, int flag) +{ + *pt= o->prev; + return(1); +} + + +int isoburn_get_next(struct isoburn *o, struct isoburn **pt, int flag) +{ + *pt= o->next; + return(1); +} + + +int isoburn_link(struct isoburn *o, struct isoburn *link, int flag) +/* + bit0= insert as link->prev rather than as link->next +*/ +{ + + /* >>> mutex */ + + if(isoburn_list_start==NULL || + isoburn_list_start==link && (flag&1)) + isoburn_list_start= o; + if(o->prev!=NULL) + o->prev->next= o->next; + if(o->next!=NULL) + o->next->prev= o->prev; + o->prev= o->next= NULL; + if(link==NULL) + return(1); + if(flag&1) { + o->next= link; + o->prev= link->prev; + if(o->prev!=NULL) + o->prev->next= o; + link->prev= o; + } else { + o->prev= link; + o->next= link->next; + if(o->next!=NULL) + o->next->prev= o; + link->next= o; + } + + /* >>> end mutex */ + + return(1); +} + + +int isoburn_count(struct isoburn *o, int flag) +/* flag: bit1= count from start of list */ +{ + int counter= 0; + + if(flag&2) + for(;o->prev!=NULL;o= o->prev); + for(;o!=NULL;o= o->next) + counter++; + return(counter); +} + + +int isoburn_by_idx(struct isoburn *o, int idx, struct isoburn **pt, int flag) +/* flag: bit0= fetch first (idx<0) or last (idx>0) item in list + bit1= address from start of list */ +{ + int i,abs_idx; + struct isoburn *npt; + + if(flag&2) + for(;o->prev!=NULL;o= o->prev); + abs_idx= (idx>0?idx:-idx); + *pt= o; + for(i= 0;(i0) + npt= o->next; + else + npt= o->prev; + if(npt==NULL && (flag&1)) + break; + *pt= npt; + } + return(*pt!=NULL); +} + + +int isoburn_find_by_drive(struct isoburn **pt, struct burn_drive *d, int flag) +{ + struct isoburn *o; + + *pt= NULL; + for(o= isoburn_list_start;o->prev!=NULL;o= o->prev) + if(o->drive==d) { + *pt= o; + return(1); + } + return(0); +} + diff --git a/libisoburn/isoburn.h b/libisoburn/isoburn.h new file mode 100644 index 00000000..224d20bf --- /dev/null +++ b/libisoburn/isoburn.h @@ -0,0 +1,91 @@ + +#ifndef Isoburn_includeD +#define Isoburn_includeD + + +/* <<< as long as no inclusion of libisofs.h */ +struct volset; + +/* for uint8_t */ +#include + + +struct isoburn { + + + /* The libburn drive to which this isoburn object is related */ + /* Most isoburn calls will use a burn_drive as object handle */ + struct burn_drive *drive; + + /* -1= inappropriate media state detected */ + /* 0= libburn multi-session media, resp. undecided yet */ + /* 1= random access media */ + /* 2= standard i/o file */ + int emulation_mode; + + /* Although rarely used, libburn can operate on several */ + /* drives simultaneously. */ + /* >>> I propose to design isoburn as chain link of a list with its + /* >>> start stored globally. */ + struct isoburn *prev; + struct isoburn *next; + + + /* --- My part --- */ + + /* Start address as given by image examination (bytes, not blocks) */ + off_t min_start_byte; + + /* Aligned start address to be used for processing (counted in blocks) */ + int nwa; + + + /* --- Vreixo's part --- */ + + /* The options for reading the old image. */ + /* target_ropts.size will contain the number of blocks of the image. */ + struct ecma119_read_opts *target_ropts; + + /* Buffered ISO head from media (should that become part of ecma119_read_opts ?) */ + uint8_t target_iso_head[65536]; + + /* The filesystem structure of the old image from media. */ + struct volset *target_volset; + + /* The output options of the current run of libisofs. */ + /* Element .overwrite eventually points to a buffered new head */ + /* with size fields describing the new size alone, not the */ + /* new combined size counted from block 0. */ + /* (This head is to be merged with above target_iso_head.) */ + struct ecma119_source_opts *new_wopts; + + +}; + + +/* Creation and disposal function */ +int isoburn_new(struct isoburn **objpt, int flag); +int isoburn_destroy(struct isoburn **objpt, int flag); + +/* Eventual readers for public attributes */ +/* ( put into separate .h file then ) */ +int isoburn_get_emulation_mode(struct isoburn *o, int *pt, int flag); +int isoburn_get_target_volset(struct isoburn *o, struct volset **pt, int flag); + +/* List management */ +int isoburn_get_prev(struct isoburn *o, struct isoburn **pt, int flag); +int isoburn_get_next(struct isoburn *o, struct isoburn **pt, int flag); +int isoburn_destroy_all(struct isoburn **objpt, int flag); +int isoburn_link(struct isoburn *o, struct isoburn *link, int flag); +int isoburn_count(struct isoburn *o, int flag); +int isoburn_by_idx(struct isoburn *o, int idx, struct isoburn **pt, int flag); +int isoburn_find_by_drive(struct isoburn **pt, struct burn_drive *d, int flag); + +/* Non API inner interfaces */ +int isoburn_start_emulation(struct isoburn *o, int flag); +int isoburn_new_rwopts(struct isoburn *o); +int isoburn_free_rwopts(struct isoburn *o); +int isoburn_invalidate_iso(struct isoburn *o, int flag); + +#endif /* Isoburn_includeD */ + diff --git a/libisoburn/isofs_wrap.c b/libisoburn/isofs_wrap.c new file mode 100644 index 00000000..fa11cedc --- /dev/null +++ b/libisoburn/isofs_wrap.c @@ -0,0 +1,91 @@ + +/* + cc -g -c isofs_wrap.c +*/ + +/* + libisofs related functions of libisoburn. + + Copyright 2007 Vreixo Formoso Lopez +*/ + + +/* Vreixo: + + This is now all yours. My text here is only a snapshot + of what i think we discussed in the last days. + + If you change the prototypes of the functions listed + in this initial stub, then you have to change isoburn.h + and eventually libisoburn.h. And you have to tell me so + i can adjust burn_wrap.c . + +*/ + + +/* API function. See libisoburn.h +*/ +int isoburn_update_iso_descriptors(struct burn_drive *drive) +{ + + /* >>> code <<< */ + +} + + +/** Allocate and initialize memory for libisofs related objects in + struct isoburn. + @param o A freshly created isoburn object with NULL pointers + @return <=0 error , 1 = success +*/ +int isoburn_new_rwopts(struct isoburn *o) +{ + + /* >>> code <<< */ + +} + + +/** Dispose memory objects created by isoburn_new_rwopts(). This function + expect that the pointers in struct isoburn might still be NULL, i.e. + that isoburn_new_rwopts() was not called before. + @return <=0 error , 1 = success +*/ +int isoburn_free_rwopts(struct isoburn *o) +{ + + /* >>> code <<< */ + +} + + +/** Initialize the emulation of multi-session on random access media. + The need for emulation is confirmed already. + @param o A freshly created isoburn object. isoburn_new_rwopts() was + already called, nevertheless. + @return <=0 error , 1 = success +*/ +int isoburn_start_emulation(struct isoburn *o, int flag) +{ + + /* >>> code <<< */ + +} + + +/** Reads, alters and writes the first 64 kB of a "media" to invalidate + an ISO image. (It shall stay restorable by skilled humans, though). + The result shall especially keep libisofs from accepting the media + image as ISO filesystem. + @param o A fully activated isoburn object. isoburn_start_emulation() + was already called. + @return <=0 error , 1 = success +*/ +int isoburn_invalidate_iso(struct isoburn *o, int flag) +{ + + /* >>> code <<< */ + +} + + diff --git a/libisoburn/libisoburn.h b/libisoburn/libisoburn.h new file mode 100644 index 00000000..c19da166 --- /dev/null +++ b/libisoburn/libisoburn.h @@ -0,0 +1,157 @@ + +/* + API definition of libisoburn. + + Copyright 2007 Vreixo Formoso Lopez + and Thomas Schmitt +*/ + +/** + +libisoburn is a frontend for libraries libburn and libisofs which enables +creation and expansion of ISO-9660 filesystems on all CD/DVD media supported +by libburn. This includes media like DVD+RW, which do not support multi-session +management on media level +>>> to come: and even plain disk files or other random access file types. + +The price for that is thorough specialization on data files in ISO-9660 +filesystem images. So libisoburn is not suitable for audio (CD-DA) or any +other CD layout which does not entirely consist of ISO-9660 sessions. + +The priciple of this frontend is that you may use any call of libisofs or +libburn unless it has a isoburn_*() wrapper listed in the following function +idocumentation. +E.g. call isoburn_initialize() rather than iso_init(); burn_initialize() +and call isoburn_drive_scan_and_grab() rather than burn_drive_scan_and_grab(). +But you may call burn_disc_get_profile() directly if you want to display +the media type. + +The usage model is like with libburn: the target is a "media" in a "drive". +The wrappers will transparently provide the necessary emulations which +are appropriate for particular target "drives". + +>>> Technical remark: +>>> For full support of plain files, libburn needs to get a null-drive +>>> which swallows all libburn calls which are not wrapped in isoburn calls. +>>> I had a count: ~ 50 API calls with struct burn_drive or +>>> struct burn_write_opts to curb :)) + +*/ + + + /* API functions */ + + +/** Initialize libisoburn, libisofs and libburn. + Wrapper for : iso_init() and burn_initialize() + @return 1 indicates success, 0 is failure +*/ +int isoburn_initialize(void); + + +/** Aquire a target drive by its filesystem path resp. libburn persistent + address. + Wrapper for: burn_drive_scan_and_grab() +*/ +int isoburn_drive_scan_and_grab(struct burn_drive_info *drive_infos[], + char* adr, int load); + + +/** Aquire a drive from the burn_drive_info[] array which was obtained by + a previous call of burn_drive_scan(). + Wrapper for: burn_drive_grab() +*/ +int isoburn_drive_grab(struct burn_drive *drive, int load); + + +/** Inquire the media status. Expect the whole spectrum of libburn BURN_DISC_* + with multi-session media. Emulated states with random access media are + BURN_DISC_BLANK and BURN_DISC_APPENDABLE. + Wrapper for: burn_disc_get_status() +*/ +enum burn_disc_status isoburn_disc_get_status(struct burn_drive *drive); + + +/** Mark the media as blank. With multi-session media this will call + burn_disc_erase(). With random access media, an eventual ISO-9660 + filesystem will get invalidated by altering its start blocks on media. + In case of success, the media is in status BURN_DISC_BLANK afterwards. + Wrapper for: burn_disc_erase() +*/ +void isoburn_disc_erase(struct burn_drive *drive, int fast); + + +/** Obtain the start block number of the most recent session on media. In + case of random access media this will always be 0. Succesfull return is + not a guarantee that there is a ISO-9660 image at all. The call will fail, + nevertheless,if isoburn_disc_get_status() returns not BURN_DISC_APPENDABLE. + Wrapper for: burn_disc_get_msc1() +*/ +int isoburn_disc_get_msc1(struct burn_drive *d, int *start_lba); + + +/** Use this with trackno==0 to obtain the predicted start block number of the + new session. The interesting number is returned in parameter nwa. + Wrapper for: burn_disc_track_lba_nwa() +*/ +int isoburn_disc_track_lba_nwa(struct burn_drive *d, struct burn_write_opts *o, + int trackno, int *lba, int *nwa); + + +/** Start writing of the new session. + This call is asynchrounous. I.e. it returns quite soon and the progress has + to be watched by a loop with call burn_drive_get_status() until + BURN_DRIVE_IDLE is returned. + Wrapper for: burn_disc_write() +*/ +int isoburn_disc_write(struct burn_write_opts *o, struct burn_disc *disc); + + +/** Call this after isoburn_disc_write has finished and burn_drive_wrote_well() + indicates success. It will eventually complete the emulation of + multi-session functionality, if needed at all. Let libisoburn decide. + Not a wrapper, but peculiar to libburn. +*/ +int isoburn_update_iso_descriptors(struct burn_drive *drive); + + +/** Release an aquired drive. + Wrapper for: burn_drive_release() +*/ +void isoburn_drive_release(struct burn_drive *drive, int eject); + + +/** Shutdown all three libraries. + Wrapper for : iso_finish() and burn_finish(). +*/ +void isoburn_finish(void); + + +/* + The following two calls are for expert applications only. + An application should have a special reason to use them. +*/ + + +/** Inquire wether the media needs emulation or would be suitable for + generic multi-session via libburn. + @return 0 is generic multi-session + 1 is emulated multi-session + -1 is not suitable for isoburn +*/ +int isoburn_needs_emulation(struct burn_drive *drive); + + +/** Caution: Use this with great care. It is not needed normally. + + This call can set the nwa block number to an arbitrary value. If ever, do + this before preparing the session by libisofs. The drive must be grabbed, + though. This overrides the automated address computation. Call + isoburn_disc_track_lba_nwa() afterwards to learn the effective new + address which might be somewhat higher than set by parameter value. + Wrapper for: burn_write_opts_set_start_byte (if ever) +*/ +void isoburn_write_opts_set_start_byte(struct burn_write_opts *opts, + off_t value); + +