/* cc -g -c isoburn.c */ /* Class core of libisoburn. Copyright 2007 Vreixo Formoso Lopes and Thomas Schmitt */ /* ( derived from stub generated by CgeN on Sat, 01 Sep 2007 12:04:36 GMT ) */ #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" /* No more: version numbers out of configure.ac major.minor.micro now comes from libisoburn.h #include "../version.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, ret; *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; #ifdef Libisoburn_no_fifO o->iso_source= NULL; #else o->fifo= NULL; #endif o->wrote_well= -1; o->fabricated_disc_status= BURN_DISC_UNREADY; for(i=0;i<65536;i++) o->target_iso_head[i]= 0; o->image= NULL; o->prev= NULL; o->next= NULL; ret= iso_image_new("ISOIMAGE", &o->image); if(ret<0) { isoburn_report_iso_error(ret, "Cannot create image", 0, "FATAL", 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; 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->image!=NULL) iso_image_unref(o->image); #ifdef Libisoburn_no_fifO if(o->iso_source!=NULL) burn_source_free(o->iso_source); #else if(o->fifo!=NULL) burn_source_free(o->fifo); #endif /* ! Libisoburn_no_fifO */ 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_target_image(struct isoburn *o, IsoImage **pt, int flag) { *pt= o->image; 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!=NULL;o= o->next) if(o->drive==d) { *pt= o; return(1); } return(0); } static int isoburn_prepare_disc_aux(struct burn_drive *d, struct burn_disc **disc, struct isoburn_imgen_opts *opts, int new_img) { struct burn_source *wsrc; struct burn_session *session; struct burn_track *track; struct isoburn *o; IsoWriteOpts *wopts= NULL; enum burn_disc_status state; int ret, fifo_chunks; ret= isoburn_find_emulator(&o, d, 0); if(ret<0 || o==NULL) {ret= -1; goto ex;} o->wrote_well= 0; /* early end will be registered as failure */ state = isoburn_disc_get_status(d); if (state != BURN_DISC_BLANK && state != BURN_DISC_APPENDABLE && (state != BURN_DISC_FULL || ! new_img)) { /* unsuitable status */ {ret= -2; goto ex;} } fifo_chunks= 32; if(opts->fifo_size >= 64*1024 && opts->fifo_size <= 1024.0 * 1024.0 * 1024.0){ fifo_chunks= opts->fifo_size/2048; if(fifo_chunks*2048 < opts->fifo_size) fifo_chunks++; } ret = iso_write_opts_new(&wopts, 0); if (ret < 0) { isoburn_report_iso_error(ret, "Cannot create iso_write_opts", 0, "FATAL",0); goto ex; } iso_write_opts_set_iso_level(wopts, opts->level); iso_write_opts_set_rockridge(wopts, opts->rockridge); iso_write_opts_set_joliet(wopts, opts->joliet); iso_write_opts_set_iso1999(wopts, opts->iso1999); iso_write_opts_set_omit_version_numbers(wopts, opts->omit_version_numbers); iso_write_opts_set_allow_deep_paths(wopts, opts->allow_deep_paths); iso_write_opts_set_allow_longer_paths(wopts, opts->allow_longer_paths); iso_write_opts_set_max_37_char_filenames(wopts, opts->max_37_char_filenames); iso_write_opts_set_no_force_dots(wopts, opts->no_force_dots); iso_write_opts_set_allow_lowercase(wopts, opts->allow_lowercase); iso_write_opts_set_allow_full_ascii(wopts, opts->allow_full_ascii); iso_write_opts_set_joliet_longer_paths(wopts, opts->joliet_longer_paths); iso_write_opts_set_sort_files(wopts, opts->sort_files); iso_write_opts_set_replace_mode(wopts, opts->replace_dir_mode, opts->replace_file_mode, opts->replace_uid, opts->replace_gid); iso_write_opts_set_default_dir_mode(wopts, opts->dir_mode); iso_write_opts_set_default_file_mode(wopts, opts->file_mode); iso_write_opts_set_default_uid(wopts, opts->uid); iso_write_opts_set_default_gid(wopts, opts->gid); iso_write_opts_set_output_charset(wopts, opts->output_charset); #ifdef Libisoburn_no_fifO iso_write_opts_set_fifo_size(wopts, fifo_chunks); #endif /* Libisoburn_no_fifO */ if (new_img) { iso_write_opts_set_ms_block(wopts, 0); iso_write_opts_set_appendable(wopts, 0); iso_write_opts_set_overwrite_buf(wopts, NULL); } else { int lba, nwa; ret = isoburn_disc_track_lba_nwa(d, NULL, 0, &lba, &nwa); if (ret != 1) {ret= -3; goto ex;} if (nwa == 0 && state == BURN_DISC_APPENDABLE) { /* invalid nwa */ {ret= -4; goto ex;} } iso_write_opts_set_ms_block(wopts, nwa); iso_write_opts_set_appendable(wopts, 1); iso_write_opts_set_overwrite_buf(wopts, o->target_iso_head); } ret = iso_image_create_burn_source(o->image, wopts, &wsrc); if (ret < 0) { isoburn_report_iso_error(ret, "Cannot create burn source", 0, "FAILURE", 0); {ret= -1; goto ex;} } /* TODO check return values for failure. propertly clean-up on error */ #ifdef Libisoburn_no_fifO o->iso_source= wsrc; #else o->fifo = burn_fifo_source_new(wsrc, 2048, fifo_chunks, 0); burn_source_free(wsrc); if (o->fifo == NULL) { fprintf(stderr, "Cannot attach fifo\n"); {ret= -1; goto ex;} } #endif /* ! Libisoburn_no_fifO */ *disc = burn_disc_create(); session = burn_session_create(); burn_disc_add_session(*disc, session, BURN_POS_END); track = burn_track_create(); #ifdef Libisoburn_no_fifO burn_track_set_source(track, o->iso_source); #else burn_track_set_source(track, o->fifo); #endif /* ! Libisoburn_no_fifO */ burn_session_add_track(session, track, BURN_POS_END); /* give up local references */ burn_track_free(track); burn_session_free(session); o->wrote_well= -1; /* neutral */ ret= 1; ex: if(wopts!=NULL) {iso_write_opts_free(wopts); wopts= NULL;} return ret; } int isoburn_prepare_disc(struct burn_drive *d, struct burn_disc **disc, struct isoburn_imgen_opts *opts) { return isoburn_prepare_disc_aux(d, disc, opts, 0); } int isoburn_prepare_new_image(struct burn_drive *d, struct burn_disc **disc, struct isoburn_imgen_opts *opts, struct burn_drive *out_drive) { int ret; struct isoburn *in_o, *out_o; ret= isoburn_prepare_disc_aux(d, disc, opts, 1); if (ret<=0) return ret; #ifdef Libisoburn_no_fifO /* Hand over source reference for optional fifo status inquiry */ if(out_drive==NULL) return 1; ret= isoburn_find_emulator(&out_o, out_drive, 0); if(ret<0 || out_o==NULL) return 1; ret= isoburn_find_emulator(&in_o, d, 0); if(ret<0 || in_o==NULL) return 1; /* then without fifo status inquiry */ if(out_o->iso_source!=NULL) burn_source_free(out_o->iso_source); out_o->iso_source= in_o->iso_source; in_o->iso_source= NULL; #endif /* Libisoburn_no_fifO */ return 1; } void isoburn_version(int *major, int *minor, int *micro) { *major= isoburn_header_version_major; *minor= isoburn_header_version_minor; *micro= isoburn_header_version_micro; /* No more: values from version.h generated from version.h.in and macro values defined in configure.ac *major = ISOBURN_MAJOR_VERSION; *minor = ISOBURN_MINOR_VERSION; *micro = ISOBURN_MICRO_VERSION; */ } int isoburn_is_compatible(int major, int minor, int micro, int flag) { int own_major, own_minor, own_micro; isoburn_version(&own_major, &own_minor, &own_micro); return(own_major > major || (own_major == major && (own_minor > minor || (own_minor == minor && own_micro >= micro)))); } /* ----------------------------------------------------------------------- */ /* Options for image reading. */ /* ----------------------------------------------------------------------- */ int isoburn_ropt_new(struct isoburn_read_opts **new_o, int flag) { struct isoburn_read_opts *o; o= (*new_o)= calloc(1, sizeof(struct isoburn_read_opts)); if(o==NULL) return(-1); o->norock= 0; o->nojoliet= 0; o->noiso1999= 1; o->preferjoliet= 0; o->uid= geteuid(); o->gid= getegid(); o->mode= 0444; o->dirmode= 0555; o->input_charset= NULL; o->hasRR= 0; o->hasJoliet= 0; o->hasIso1999= 0; o->hasElTorito= 0; o->size= 0; o->pretend_blank= 1; return(1); } int isoburn_ropt_destroy(struct isoburn_read_opts **o, int flag) { if(*o==NULL) return(0); free(*o); *o= NULL; return(1); } int isoburn_ropt_set_extensions(struct isoburn_read_opts *o, int ext) { o->norock= !!(ext&1); o->nojoliet= !!(ext&2); o->noiso1999= !!(ext&4); o->preferjoliet= !!(ext&8); o->pretend_blank= !!(ext&16); return(1); } int isoburn_ropt_get_extensions(struct isoburn_read_opts *o, int *ext) { *ext= (!!o->norock) | ((!!o->nojoliet)<<1) | ((!!o->noiso1999)<<2) | ((!!o->preferjoliet)<<3) | ((!!o->pretend_blank)<<4); return(1); } int isoburn_ropt_set_default_perms(struct isoburn_read_opts *o, uid_t uid, gid_t gid, mode_t mode) { mode_t dirmode; o->uid= uid; o->gid= gid; o->mode= mode; dirmode= mode; if(dirmode & S_IRUSR) dirmode|= S_IXUSR; if(dirmode & S_IRGRP) dirmode|= S_IXGRP; if(dirmode & S_IROTH) dirmode|= S_IXOTH; o->dirmode= dirmode; return(1); } int isoburn_ropt_get_default_perms(struct isoburn_read_opts *o, uid_t *uid, gid_t *gid, mode_t *mode) { *uid= o->uid; *gid= o->gid; *mode= o->mode; return(1); } int isoburn_ropt_set_default_dirperms(struct isoburn_read_opts *o, mode_t mode) { o->dirmode= mode; return(1); } int isoburn_ropt_get_default_dirperms(struct isoburn_read_opts *o, mode_t *mode) { *mode= o->dirmode; return(1); } int isoburn_ropt_set_input_charset(struct isoburn_read_opts *o, char *input_charset) { o->input_charset= input_charset; return(1); } int isoburn_igopt_get_in_charset(struct isoburn_read_opts *o, char **input_charset) { *input_charset= o->input_charset; return(1); } int isoburn_ropt_get_size_what(struct isoburn_read_opts *o, uint32_t *size, int *has_what) { *size= o->size; *has_what= (!!o->hasRR) | ((!!o->hasJoliet)<<1) | ((!!o->hasIso1999)<<2) | ((!!o->hasElTorito)<<3); return(1); } /* ----------------------------------------------------------------------- */ /* Options for image generation by libisofs and image transport to libburn. */ /* ----------------------------------------------------------------------- */ int isoburn_igopt_new(struct isoburn_imgen_opts **new_o, int flag) { struct isoburn_imgen_opts *o; o= (*new_o)= calloc(1, sizeof(struct isoburn_imgen_opts)); if(o==NULL) return(-1); o->level= 2; o->rockridge= 1; o->joliet= 0; o->iso1999= 0; o->omit_version_numbers= 0; o->allow_deep_paths= 1; o->allow_longer_paths= 0; o->max_37_char_filenames= 0; o->no_force_dots= 0; o->allow_lowercase= 0; o->allow_full_ascii= 0; o->joliet_longer_paths= 0; o->sort_files= 0; o->replace_dir_mode= 0; o->replace_file_mode= 0; o->replace_uid= 0; o->replace_gid= 0; o->dir_mode= 0555; o->file_mode= 0444; o->uid= 0; o->gid= 0; o->output_charset= 0; o->fifo_size= 4*1024*1024; return(1); } int isoburn_igopt_destroy(struct isoburn_imgen_opts **o, int flag) { if(*o==NULL) return(0); free(*o); *o= NULL; return(1); } int isoburn_igopt_set_level(struct isoburn_imgen_opts *o, int level) { o->level= level; return(1); } int isoburn_igopt_get_level(struct isoburn_imgen_opts *o, int *level) { *level= o->level; return(1); } int isoburn_igopt_set_extensions(struct isoburn_imgen_opts *o, int ext) { o->rockridge= !!(ext&1); o->joliet= !!(ext&2); o->iso1999= !!(ext&4); return(1); } int isoburn_igopt_get_extensions(struct isoburn_imgen_opts *o, int *ext) { *ext= (!!o->rockridge) | ((!!o->joliet)<<1) | ((!!o->iso1999)<<2); return(1); } int isoburn_igopt_set_relaxed(struct isoburn_imgen_opts *o, int relax) { o->omit_version_numbers= !!(relax&1); o->allow_deep_paths= !!(relax&2); o->allow_longer_paths= !!(relax&4); o->max_37_char_filenames= !!(relax&8); o->no_force_dots= !!(relax&16); o->allow_lowercase= !!(relax&32); o->allow_full_ascii= !!(relax&64); o->joliet_longer_paths= !!(relax&128); return(1); } int isoburn_igopt_get_relaxed(struct isoburn_imgen_opts *o, int *relax) { *relax= (!!o->omit_version_numbers) | ((!!o->allow_deep_paths)<<1) | ((!!o->allow_longer_paths)<<2) | ((!!o->max_37_char_filenames)<<3) | ((!!o->no_force_dots)<<4) | ((!!o->allow_lowercase)<<5) | ((!!o->allow_full_ascii)<<6) | ((!!o->joliet_longer_paths)<<7); return(1); } int isoburn_igopt_set_sort_files(struct isoburn_imgen_opts *o, int value) { o->sort_files= !!(value&1); return(1); } int isoburn_igopt_get_sort_files(struct isoburn_imgen_opts *o, int *value) { *value= !!o->sort_files; return(1); } int isoburn_igopt_set_over_mode(struct isoburn_imgen_opts *o, int replace_dir_mode, int replace_file_mode, mode_t dir_mode, mode_t file_mode) { o->replace_dir_mode= replace_dir_mode%3; o->replace_file_mode= replace_file_mode%3; o->dir_mode= dir_mode; o->file_mode= file_mode; return(1); } int isoburn_igopt_get_over_mode(struct isoburn_imgen_opts *o, int *replace_dir_mode, int *replace_file_mode, mode_t *dir_mode, mode_t *file_mode) { *replace_dir_mode= o->replace_dir_mode%3; *replace_file_mode= o->replace_file_mode%3; *dir_mode= o->dir_mode; *file_mode= o->file_mode; return(1); } int isoburn_igopt_set_over_ugid(struct isoburn_imgen_opts *o, int replace_uid, int replace_gid, uid_t uid, gid_t gid) { o->replace_uid= replace_uid%3; o->replace_gid= replace_gid%3; o->uid= uid; o->gid= gid; return(1); } int isoburn_igopt_get_over_ugid(struct isoburn_imgen_opts *o, int *replace_uid, int *replace_gid, uid_t *uid, gid_t *gid) { *replace_uid= o->replace_uid%3; *replace_gid= o->replace_gid%3; *uid= o->uid; *gid= o->gid; return(1); } int isoburn_igopt_set_out_charset(struct isoburn_imgen_opts *o, char *output_charset) { o->output_charset= output_charset; return(1); } int isoburn_igopt_get_out_charset(struct isoburn_imgen_opts *o, char **output_charset) { *output_charset= o->output_charset; return(1); } int isoburn_igopt_set_fifo_size(struct isoburn_imgen_opts *o, int fifo_size) { o->fifo_size= fifo_size; return(1); } int isoburn_igopt_get_fifo_size(struct isoburn_imgen_opts *o, int *fifo_size) { *fifo_size= o->fifo_size; return(1); }