/* 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 #include /* >>> NG */ #include #include "libisoburn.h" #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, 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; o->fifo= NULL; 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("NEW", &o->image); if(ret<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); if(o->fifo!=NULL) burn_source_free(o->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_source_opts *opts, int new_img) { struct burn_source *wsrc; struct burn_session *session; struct burn_track *track; struct isoburn *o; Ecma119WriteOpts wopts; enum burn_disc_status state; int ret, chunks; ret= isoburn_find_emulator(&o, d, 0); if(ret<0 || o==NULL) return -1; 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 */ return -2; } memset((char *) &wopts, 0, sizeof(wopts)); wopts.level = opts->level; wopts.rockridge = opts->rockridge; wopts.joliet = opts->joliet; wopts.omit_version_numbers = opts->omit_version_numbers; wopts.allow_deep_paths = opts->allow_deep_paths; wopts.max_37_char_filenames = opts->max_37_char_filenames; wopts.no_force_dots = opts->no_force_dots; wopts.allow_lowercase = opts->allow_lowercase; wopts.allow_full_ascii = opts->allow_full_ascii; wopts.joliet_longer_paths = opts->joliet_longer_paths; /* wopts.copy_eltorito = opts->copy_eltorito; */ wopts.sort_files = opts->sort_files; wopts.replace_dir_mode = opts->replace_dir_mode; wopts.replace_file_mode = opts->replace_file_mode; wopts.replace_uid = opts->replace_uid; wopts.replace_gid = opts->replace_gid; wopts.dir_mode = opts->dir_mode; wopts.file_mode = opts->file_mode; wopts.gid = opts->gid; wopts.uid = opts->uid; wopts.output_charset = opts->output_charset; if (new_img) { wopts.ms_block = 0; wopts.appendable = 0; wopts.overwrite = NULL; } else { int lba, nwa; ret = isoburn_disc_track_lba_nwa(d, NULL, 0, &lba, &nwa); if (ret != 1) return -3; if (nwa == 0 && state == BURN_DISC_APPENDABLE) { /* invalid nwa */ return -4; } wopts.ms_block = nwa; wopts.appendable = 1; wopts.overwrite = o->target_iso_head; } ret = iso_image_create_burn_source(o->image, &wopts, &wsrc); if (ret < 0) return -1; /* TODO check return values for failure. propertly clean-up on error */ chunks= 32; if(opts->fifo_size >= 64*1024 && opts->fifo_size <= 1024.0 * 1024.0 * 1024.0){ chunks= opts->fifo_size/2048; if(chunks*2048 < opts->fifo_size) chunks++; } o->fifo = burn_fifo_source_new(wsrc, 2048, chunks, 0); burn_source_free(wsrc); if (o->fifo == NULL) { fprintf(stderr, "Cannot attach fifo\n"); return -1; } *disc = burn_disc_create(); session = burn_session_create(); burn_disc_add_session(*disc, session, BURN_POS_END); track = burn_track_create(); burn_track_set_source(track, o->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 */ return 1; } int isoburn_prepare_disc(struct burn_drive *d, struct burn_disc **disc, struct isoburn_source_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_source_opts *opts) { return isoburn_prepare_disc_aux(d, disc, opts, 1); }