/* cc -g -c isoburn.c */ /* Class core of libisoburn. Copyright 2007 - 2012 Vreixo Formoso Lopes Thomas Schmitt Provided under GPL version 2 or later. */ #ifdef HAVE_CONFIG_H #include "../config.h" #endif /* ( 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" /* Default values for application provided msgs_submit methods. To be attached to newly aquired drives. */ int (*libisoburn_default_msgs_submit) (void *handle, int error_code, char msg_text[], int os_errno, char severity[], int flag)= NULL; void *libisoburn_default_msgs_submit_handle= NULL; int libisoburn_default_msgs_submit_flag= 0; /* ----------------------- isoburn_toc_entry ---------------------- */ int isoburn_toc_entry_new(struct isoburn_toc_entry **objpt, struct isoburn_toc_entry *boss, int flag) { struct isoburn_toc_entry *o, *s; *objpt= o= (struct isoburn_toc_entry *) malloc(sizeof(struct isoburn_toc_entry)); if(o==NULL) { isoburn_msgs_submit(NULL, 0x00060000, "Cannot allocate memory for isoburn toc entry", 0, "FATAL", 0); return(-1); } o->session= 0; o->track_no= 0; o->start_lba= -1; o->track_blocks= 0; o->volid= NULL; o->next= NULL; if(boss!=NULL) { for(s= boss; s->next!=NULL; s= s->next); s->next= o; } return(1); } /* @param flag bit0= delete all subordinates too */ int isoburn_toc_entry_destroy(struct isoburn_toc_entry **o, int flag) { if(*o==NULL) return(0); if(flag&1) isoburn_toc_entry_destroy(&((*o)->next), flag); if((*o)->volid != NULL) free((*o)->volid); free((char *) (*o)); *o= NULL; return(1); } /* --------------------- end isoburn_toc_entry -------------------- */ /* -------------------------- 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 ret; *objpt= o= (struct isoburn *) malloc(sizeof(struct isoburn)); if(o==NULL) { isoburn_msgs_submit(NULL, 0x00060000, "Cannot allocate memory for isoburn control object", 0, "FATAL", 0); return(-1); } o->drive= NULL; o->emulation_mode= 0; o->fabricated_msc1= -1; o->fabricated_msc2= -1; o->zero_nwa= Libisoburn_overwriteable_starT; o->min_start_byte= o->zero_nwa * 2048; o->nwa= o->zero_nwa; o->truncate= 0; o->iso_source= NULL; o->fabricated_disc_status= BURN_DISC_UNREADY; o->media_read_error= 0; o->toc= NULL; o->wrote_well= -1; o->loaded_partition_offset= 0; o->target_iso_head_size= Libisoburn_target_head_sizE; o->target_iso_head= NULL; o->image= NULL; o->image_start_lba= -1; o->iso_data_source= NULL; o->read_pacifier= NULL; o->read_pacifier_handle= NULL; o->msgs_submit= NULL; o->msgs_submit_handle= NULL; o->msgs_submit_flag= 0; o->prev= NULL; o->next= NULL; o->target_iso_head= calloc(1, o->target_iso_head_size); if(o->target_iso_head == NULL) { isoburn_report_iso_error(ISO_OUT_OF_MEM, "Cannot allocate overwrite buffer", 0, "FATAL", 0); goto failed; } ret= iso_image_new("ISOIMAGE", &o->image); if(ret<0) { isoburn_report_iso_error(ret, "Cannot create image object", 0, "FATAL", 0); goto failed; } ret= isoburn_root_defaults(o->image, 0); 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->toc!=NULL) isoburn_toc_entry_destroy(&(o->toc), 1); /* all */ if(o->iso_source!=NULL) burn_source_free(o->iso_source); if(o->iso_data_source!=NULL) iso_data_source_unref(o->iso_data_source); if(o->target_iso_head != NULL) free(o->target_iso_head); 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); } int isoburn_msgs_submit(struct isoburn *o, int error_code, char msg_text[], int os_errno, char severity[], int flag) { int ret, use_drive_method= 0; if(o!=NULL) if(o->msgs_submit!=NULL) use_drive_method= 1; if(use_drive_method) { ret= o->msgs_submit(o->msgs_submit_handle, error_code, msg_text, os_errno, severity, o->msgs_submit_flag); return(ret); } if(libisoburn_default_msgs_submit != NULL) { ret= libisoburn_default_msgs_submit(libisoburn_default_msgs_submit_handle, error_code, msg_text, os_errno, severity, libisoburn_default_msgs_submit_flag); return(ret); } /* Fallback: use message queue of libburn */ burn_msgs_submit(error_code, msg_text, os_errno, severity, NULL); return(1); } /** Check whether the size of target_iso_head matches the given partition offset. Eventually adjust size. */ int isoburn_adjust_target_iso_head(struct isoburn *o, uint32_t offst, int flag) { uint8_t *new_buf; uint32_t new_size; if((uint32_t) o->target_iso_head_size == Libisoburn_target_head_sizE + 2048 * offst) return(1); new_size= Libisoburn_target_head_sizE + 2048 * offst; new_buf= calloc(1, new_size); if(new_buf == NULL) { isoburn_msgs_submit(o, 0x00060000, "Cannot re-allocate overwrite buffer", 0, "FATAL", 0); return(-1); } memcpy(new_buf, o->target_iso_head, (uint32_t) o->target_iso_head_size < new_size ? (uint32_t) o->target_iso_head_size : new_size); free(o->target_iso_head); o->target_iso_head= new_buf; o->target_iso_head_size= new_size; if(o->nwa == o->zero_nwa) o->nwa= Libisoburn_overwriteable_starT + offst; o->zero_nwa= Libisoburn_overwriteable_starT + offst; return(1); } /* @param flag bit0= modifying rather than growing bit1= prepare for early release of input drive: wait until input and then disable image data source */ static int isoburn_prepare_disc_aux(struct burn_drive *in_d, struct burn_drive *out_d, struct burn_disc **disc, struct isoburn_imgen_opts *opts, int flag) { struct burn_source *wsrc; struct burn_session *session; struct burn_track *track; struct isoburn *in_o, *out_o; IsoWriteOpts *wopts= NULL; enum burn_disc_status state; int ret, fifo_chunks, lba, nwa, i, new_img, early_indev_release, rec_mtime; uint32_t data_start= -1; size_t buffer_size= 0, buffer_free= 0; char *msg= NULL; msg= calloc(1, 160); if(msg == NULL) {ret= -1; goto ex;} new_img= flag&1; early_indev_release= flag&2; ret= isoburn_find_emulator(&in_o, in_d, 0); if(ret<0 || in_o==NULL) {ret= -1; goto ex;} ret= isoburn_find_emulator(&out_o, out_d, 0); if(ret<0 || out_o==NULL) {ret= -1; goto ex;} /* early end will be registered as failure */ in_o->wrote_well= out_o->wrote_well= 0; if(new_img && early_indev_release) { isoburn_msgs_submit(in_o, 0x00060000, "Programming error: Wrong session setup: new_img && early_indev_release", 0, "FATAL", 0); {ret= -4; goto ex;} } state = isoburn_disc_get_status(in_d); if (state != BURN_DISC_BLANK && state != BURN_DISC_APPENDABLE && state != BURN_DISC_FULL) { isoburn_msgs_submit(in_o, 0x00060000, "Unsuitable source media state", 0, "FAILURE", 0); {ret= -2; goto ex;} } state = isoburn_disc_get_status(out_d); if (state != BURN_DISC_BLANK && state != BURN_DISC_APPENDABLE) { isoburn_msgs_submit(out_o, 0x00060000, "Unsuitable target media state", 0, "FAILURE", 0); {ret= -2; goto ex;} } if (state != BURN_DISC_BLANK && opts->libjte_handle != NULL) { isoburn_msgs_submit(out_o, 0x00060000, "Jigdo Template Extraction works only on blank target media", 0, "FAILURE", 0); {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_will_cancel(wopts, opts->will_cancel); 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_hfsplus(wopts, opts->hfsplus); iso_write_opts_set_fat(wopts, opts->fat); iso_write_opts_set_iso1999(wopts, opts->iso1999); iso_write_opts_set_hardlinks(wopts, opts->hardlinks); if(opts->hardlinks) iso_write_opts_set_rrip_1_10_px_ino(wopts, 1); iso_write_opts_set_aaip(wopts, opts->aaip); iso_write_opts_set_old_empty(wopts, !!opts->old_empty); iso_write_opts_set_untranslated_name_len(wopts, opts->untranslated_name_len); iso_write_opts_set_allow_dir_id_ext(wopts, opts->allow_dir_id_ext); 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_rr_reloc(wopts, opts->rr_reloc_dir, opts->rr_reloc_flags); 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_allow_7bit_ascii(wopts, opts->allow_7bit_ascii); iso_write_opts_set_relaxed_vol_atts(wopts, 1); iso_write_opts_set_joliet_longer_paths(wopts, opts->joliet_longer_paths); iso_write_opts_set_joliet_long_names(wopts, opts->joliet_long_names); iso_write_opts_set_always_gmt(wopts, opts->always_gmt); iso_write_opts_set_rrip_version_1_10(wopts, opts->rrip_version_1_10); rec_mtime= 0; if(opts->dir_rec_mtime) rec_mtime|= 1; else rec_mtime|= (1 << 14); if(opts->joliet_rec_mtime) rec_mtime|= 2; if(opts->iso1999_rec_mtime) rec_mtime|= 4; iso_write_opts_set_dir_rec_mtime(wopts, rec_mtime); iso_write_opts_set_aaip_susp_1_10(wopts, opts->aaip_susp_1_10); iso_write_opts_set_sort_files(wopts, opts->sort_files); iso_write_opts_set_record_md5(wopts, opts->session_md5, opts->file_md5 & 3); if(opts->scdbackup_tag_name[0] && opts->scdbackup_tag_time[0]) iso_write_opts_set_scdbackup_tag(wopts, opts->scdbackup_tag_name, opts->scdbackup_tag_time, opts->scdbackup_tag_written); 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); iso_write_opts_set_fifo_size(wopts, fifo_chunks); ret = iso_write_opts_set_system_area(wopts, opts->system_area_data, opts->system_area_options, 0); if (ret < 0) { isoburn_report_iso_error(ret, "Cannot set content of System Area", 0, "FAILURE", 0); {ret= -1; goto ex;} } iso_write_opts_set_pvd_times(wopts, opts->vol_creation_time, opts->vol_modification_time, opts->vol_expiration_time, opts->vol_effective_time, opts->vol_uuid); iso_write_opts_attach_jte(wopts, opts->libjte_handle); iso_write_opts_set_hfsp_serial_number(wopts, opts->hfsp_serial_number); ret= isoburn_adjust_target_iso_head(out_o, opts->partition_offset, 0); if(ret <= 0) {ret= -1; goto ex;} if(out_o->nwa < out_o->zero_nwa) out_o->zero_nwa= 0; if(opts->no_emul_toc || opts->libjte_handle != NULL) { if(out_o->nwa == out_o->zero_nwa && out_o->zero_nwa == Libisoburn_overwriteable_starT + opts->partition_offset && out_o->emulation_mode == 1) { out_o->nwa= 0; out_o->zero_nwa= 0; out_o->min_start_byte= 0; } } ret = isoburn_disc_track_lba_nwa(out_d, NULL, 0, &lba, &nwa); opts->effective_lba= nwa; ret= isoburn_get_msc2(out_o, NULL, &nwa, 0); if (ret != 1) { isoburn_msgs_submit(out_o, 0x00060000, "Cannot determine next writeable address", 0, "FAILURE", 0); /* >>> NWA_V : If burn_next_track_damaged: ??? Close track and session ? ??? Issue a hint for a repair command ? */; {ret= -3; goto ex;} } iso_write_opts_set_ms_block(wopts, nwa); iso_write_opts_set_appendable(wopts, !new_img); iso_write_opts_set_overwrite_buf(wopts, nwa>0 ? out_o->target_iso_head : NULL); iso_write_opts_set_part_offset(wopts, opts->partition_offset, opts->partition_secs_per_head, opts->partition_heads_per_cyl); iso_write_opts_set_tail_blocks(wopts, opts->tail_blocks); if(opts->prep_partition != NULL) { ret = iso_write_opts_set_prep_img(wopts, opts->prep_partition, 0); if(ret < 0) { isoburn_report_iso_error(ret, "Cannot set path for PreP partition", 0, "FAILURE", 0); {ret= -1; goto ex;} } } if(opts->efi_boot_partition != NULL) { ret = iso_write_opts_set_efi_bootp(wopts, opts->efi_boot_partition, 0); if(ret < 0) { isoburn_report_iso_error(ret, "Cannot set path for EFI system partition", 0, "FAILURE", 0); {ret= -1; goto ex;} } } for(i= 0; i < Libisoburn_max_appended_partitionS; i++) { if(opts->appended_partitions[i] == NULL) continue; ret= iso_write_opts_set_partition_img(wopts, i + 1, opts->appended_part_types[i], opts->appended_partitions[i], 0); if(ret < 0) { isoburn_report_iso_error(ret, "Cannot set path for appended partition", 0, "FAILURE", 0); {ret= -1; goto ex;} } } iso_write_opts_set_disc_label(wopts, opts->ascii_disc_label); ret = iso_image_create_burn_source(in_o->image, wopts, &wsrc); if (ret < 0) { isoburn_report_iso_error(ret, "Cannot create burn source", 0, "FAILURE", 0); {ret= -1; goto ex;} } if (early_indev_release) { for(i= 0; i<300; i++) { /* <<< ??? */ if((i%30) == 0) { sprintf(msg, "Waiting for data in fifo since %d seconds", i/30); isoburn_msgs_submit(in_o, 0x00060000, msg, 0, "DEBUG", 0); } usleep(100000); ret= iso_ring_buffer_get_status(wsrc, &buffer_size, &buffer_free); if(ret >0 && buffer_size != buffer_free) break; } /* <<< ??? */ sprintf(msg, "After %.1f seconds: %d bytes of output available (fifo state=%d)", ((double) i+1) / 10.0, (int) (buffer_size - buffer_free), ret); isoburn_msgs_submit(in_o, 0x00060000, msg, 0, "DEBUG", 0); if(in_o->iso_data_source!=NULL) isoburn_data_source_shutdown(in_o->iso_data_source, 0); } ret= iso_write_opts_get_data_start(wopts, &data_start, 0); opts->data_start_lba= -1; if(ret > 0 && data_start <= 0x7FFFFFFF) opts->data_start_lba= data_start; /* TODO check return values for failure. propertly clean-up on error */ out_o->iso_source= wsrc; *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, out_o->iso_source); burn_session_add_track(session, track, BURN_POS_END); /* give up local references */ burn_track_free(track); burn_session_free(session); in_o->wrote_well= out_o->wrote_well= -1; /* neutral */ ret= 1; ex: if(wopts!=NULL) {iso_write_opts_free(wopts); wopts= NULL;} if(msg != NULL) free(msg); 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, 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; ret= isoburn_prepare_disc_aux(d, out_drive, disc, opts, 1); if (ret<=0) return ret; return 1; } /* API since 0.2.2 */ int isoburn_prepare_blind_grow(struct burn_drive *d, struct burn_disc **disc, struct isoburn_imgen_opts *opts, struct burn_drive *out_drive, int nwa) { int ret; struct isoburn *o= NULL; ret= isoburn_find_emulator(&o, out_drive, 0); if(ret<0 || o==NULL) return(-1); if(nwa >= 0) o->fabricated_msc2= nwa; if(o->nwa == o->zero_nwa) o->nwa= o->zero_nwa= 0; else o->zero_nwa= 0; o->min_start_byte= 0; ret= isoburn_prepare_disc_aux(d, out_drive, disc, opts, 2); if (ret<=0) return ret; return(1); } /* API @since 0.1.0 @param flag bit0= this is a regular end, not an abort give up source reference */ int isoburn_cancel_prepared_write(struct burn_drive *d, struct burn_drive *output_drive, int flag) { int ret; struct isoburn *o= NULL; if(output_drive!=NULL) { ret= isoburn_find_emulator(&o, output_drive, 0); if(ret<0 || o==NULL) o= NULL; else if(o->iso_source==NULL) o= NULL; } if(o==NULL) { ret= isoburn_find_emulator(&o, d, 0); if(ret<0) return(-1); if(o==NULL) return(0); if(o->iso_source==NULL) return(0); } if(o->iso_source->read!=NULL) return(0); if(o->iso_source->version<1) return(0); o->iso_source->cancel(o->iso_source); burn_source_free(o->iso_source); o->iso_source= NULL; return(1); } /* API @since 0.1.0 */ int isoburn_sync_after_write(struct burn_drive *d, struct burn_drive *output_drive, int flag) { return isoburn_cancel_prepared_write(d, output_drive, 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) { isoburn_msgs_submit(NULL, 0x00060000, "Cannot allocate memory for read options", 0, "FATAL", 0); return(-1); } o->cache_tiles= Libisoburn_default_cache_tileS; o->cache_tile_blocks= Libisoburn_default_tile_blockS; o->norock= 0; o->nojoliet= 0; o->noiso1999= 1; o->noaaip= 1; o->noacl= 1; o->noea= 1; o->noino= 1; o->nomd5= 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; o->displacement= 0; o->displacement_sign= 0; 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_data_cache(struct isoburn_read_opts *o, int cache_tiles, int tile_blocks, int flag) { int i; char msg[80]; if(cache_tiles < 1) { isoburn_msgs_submit(NULL, 0x00060000, "Requested number of data cache tiles is too small (< 1)", 0, "SORRY", 0); return(0); } if(((double) cache_tiles) * ((double) tile_blocks) > (double) Libisoburn_cache_max_sizE) { sprintf(msg, "Requested size of data cache exceeds limit of %.f blocks", (double) Libisoburn_cache_max_sizE); isoburn_msgs_submit(NULL, 0x00060000, msg, 0, "SORRY", 0); return(0); } for(i = 1; i <= Libisoburn_cache_max_sizE; i = i << 1) if(i == tile_blocks) break; if(i > Libisoburn_cache_max_sizE) { isoburn_msgs_submit(NULL, 0x00060000, "Requested number of blocks per data cache tiles is not a power of 2", 0, "SORRY", 0); return(0); } if(o != NULL) { o->cache_tiles= cache_tiles; o->cache_tile_blocks= tile_blocks; } return(1); } int isoburn_ropt_get_data_cache(struct isoburn_read_opts *o, int *cache_tiles, int *tile_blocks, int *set_flag, int flag) { if((flag & 1) || o == NULL) { *cache_tiles= Libisoburn_default_cache_tileS; *tile_blocks= Libisoburn_default_tile_blockS; *set_flag= 0; return(1); } *cache_tiles= o->cache_tiles; *tile_blocks= o->cache_tile_blocks; *set_flag= 0; 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); o->noaaip= !!(ext & 32); o->noacl= !!(ext & 64); o->noea= !!(ext & 128); o->noino= !!(ext & 256); o->nomd5= (ext >> 9) & 3; 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) | ((!!o->noaaip) << 5) | ((!!o->noacl) << 6) | ((!!o->noea) << 7) | ((!!o->noino) << 8) | ((o->nomd5 & 3) << 9); 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_ropt_get_input_charset(struct isoburn_read_opts *o, char **input_charset) { *input_charset= o->input_charset; return(1); } int isoburn_ropt_set_auto_incharset(struct isoburn_read_opts *o, int mode) { o->auto_input_charset= mode & 1; return(1); } int isoburn_ropt_get_auto_incharset(struct isoburn_read_opts *o, int *mode) { *mode= o->auto_input_charset; return(1); } int isoburn_ropt_set_displacement(struct isoburn_read_opts *o, uint32_t displacement, int displacement_sign) { o->displacement= displacement; o->displacement_sign= displacement_sign; return(1); } int isoburn_ropt_get_displacement(struct isoburn_read_opts *o, uint32_t *displacement, int *displacement_sign) { *displacement= o->displacement; *displacement_sign= o->displacement_sign; 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; int i; o= (*new_o)= calloc(1, sizeof(struct isoburn_imgen_opts)); if(o==NULL) { isoburn_msgs_submit(NULL, 0x00060000, "Cannot allocate memory for image generation options", 0, "FATAL", 0); return(-1); } o->level= 2; o->rockridge= 1; o->joliet= 0; o->iso1999= 0; o->hardlinks= 0; o->aaip = 0; o->session_md5= 0; o->file_md5= 0; o->no_emul_toc= 0; o->old_empty= 0; o->untranslated_name_len = 0; o->allow_dir_id_ext = 0; o->omit_version_numbers= 0; o->allow_deep_paths= 1; o->rr_reloc_dir= NULL; o->rr_reloc_flags= 0; 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->allow_7bit_ascii= 0; o->joliet_longer_paths= 0; o->joliet_long_names= 0; o->always_gmt= 0; o->rrip_version_1_10= 0; o->dir_rec_mtime= 0; o->aaip_susp_1_10= 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= NULL; o->fifo_size= 4*1024*1024; o->effective_lba= -1; o->data_start_lba= -1; o->system_area_data= NULL; o->system_area_options= 0; o->partition_offset= 0; o->partition_secs_per_head= 0; o->partition_heads_per_cyl= 0; o->vol_creation_time= 0; o->vol_modification_time= 0; o->vol_expiration_time= 0; o->vol_effective_time= 0; o->libjte_handle= NULL; o->tail_blocks= 0; o->prep_partition= NULL; o->efi_boot_partition= NULL; for(i= 0; i < Libisoburn_max_appended_partitionS; i++) { o->appended_partitions[i]= NULL; o->appended_part_types[i]= 0; } memset(o->hfsp_serial_number, 0, 8); return(1); } int isoburn_igopt_destroy(struct isoburn_imgen_opts **o, int flag) { int i; if(*o==NULL) return(0); if((*o)->rr_reloc_dir != NULL) free((*o)->rr_reloc_dir); if((*o)->prep_partition != NULL) free((*o)->prep_partition); if((*o)->efi_boot_partition != NULL) free((*o)->efi_boot_partition); for(i= 0; i < Libisoburn_max_appended_partitionS; i++) if((*o)->appended_partitions[i] != NULL) free((*o)->appended_partitions[i]); if ((*o)->system_area_data != NULL) free((*o)->system_area_data); 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); o->hardlinks= !!(ext & 8); o->aaip= !!(ext & 32); o->session_md5= !!(ext & 64); o->file_md5= (ext & (128 | 256)) >> 7; o->no_emul_toc= !!(ext & 512); o->will_cancel= !!(ext & 1024); o->old_empty= !!(ext & 2048); o->hfsplus= !!(ext & 4096); o->fat= !!(ext & 8192); return(1); } int isoburn_igopt_get_extensions(struct isoburn_imgen_opts *o, int *ext) { *ext= (!!o->rockridge) | ((!!o->joliet)<<1) | ((!!o->iso1999)<<2) | ((!!o->hardlinks) << 3) | ((!!o->aaip) << 5) | ((!!o->session_md5) << 6) | ((o->file_md5 & 3) << 7) | ((!!o->no_emul_toc) << 9) | ((o->will_cancel) << 10) | ((!!o->old_empty) << 11) | ((!!o->hfsplus) << 12) | ((!!o->fat) << 13); return(1); } int isoburn_igopt_set_relaxed(struct isoburn_imgen_opts *o, int relax) { o->omit_version_numbers= (!!(relax&1)) | (2 * !!(relax & isoburn_igopt_only_iso_versions)); 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)) | (2 * !!(relax & isoburn_igopt_no_j_force_dots)); o->allow_lowercase= !!(relax&32); o->allow_full_ascii= !!(relax&64); o->joliet_longer_paths= !!(relax&128); o->always_gmt= !!(relax & isoburn_igopt_always_gmt); o->rrip_version_1_10= !!(relax & isoburn_igopt_rrip_version_1_10); o->dir_rec_mtime= !!(relax & isoburn_igopt_dir_rec_mtime); o->aaip_susp_1_10= !!(relax & isoburn_igopt_aaip_susp_1_10); o->allow_dir_id_ext= !!(relax & isoburn_igopt_allow_dir_id_ext); o->joliet_long_names= !!(relax & isoburn_igopt_joliet_long_names); o->joliet_rec_mtime= !!(relax & isoburn_igopt_joliet_rec_mtime); o->iso1999_rec_mtime= !!(relax & isoburn_igopt_iso1999_rec_mtime); o->allow_7bit_ascii= !!(relax & isoburn_igopt_allow_7bit_ascii); 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 & 1))<<4)| ((!!o->allow_lowercase)<<5) | ((!!o->allow_full_ascii)<<6) | ((!!o->joliet_longer_paths)<<7) | ((!!o->always_gmt)<<8) | ((!!o->rrip_version_1_10)<<9) | ((!!o->dir_rec_mtime)<<10) | ((!!o->aaip_susp_1_10)<<11) | ((!!(o->omit_version_numbers & 2))<<12) | ((!!(o->no_force_dots & 2))<<13) | ((!!o->allow_dir_id_ext) << 14) | ((!!o->joliet_long_names) << 15) | ((!!o->joliet_rec_mtime) << 16) | ((!!o->iso1999_rec_mtime) << 17) | ((!!o->allow_full_ascii) << 18); return(1); } int isoburn_igopt_set_rr_reloc(struct isoburn_imgen_opts *o, char *name, int flags) { if(o->rr_reloc_dir != name) { if(o->rr_reloc_dir != NULL) free(o->rr_reloc_dir); o->rr_reloc_dir= NULL; if(name != NULL) { o->rr_reloc_dir= strdup(name); if(o->rr_reloc_dir == NULL) { isoburn_msgs_submit(NULL, 0x00060000, "Cannot allocate memory for image generation options", 0, "FATAL", 0); return(-1); } } } o->rr_reloc_flags = flags & 1; return 1; } int isoburn_igopt_get_rr_reloc(struct isoburn_imgen_opts *o, char **name, int *flags) { *name= o->rr_reloc_dir; *flags= o->rr_reloc_flags; return(1); } int isoburn_igopt_set_untranslated_name_len(struct isoburn_imgen_opts *o, int len) { int ret; IsoWriteOpts *opts = NULL; char *msg= NULL; msg= calloc(1, 160); if(msg == NULL) {ret= -1; goto ex;} ret= iso_write_opts_new(&opts, 0); if(ret < 0) { isoburn_msgs_submit(NULL, 0x00060000, "Cannot create libisofs write options object", 0, "FATAL", 0); {ret= 0; goto ex;} } ret= iso_write_opts_set_untranslated_name_len(opts, len); if(ret < 0) { ret= iso_write_opts_set_untranslated_name_len(opts, -1); sprintf(msg, "Improper value for maximum length of untranslated names (%d <-> -1 ... %d)", len, ret); isoburn_msgs_submit(NULL, 0x00060000, msg, 0, "FAILURE", 0); iso_write_opts_free(opts); {ret= 0; goto ex;} } o->untranslated_name_len= ret; /* Normalized len value */ iso_write_opts_free(opts); ret= 1; ex:; if(msg != NULL) free(msg); return(ret); } int isoburn_igopt_get_untranslated_name_len(struct isoburn_imgen_opts *o, int *len) { *len = o->untranslated_name_len; 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); } int isoburn_igopt_get_effective_lba(struct isoburn_imgen_opts *o, int *lba) { *lba= o->effective_lba; return(1); } int isoburn_igopt_get_data_start(struct isoburn_imgen_opts *o, int *lba) { *lba= o->data_start_lba; return(1); } int isoburn_igopt_set_scdbackup_tag(struct isoburn_imgen_opts *o, char *name, char *timestamp, char *tag_written) { strncpy(o->scdbackup_tag_name, name, 80); o->scdbackup_tag_name[80]= 0; strncpy(o->scdbackup_tag_time, timestamp, 18); o->scdbackup_tag_time[18]= 0; o->scdbackup_tag_written = tag_written; if(tag_written != NULL) tag_written[0]= 0; return(1); } int isoburn_igopt_get_scdbackup_tag(struct isoburn_imgen_opts *o, char name[81], char timestamp[19], char **tag_written) { strncpy(name, o->scdbackup_tag_name, 80); name[80]= 0; strncpy(timestamp, o->scdbackup_tag_time, 18); timestamp[18]= 0; *tag_written= o->scdbackup_tag_written; return(1); } int isoburn_igopt_set_system_area(struct isoburn_imgen_opts *opts, char data[32768], int options) { if (data == NULL) { /* Disable */ if (opts->system_area_data != NULL) free(opts->system_area_data); opts->system_area_data = NULL; } else { if (opts->system_area_data == NULL) { opts->system_area_data = calloc(32768, 1); if (opts->system_area_data == NULL) return(-1); } memcpy(opts->system_area_data, data, 32768); } opts->system_area_options = options & 0x3ff; return(1); } int isoburn_igopt_get_system_area(struct isoburn_imgen_opts *opts, char data[32768], int *options) { *options= opts->system_area_options; if(opts->system_area_data == NULL) return(0); memcpy(data, opts->system_area_data, 32768); return(1); } int isoburn_igopt_set_pvd_times(struct isoburn_imgen_opts *opts, time_t vol_creation_time, time_t vol_modification_time, time_t vol_expiration_time, time_t vol_effective_time, char *vol_uuid) { opts->vol_creation_time = vol_creation_time; opts->vol_modification_time = vol_modification_time; opts->vol_expiration_time = vol_expiration_time; opts->vol_effective_time = vol_effective_time; strncpy(opts->vol_uuid, vol_uuid, 16); opts->vol_uuid[16] = 0; return(1); } int isoburn_igopt_get_pvd_times(struct isoburn_imgen_opts *opts, time_t *vol_creation_time, time_t *vol_modification_time, time_t *vol_expiration_time, time_t *vol_effective_time, char vol_uuid[17]) { *vol_creation_time = opts->vol_creation_time; *vol_modification_time = opts->vol_modification_time; *vol_expiration_time = opts->vol_expiration_time; *vol_effective_time = opts->vol_effective_time; strcpy(vol_uuid, opts->vol_uuid); return(1); } int isoburn_igopt_set_part_offset(struct isoburn_imgen_opts *opts, uint32_t block_offset_2k, int secs_512_per_head, int heads_per_cyl) { if (block_offset_2k > 0 && block_offset_2k < 16) return(0); opts->partition_offset = block_offset_2k; opts->partition_secs_per_head = secs_512_per_head; opts->partition_heads_per_cyl = heads_per_cyl; return(1); } int isoburn_igopt_get_part_offset(struct isoburn_imgen_opts *opts, uint32_t *block_offset_2k, int *secs_512_per_head, int *heads_per_cyl) { *block_offset_2k = opts->partition_offset; *secs_512_per_head = opts->partition_secs_per_head; *heads_per_cyl = opts->partition_heads_per_cyl; return 1; } int isoburn_igopt_attach_jte(struct isoburn_imgen_opts *opts, void *libjte_handle) { opts->libjte_handle = libjte_handle; return 1; } int isoburn_igopt_detach_jte(struct isoburn_imgen_opts *opts, void **libjte_handle) { if(libjte_handle != NULL) *libjte_handle = opts->libjte_handle; opts->libjte_handle = NULL; return 1; } int isoburn_igopt_set_tail_blocks(struct isoburn_imgen_opts *opts, uint32_t num_blocks) { opts->tail_blocks = num_blocks; return 1; } int isoburn_igopt_get_tail_blocks(struct isoburn_imgen_opts *opts, uint32_t *num_blocks) { *num_blocks = opts->tail_blocks; return 1; } int isoburn_igopt_set_prep_partition(struct isoburn_imgen_opts *o, char *path, int flag) { if(o->prep_partition != NULL) free(o->prep_partition); o->prep_partition= NULL; if(path != NULL) { o->prep_partition= strdup(path); if(o->prep_partition == NULL) { isoburn_report_iso_error(ISO_OUT_OF_MEM, "Out of memory", 0, "FATAL", 0); return(-1); } } return(1); } int isoburn_igopt_get_prep_partition(struct isoburn_imgen_opts *opts, char **path, int flag) { *path= opts->prep_partition; return(1); } int isoburn_igopt_set_efi_bootp(struct isoburn_imgen_opts *o, char *path, int flag) { if(o->efi_boot_partition != NULL) free(o->efi_boot_partition); o->efi_boot_partition= NULL; if(path != NULL) { o->efi_boot_partition= strdup(path); if(o->efi_boot_partition == NULL) { isoburn_report_iso_error(ISO_OUT_OF_MEM, "Out of memory", 0, "FATAL", 0); return(-1); } } return(1); } int isoburn_igopt_get_efi_bootp(struct isoburn_imgen_opts *opts, char **path, int flag) { *path= opts->efi_boot_partition; return(1); } int isoburn_igopt_set_partition_img(struct isoburn_imgen_opts *opts, int partition_number, uint8_t partition_type, char *image_path) { char msg[80]; if (partition_number < 1 || partition_number > Libisoburn_max_appended_partitionS) { sprintf(msg, "Partition number is out of range (1 ... %d)", Libisoburn_max_appended_partitionS); isoburn_msgs_submit(NULL, 0x00060000, msg, 0, "FAILURE", 0); return(0); } if (opts->appended_partitions[partition_number - 1] != NULL) free(opts->appended_partitions[partition_number - 1]); opts->appended_partitions[partition_number - 1] = strdup(image_path); if (opts->appended_partitions[partition_number - 1] == NULL) return(-1); opts->appended_part_types[partition_number - 1] = partition_type; return(1); } int isoburn_igopt_get_partition_img(struct isoburn_imgen_opts *opts, int num_entries, uint8_t partition_types[], char *image_paths[]) { int i, max_entry= 0; for(i= 0; i < num_entries; i++) image_paths[i]= NULL; for(i= 0; i < Libisoburn_max_appended_partitionS; i++) { if(opts->appended_partitions[i] == NULL) continue; if(i < num_entries) { image_paths[i]= opts->appended_partitions[i]; partition_types[i]= opts->appended_part_types[i]; } max_entry= i + 1; } return(max_entry); } int isoburn_igopt_set_disc_label(struct isoburn_imgen_opts *opts, char *label) { strncpy(opts->ascii_disc_label, label, Libisoburn_disc_label_sizE - 1); opts->ascii_disc_label[Libisoburn_disc_label_sizE - 1] = 0; return(1); } int isoburn_igopt_get_disc_label(struct isoburn_imgen_opts *opts, char **label) { *label= opts->ascii_disc_label; return(1); } int isoburn_igopt_set_hfsp_serial_number(struct isoburn_imgen_opts *opts, uint8_t serial_number[8]) { memcpy(opts->hfsp_serial_number, serial_number, 8); return(1); } int isoburn_igopt_get_hfsp_serial_number(struct isoburn_imgen_opts *opts, uint8_t serial_number[8]) { memcpy(serial_number, opts->hfsp_serial_number, 8); return(1); }