You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1858 lines
49 KiB
1858 lines
49 KiB
|
|
/* |
|
cc -g -c isoburn.c |
|
*/ |
|
|
|
/* |
|
Class core of libisoburn. |
|
|
|
Copyright 2007 - 2015 Vreixo Formoso Lopes <metalpain2002@yahoo.es> |
|
Thomas Schmitt <scdbackup@gmx.net> |
|
|
|
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 <sys/types.h> |
|
#include <stdlib.h> |
|
#include <stdio.h> |
|
#include <string.h> |
|
#include <errno.h> |
|
#include <unistd.h> |
|
|
|
#ifndef Xorriso_standalonE |
|
|
|
#include <libburn/libburn.h> |
|
|
|
#include <libisofs/libisofs.h> |
|
|
|
#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->do_tao= 0; |
|
o->do_fsync= 1; |
|
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;(i<abs_idx || (flag&1)) && *pt!=NULL;i++) { |
|
if(idx>0) |
|
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 out_o The output isoburn object may be NULL if no real write run is |
|
desired with opts. |
|
@param flag bit0= modifying rather than growing |
|
*/ |
|
static |
|
int isoburn_make_iso_write_opts(struct isoburn *out_o, |
|
struct isoburn_imgen_opts *opts, |
|
int fifo_chunks, |
|
IsoWriteOpts *wopts, |
|
int flag) |
|
{ |
|
int ret, rec_mtime, new_img, lba, nwa, i; |
|
struct burn_drive *out_d; |
|
|
|
new_img= flag&1; |
|
|
|
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_hfsp_block_size(wopts, opts->hfsp_block_size, |
|
opts->apm_block_size); |
|
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_joliet_utf16(wopts, opts->joliet_utf16); |
|
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); |
|
|
|
if(out_o != NULL) { |
|
out_d= out_o->drive; |
|
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, |
|
opts->prep_part_flag & 1); |
|
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, |
|
opts->efi_boot_part_flag & 1); |
|
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], |
|
opts->appended_part_flags[i]); |
|
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_appended_as_gpt(wopts, opts->appended_as_gpt); |
|
iso_write_opts_set_disc_label(wopts, opts->ascii_disc_label); |
|
|
|
ret= 1; |
|
ex: |
|
return(ret); |
|
} |
|
|
|
|
|
/* @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, i, new_img, early_indev_release; |
|
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;} |
|
} |
|
|
|
out_o->do_tao = opts->do_tao; |
|
out_o->do_fsync = opts->do_fsync; |
|
|
|
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; |
|
} |
|
ret= isoburn_make_iso_write_opts(out_o, opts, fifo_chunks, wopts, flag & 1); |
|
if(ret < 0) |
|
goto ex; |
|
|
|
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->joliet_utf16= 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->prep_part_flag= 0; |
|
o->efi_boot_partition= NULL; |
|
o->efi_boot_part_flag= 0; |
|
for(i= 0; i < Libisoburn_max_appended_partitionS; i++) { |
|
o->appended_partitions[i]= NULL; |
|
o->appended_part_types[i]= 0; |
|
o->appended_part_flags[i]= 0; |
|
} |
|
memset(o->hfsp_serial_number, 0, 8); |
|
o->hfsp_block_size= 0; |
|
o->apm_block_size= 0; |
|
o->do_tao= 0; |
|
o->do_fsync= 0; |
|
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); |
|
o->joliet_utf16= !!(relax & isoburn_igopt_joliet_utf16); |
|
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) | |
|
((!!o->joliet_utf16) << 19); |
|
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 & 0x7fff; |
|
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; |
|
o->prep_part_flag= 0; |
|
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); |
|
} |
|
} |
|
o->prep_part_flag= flag & 1; |
|
return(1); |
|
} |
|
|
|
|
|
int isoburn_igopt_get_prep_partition(struct isoburn_imgen_opts *opts, |
|
char **path, int flag) |
|
{ |
|
*path= opts->prep_partition; |
|
if(flag & 1) |
|
return(1 + (opts->prep_part_flag & 0x3fffffff)); |
|
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; |
|
o->efi_boot_part_flag= 0; |
|
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); |
|
} |
|
} |
|
o->efi_boot_part_flag = flag & 1; |
|
return(1); |
|
} |
|
|
|
|
|
int isoburn_igopt_get_efi_bootp(struct isoburn_imgen_opts *opts, |
|
char **path, int flag) |
|
{ |
|
*path= opts->efi_boot_partition; |
|
if(flag & 1) |
|
return(1 + (opts->efi_boot_part_flag & 0x3fffffff)); |
|
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_part_flag(struct isoburn_imgen_opts *opts, |
|
int partition_number, int flag) |
|
{ |
|
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); |
|
} |
|
opts->appended_part_flags[partition_number - 1]= flag; |
|
return(1); |
|
} |
|
|
|
|
|
int isoburn_igopt_get_part_flags(struct isoburn_imgen_opts *opts, |
|
int num_entries, int part_flags[]) |
|
{ |
|
int i, max_entry= 0; |
|
|
|
for(i= 0; i < num_entries; i++) |
|
part_flags[i]= 0; |
|
for(i= 0; i < Libisoburn_max_appended_partitionS; i++) { |
|
if(i < num_entries) |
|
part_flags[i]= opts->appended_part_flags[i]; |
|
max_entry= i + 1; |
|
} |
|
return(max_entry); |
|
} |
|
|
|
|
|
int isoburn_igopt_set_appended_as_gpt(struct isoburn_imgen_opts *opts, int gpt) |
|
{ |
|
opts->appended_as_gpt= !!gpt; |
|
return(1); |
|
} |
|
|
|
|
|
int isoburn_igopt_get_appended_as_gpt(struct isoburn_imgen_opts *opts, |
|
int *gpt) |
|
{ |
|
*gpt= opts->appended_as_gpt; |
|
return(1); |
|
} |
|
|
|
|
|
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); |
|
} |
|
|
|
|
|
int isoburn_igopt_set_hfsp_block_size(struct isoburn_imgen_opts *opts, |
|
int hfsp_block_size, int apm_block_size) |
|
{ |
|
char msg[80]; |
|
|
|
msg[0]= 0; |
|
if(hfsp_block_size != -1) { |
|
if(hfsp_block_size != 0 && hfsp_block_size != 512 && |
|
hfsp_block_size != 2048) { |
|
sprintf(msg, "Not a supported HFS+ size (%d <-> 0, 512, 2048)", |
|
hfsp_block_size); |
|
isoburn_msgs_submit(NULL, 0x00060000, msg, 0, "FAILURE", 0); |
|
} |
|
opts->hfsp_block_size = hfsp_block_size; |
|
} |
|
if(apm_block_size != -1) { |
|
if(apm_block_size != 0 && apm_block_size != 512 && apm_block_size != 2048) { |
|
sprintf(msg, "Not a supported APM block size (%d <-> 0, 512, 2048)", |
|
apm_block_size); |
|
isoburn_msgs_submit(NULL, 0x00060000, msg, 0, "FAILURE", 0); |
|
} |
|
opts->apm_block_size = apm_block_size; |
|
} |
|
if(msg[0]) |
|
return(0); |
|
return(1); |
|
} |
|
|
|
|
|
int isoburn_igopt_get_hfsp_block_size(struct isoburn_imgen_opts *opts, |
|
int *hfsp_block_size, int *apm_block_size) |
|
{ |
|
*hfsp_block_size= opts->hfsp_block_size; |
|
*apm_block_size= opts->apm_block_size; |
|
return(1); |
|
} |
|
|
|
|
|
int isoburn_igopt_set_write_type(struct isoburn_imgen_opts *opts, int do_tao) |
|
{ |
|
if(do_tao < -1 || do_tao > 1) |
|
return(0); |
|
opts->do_tao= do_tao; |
|
return(1); |
|
} |
|
|
|
|
|
int isoburn_igopt_get_write_type(struct isoburn_imgen_opts *opts, int *do_tao) |
|
{ |
|
*do_tao= opts->do_tao; |
|
return(1); |
|
} |
|
|
|
int isoburn_igopt_set_stdio_endsync(struct isoburn_imgen_opts *opts, |
|
int do_sync) |
|
{ |
|
opts->do_fsync= !!do_sync; |
|
return(1); |
|
} |
|
|
|
int isoburn_igopt_get_stdio_endsync(struct isoburn_imgen_opts *opts, |
|
int *do_sync) |
|
{ |
|
*do_sync= opts->do_fsync; |
|
return(1); |
|
} |
|
|
|
int isoburn_conv_name_chars(struct isoburn_imgen_opts *opts, |
|
char *name, size_t name_len, |
|
char **result, size_t *result_len, int flag) |
|
{ |
|
int ret; |
|
IsoWriteOpts *wopts= NULL; |
|
|
|
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; |
|
} |
|
ret= isoburn_make_iso_write_opts(NULL, opts, 0, wopts, 0); |
|
if(ret < 0) |
|
goto ex; |
|
ret= iso_conv_name_chars(wopts, name, name_len, result, result_len, flag); |
|
ex:; |
|
if(wopts != NULL) |
|
iso_write_opts_free(wopts); |
|
return(ret); |
|
}
|
|
|