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.

3359 lines
107 KiB

/* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images.
Copyright 2007-2012 Thomas Schmitt, <scdbackup@gmx.net>
Provided under GPL version 2 or later.
This file contains functions which operate on drives and media.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <ctype.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <time.h>
#include <errno.h>
#include <pthread.h>
#include "xorriso.h"
#include "xorriso_private.h"
#include "lib_mgt.h"
#include "drive_mgt.h"
#include "iso_img.h"
#include "sort_cmp.h"
#include "write_run.h"
#include "read_run.h"
static const char *un0(const char *text)
{
if(text == NULL)
return("");
return(text);
}
int Xorriso_auto_driveadr(struct XorrisO *xorriso, char *adr, char *result,
int flag)
{
int ret, is_known_mmc= 0, does_exist= 0;
char *path_pt, *libburn_adr= NULL;
char *abs_pt, *abs_adr= NULL;
struct stat stbuf;
Xorriso_alloc_meM(libburn_adr, char, BURN_DRIVE_ADR_LEN + SfileadrL);
Xorriso_alloc_meM(abs_adr, char, SfileadrL);
path_pt= adr;
if(strncmp(adr, "stdio:", 6) == 0)
path_pt= adr + 6;
else if(strncmp(adr, "mmc:", 4) == 0)
path_pt= adr + 4;
/* <<< replace by Xorriso_normalize_img_path() ? */;
if(path_pt[0] != '/') {
abs_pt= getcwd(abs_adr, SfileadrL - 1);
if(abs_pt == NULL) {
Xorriso_msgs_submit(xorriso, 0,
"Relative drive path given. Cannot determine working directory.",
errno, "FAILURE", 0);
{ret= -1; goto ex;}
}
ret= Sfile_add_to_path(abs_adr, path_pt, 0);
if(ret <= 0)
{ret= -1; goto ex;}
}
is_known_mmc= burn_drive_convert_fs_adr(path_pt, libburn_adr);
does_exist= (stat(path_pt, &stbuf) != -1);
Xorriso_process_msg_queues(xorriso,0);
ret= Xorriso_is_in_patternlist(xorriso, xorriso->drive_whitelist, path_pt, 0);
if(ret > 0)
goto ok;
ret= Xorriso_is_in_patternlist(xorriso, xorriso->drive_blacklist, path_pt, 0);
if(ret < 0)
goto ex;
if(ret) {
strcpy(xorriso->info_text, "Drive address ");
Text_shellsafe(adr, xorriso->info_text, 1);
strcat(xorriso->info_text,
" rejected because: -drive_class 'banned' ");
Text_shellsafe(Xorriso_get_pattern(xorriso, xorriso->drive_blacklist,
ret - 1, 0),
xorriso->info_text, 1);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
{ret= 0; goto ex;}
}
/* if in greylist and not MMC and not stdio prefix: reject */
if(is_known_mmc < 0)
goto ex;
if(adr == path_pt && !is_known_mmc) { /* no prefix, no MMC */
ret= Xorriso_is_in_patternlist(xorriso, xorriso->drive_greylist, path_pt,0);
if(ret < 0)
goto ex;
if(ret) {
strcpy(xorriso->info_text, "Drive address ");
Text_shellsafe(adr, xorriso->info_text, 1);
strcat(xorriso->info_text, " rejected because: ");
if(does_exist)
strcat(xorriso->info_text, "not MMC");
else
strcat(xorriso->info_text, "not existing");
strcat(xorriso->info_text, " and -drive_class 'caution' ");
Text_shellsafe(Xorriso_get_pattern(xorriso,xorriso->drive_greylist,
ret - 1, 0),
xorriso->info_text, 1);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
sprintf(xorriso->info_text,
"If the address is a legitimate %s, prepend \"stdio:\"",
does_exist ? "target" : "address for a new regular file");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0);
{ret= 0; goto ex;}
}
}
ok:;
if(strncmp(adr, "mmc:", 4) == 0) {
if(Sfile_str(result, path_pt, 0) <= 0)
{ret= 0; goto ex;}
} else if(adr == path_pt && is_known_mmc <= 0) {
Sfile_str(result, "stdio:", 0);
if(Sfile_str(result, adr, 1) <= 0)
{ret= 0; goto ex;}
} else {
if(Sfile_str(result, adr, 0) <= 0)
{ret= 0; goto ex;}
}
if(strncmp(result, "stdio:", 6)==0) {
if(xorriso->ban_stdio_write) {
strcpy(xorriso->info_text, "Drive address banned by -ban_stdio_write : ");
Text_shellsafe(result, xorriso->info_text, 1);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
{ret= 0; goto ex;}
}
}
ret= 1;
ex:;
Xorriso_free_meM(libburn_adr);
Xorriso_free_meM(abs_adr);
return(ret);
}
static int Xorriso_grasp_loaded_aaip(struct XorrisO *xorriso, IsoImage *volset,
int flag)
{
int ret, change_pending_rec;
IsoNode *root_node;
size_t value_length;
char *value= NULL;
double num;
struct FindjoB *job= NULL;
struct stat dir_stbuf;
/* To be re-instated at function end */
change_pending_rec= xorriso->volset_change_pending;
/* Look for isofs.st and put it into xorriso->isofs_st_in */
root_node= (IsoNode *) iso_image_get_root(volset);
ret= iso_node_lookup_attr(root_node, "isofs.st", &value_length, &value, 0);
if(ret > 0) {
if(value_length > 0) {
sscanf(value, "%lf", &num);
if(num > 0)
xorriso->isofs_st_in= num;
}
free(value);
}
if(xorriso->do_hfsplus) {
/* Bring isofs.hx to iso_hfsplus_xinfo_func,
isofs.hb to IsoImage blessings
*/
ret= Findjob_new(&job, "/", 0);
if(ret<=0) {
Xorriso_no_findjob(xorriso, "xorriso", 0);
{ret= -1; goto ex;}
}
Findjob_set_action_target(job, 49, NULL, 0);
ret= Xorriso_findi(xorriso, job, NULL, (off_t) 0, NULL, "/",
&dir_stbuf, 0, 0);
if(ret <= 0)
goto ex;
}
ret= 1;
ex:;
xorriso->volset_change_pending= change_pending_rec;
Findjob_destroy(&job, 0);
return(ret);
}
/* @param flag bit0= aquire as isoburn input drive
bit1= aquire as libburn output drive (as isoburn drive if bit0)
bit2= regard overwriteable media as blank
bit3= if the drive is a regular disk file: truncate it to
the write start address
bit5= do not print toc
bit6= do not calm down drive after aquiring it
bit7= re-assess rather than aquire:
Do not give up drives,
use isoburn_drive_aquire() with re-assessment bit
@return <=0 failure , 1= ok
2=success, but not writeable with bit1
3=success, but not blank and not ISO with bit0
*/
int Xorriso_aquire_drive(struct XorrisO *xorriso, char *adr, char *show_adr,
int flag)
{
int ret, hret, not_writeable= 0, has_what, aquire_flag, load_lba, ext;
int lba, track, session, params_flag, adr_mode, read_ret, start_lba;
uint32_t size, offst;
struct burn_drive_info *dinfo= NULL, *out_dinfo= NULL, *in_dinfo= NULL;
struct burn_drive *drive= NULL, *out_drive= NULL, *in_drive= NULL;
enum burn_disc_status state;
IsoImage *volset = NULL;
struct isoburn_read_opts *ropts= NULL;
char *libburn_adr= NULL, *off_adr= NULL, *boot_fate, *sev;
char volid[33], *adr_data= NULL, *adr_pt;
Xorriso_alloc_meM(libburn_adr, char, SfileadrL);
Xorriso_alloc_meM(off_adr, char, SfileadrL);
Xorriso_alloc_meM(adr_data, char, 163);
if(show_adr == NULL) {
show_adr= adr;
ret= burn_drive_convert_fs_adr(adr, off_adr);
if(ret > 0)
adr= off_adr;
}
if((flag&3)==0) {
sprintf(xorriso->info_text,
"XORRISOBURN program error : Xorriso_aquire_drive bit0+bit1 not set");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
{ret= -1; goto ex;}
}
if(!(flag & 128)) {
ret= Xorriso_give_up_drive(xorriso, (flag&3)|8);
if(ret<=0)
goto ex;
}
if(flag & 1)
xorriso->isofs_st_out= time(0) - 1;
ret= Xorriso_auto_driveadr(xorriso, adr, libburn_adr, 0);
if(ret <= 0)
goto ex;
if(strcmp(libburn_adr,"stdio:/dev/fd/1")==0) {
if(xorriso->dev_fd_1<0) {
sprintf(xorriso->info_text,
"-*dev \"stdio:/dev/fd/1\" was not a start argument. Cannot use it now.");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
{ret= 0; goto ex;}
} else {
sprintf(libburn_adr, "stdio:/dev/fd/%d", xorriso->dev_fd_1);
}
}
if(flag & 128) {
if(flag & 1)
Xorriso_get_drive_handles(xorriso, &in_dinfo, &in_drive, "", 16);
if(flag & 2)
Xorriso_get_drive_handles(xorriso, &out_dinfo, &out_drive, "", 2 | 16);
if(in_dinfo != NULL && (out_dinfo == NULL || out_dinfo == in_dinfo)) {
dinfo= in_dinfo;
if(flag & 2)
xorriso->outdev_is_exclusive= xorriso->indev_is_exclusive;
} else if(out_dinfo != NULL && in_dinfo == NULL) {
dinfo= out_dinfo;
if(flag & 1)
xorriso->indev_is_exclusive= xorriso->outdev_is_exclusive;
} else if(out_dinfo != NULL || in_dinfo != NULL) {
sprintf(xorriso->info_text,
"Two different drives shall be re-assed in one call");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
{ret= 0; goto ex;}
} else {
sprintf(xorriso->info_text, "No drive aquired on re-assessment");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
{ret= 0; goto ex;}
}
} else if((flag&3)==1 && xorriso->out_drive_handle!=NULL) {
ret= Xorriso_get_drive_handles(xorriso, &out_dinfo, &out_drive,
"on attempt to compare new indev with outdev", 2);
if(ret<=0)
goto ex;
ret= burn_drive_equals_adr(out_drive, libburn_adr, 1);
if(ret==1) {
dinfo= out_dinfo;
xorriso->indev_is_exclusive= xorriso->outdev_is_exclusive;
}
} else if((flag&3)==2 && xorriso->in_drive_handle!=NULL) {
ret= Xorriso_get_drive_handles(xorriso, &in_dinfo, &in_drive,
"on attempt to compare new outdev with indev", 0);
if(ret<=0)
goto ex;
ret= burn_drive_equals_adr(in_drive, libburn_adr, 1);
if(ret==1) {
dinfo= in_dinfo;
xorriso->outdev_is_exclusive= xorriso->indev_is_exclusive;
}
}
if(dinfo == NULL || (flag & 128)) {
aquire_flag= 1 | ((flag&(8|4))>>1) | ((xorriso->toc_emulation_flag & 3)<<3);
if(xorriso->toc_emulation_flag & 4)
aquire_flag|= 128;
if(xorriso->toc_emulation_flag & 8)
aquire_flag|= 512;
if(!(xorriso->do_aaip & 1))
aquire_flag|= 32;
if((xorriso->ino_behavior & (1 | 2)) && !(xorriso->do_aaip & (4 | 32)))
aquire_flag|= 64;
if(flag & 128)
aquire_flag|= 256;
burn_preset_device_open(xorriso->drives_exclusive, 0, 0);
burn_allow_drive_role_4(1 | (xorriso->early_stdio_test & 14));
ret= isoburn_drive_aquire(&dinfo, libburn_adr, aquire_flag);
burn_preset_device_open(1, 0, 0);
Xorriso_process_msg_queues(xorriso,0);
if(ret<=0) {
if(flag & 128)
sprintf(xorriso->info_text,"Cannot re-assess drive '%s'", adr);
else
sprintf(xorriso->info_text,"Cannot aquire drive '%s'", adr);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
ret= 0; goto ex;
}
state= isoburn_disc_get_status(dinfo[0].drive);
ret= isoburn_get_img_partition_offset(dinfo[0].drive, &offst);
if((state == BURN_DISC_APPENDABLE || state == BURN_DISC_FULL) && ret == 1) {
sprintf(xorriso->info_text,
"ISO image bears MBR with -boot_image any partition_offset=%lu",
(unsigned long) offst);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
}
if(flag&1)
if(xorriso->image_start_mode&(1<<31)) /* used up setting */
xorriso->image_start_mode= 0; /* no need to perform auto setting */
if(flag & 1)
xorriso->indev_is_exclusive= xorriso->drives_exclusive;
if(flag & 2)
xorriso->outdev_is_exclusive= xorriso->drives_exclusive;
}
drive= dinfo[0].drive;
volset= isoburn_get_attached_image(drive);
if(volset != NULL) {
ret= iso_image_set_truncate_mode(volset, 1, xorriso->file_name_limit);
Xorriso_process_msg_queues(xorriso,0);
if(ret < 0)
{ret= 0; goto ex;}
}
state= isoburn_disc_get_status(drive);
Xorriso_process_msg_queues(xorriso,0);
if(flag&1) {
if(xorriso->image_start_mode&(1<<31)) /* used up setting */
xorriso->image_start_mode&= ~0xffff; /* perform auto setting */
if((xorriso->image_start_mode&(1<<30))) { /* if enabled at all */
adr_pt= xorriso->image_start_value;
adr_mode= xorriso->image_start_mode & 0xffff;
if(adr_mode == 4 && strlen(adr_pt) <= 80) {
/* Convert volid search expression into lba */
params_flag= 0;
ret= Xorriso__bourne_to_reg(xorriso->image_start_value, adr_data, 0);
if(ret == 1)
params_flag|= 4;
ret= isoburn_get_mount_params(drive, 4, adr_data, &lba, &track,
&session, volid, params_flag);
Xorriso_process_msg_queues(xorriso,0);
if(ret <= 0)
goto ex;
if(session <= 0 || track <= 0 || ret == 2) {
Xorriso_msgs_submit(xorriso, 0,
"-load : Given address does not point to an ISO 9660 session",
0, "FAILURE", 0);
ret= 0; goto ex;
}
sprintf(volid, "%d", lba);
adr_pt= volid;
adr_mode= 3;
}
ret= isoburn_set_msc1(drive, adr_mode, adr_pt,
!!(xorriso->image_start_mode & (1<<16)));
if(ret<=0)
goto ex;
if(xorriso->image_start_mode&(1<<31))
xorriso->image_start_mode= 0; /* disable msc1 setting completely */
else
xorriso->image_start_mode|= (1<<31); /* mark as used up */
}
}
if(flag&1) {
volset= isoburn_get_attached_image(drive);
if(volset != NULL) { /* The image object is already created */
iso_image_unref(volset);
}
}
if(flag&2) {
xorriso->out_drive_handle= dinfo;
if(Sfile_str(xorriso->outdev, show_adr, 0)<=0)
{ret= -1; goto ex;}
ret= burn_drive_convert_fs_adr(adr, xorriso->outdev_off_adr);
if(ret <= 0)
xorriso->outdev_off_adr[0]= 0;
if(state != BURN_DISC_BLANK && state != BURN_DISC_APPENDABLE) {
sprintf(xorriso->info_text, "Disc status unsuitable for writing");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
not_writeable= 1;
}
}
if(flag&1) {
xorriso->in_drive_handle= dinfo;
if(Sfile_str(xorriso->indev, show_adr, 0)<=0)
{ret= -1; goto ex;}
ret= burn_drive_convert_fs_adr(adr, xorriso->indev_off_adr);
if(ret <= 0)
xorriso->indev_off_adr[0]= 0;
} else if(flag&2) {
if(xorriso->in_volset_handle==NULL) {
/* No volume loaded: create empty one */
ret= Xorriso_create_empty_iso(xorriso, 0);
if(ret<=0)
goto ex;
} else {
iso_image_ref((IsoImage *) xorriso->in_volset_handle);
start_lba= -1;
ret= Xorriso_get_drive_handles(xorriso, &in_dinfo, &in_drive,
"on attempt to attach ISO image object to outdev", 16);
if(ret > 0)
start_lba= isoburn_get_attached_start_lba(in_drive);
ret= isoburn_attach_image(drive, (IsoImage *) xorriso->in_volset_handle);
if(ret<=0) {
sprintf(xorriso->info_text,
"Failed to attach ISO image object to outdev");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
{ret= -1; goto ex;}
}
if(start_lba >= 0)
isoburn_attach_start_lba(drive, lba, 0);
}
if(!(flag&32))
Xorriso_toc(xorriso, 1 | 2 | 8);
{ret= 1+not_writeable; goto ex;}
}
if(xorriso->in_volset_handle!=NULL)
iso_image_unref((IsoImage *) xorriso->in_volset_handle);
xorriso->in_volset_handle= NULL;
Sectorbitmap_destroy(&(xorriso->in_sector_map), 0);
Xorriso_destroy_hln_array(xorriso, 0);
Xorriso_destroy_di_array(xorriso, 0);
xorriso->boot_count= 0;
/* check for invalid state */
if(state != BURN_DISC_BLANK && state != BURN_DISC_APPENDABLE &&
state != BURN_DISC_FULL) {
sprintf(xorriso->info_text,
"Disc status not blank and unsuitable for reading");
sev= "FAILURE";
if(xorriso->img_read_error_mode==2)
sev= "FATAL";
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, sev, 0);
Xorriso_give_up_drive(xorriso, 1|((flag&32)>>2));
ret= 3; goto ex;
}
/* fill read opts */
ret= isoburn_ropt_new(&ropts, 0);
if(ret<=0)
goto ex;
ret= Xorriso_set_data_cache(xorriso, ropts, xorriso->cache_num_tiles,
xorriso->cache_tile_blocks,
xorriso->cache_default);
if(ret<=0)
goto ex;
ext= isoburn_ropt_noiso1999;
if((xorriso->ino_behavior & (1 | 2)) && !(xorriso->do_aaip & (1 | 4 | 32))
&& !(xorriso->do_md5 & 1) && !(xorriso->do_hfsplus))
ext|= isoburn_ropt_noaaip;
if(!(xorriso->do_aaip & 1))
ext|= isoburn_ropt_noacl;
if(!(xorriso->do_aaip & 4))
ext|= isoburn_ropt_noea;
if(xorriso->ino_behavior & 1)
ext|= isoburn_ropt_noino;
if(!(xorriso->do_md5 & 1))
ext|= isoburn_ropt_nomd5;
if(xorriso->do_md5 & 32)
ext|= isoburn_ropt_nomd5tag;
if(xorriso->ecma119_map == 0)
ext|= isoburn_ropt_map_unmapped;
else if(xorriso->ecma119_map == 2)
ext|= isoburn_ropt_map_uppercase;
else if(xorriso->ecma119_map == 3)
ext|= isoburn_ropt_map_lowercase;
else
ext|= isoburn_ropt_map_stripped;
/* >>> Next rev: more bits in do_*, #de fine Xorriso_provisory_read_optS 1 */
#ifdef Xorriso_provisory_read_optS
if(!xorriso->do_rockridge)
ext|= isoburn_ropt_norock;
if(!xorriso->do_joliet)
ext|= isoburn_ropt_nojoliet;
#endif /* Xorriso_provisory_read_optS */
isoburn_ropt_set_extensions(ropts, ext);
isoburn_ropt_set_default_perms(ropts, (uid_t) 0, (gid_t) 0, (mode_t) 0555);
isoburn_ropt_set_input_charset(ropts, xorriso->in_charset);
isoburn_ropt_set_auto_incharset(ropts, !!(xorriso->do_aaip & 512));
isoburn_ropt_set_displacement(ropts, xorriso->displacement,
xorriso->displacement_sign);
isoburn_ropt_set_truncate_mode(ropts, 1, xorriso->file_name_limit);
Xorriso_set_image_severities(xorriso, 1); /* No DEBUG messages */
Xorriso_pacifier_reset(xorriso, 0);
isoburn_set_read_pacifier(drive, Xorriso__read_pacifier, (void *) xorriso);
/* <<< Trying to work around too much tolerance on bad image trees.
Better would be a chance to instruct libisofs what to do in
case of image read errors. There is a risk to mistake other SORRYs.
*/
if(xorriso->img_read_error_mode>0)
iso_set_abort_severity("SORRY");
if(state != BURN_DISC_BLANK) {
ret= isoburn_disc_get_msc1(drive, &load_lba);
if(ret > 0) {
sprintf(xorriso->info_text,
"Loading ISO image tree from LBA %d", load_lba);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
}
ret= Xorriso_assert_volid(xorriso, load_lba, 0);
if(ret <= 0)
goto ex;
}
if(xorriso->read_speed != -2)
burn_drive_set_speed(drive, xorriso->read_speed, 0);
read_ret= ret= isoburn_read_image(drive, ropts, &volset);
/* <<< Resetting to normal thresholds */
if(xorriso->img_read_error_mode>0)
Xorriso_set_abort_severity(xorriso, 0);
if(ret<=0) {
Xorriso_process_msg_queues(xorriso,0);
Xorriso_set_image_severities(xorriso, 0);
Xorriso_give_up_drive(xorriso, 1|((flag&32)>>2));
sprintf(xorriso->info_text,"Cannot read ISO image tree");
sev= "FAILURE";
if(xorriso->img_read_error_mode==2)
sev= "FATAL";
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, sev, 0);
if(read_ret == (int) ISO_SB_TREE_CORRUPTED && (xorriso->do_md5 & 1)) {
Xorriso_msgs_submit(xorriso, 0,
"This might be false MD5 alarm if an add-on session was written by growisofs.",
0, "HINT", 0);
Xorriso_msgs_submit(xorriso, 0,
"In this case you get an ISO image tree by option -md5 'load_check_off'",
0, "HINT", 0);
} else if(xorriso->img_read_error_mode!=0) {
Xorriso_msgs_submit(xorriso, 0, "You might get a partial or altered ISO image tree by option -error_behavior 'image_loading' 'best_effort' if -abort_on is set to be tolerant enough.",
0, "HINT", 0);
}
ret= 3; goto ex;
}
Xorriso_pacifier_callback(xorriso, "nodes read", xorriso->pacifier_count, 0,
"", 1); /* report end count */
xorriso->in_volset_handle= (void *) volset;
xorriso->in_sector_map= NULL;
Xorriso_set_image_severities(xorriso, 0);
Xorriso_update_volid(xorriso, 0);
strncpy(xorriso->application_id,
un0(iso_image_get_application_id(volset)), 128);
xorriso->application_id[128]= 0;
strncpy(xorriso->publisher, un0(iso_image_get_publisher_id(volset)), 128);
xorriso->publisher[128]= 0;
strncpy(xorriso->system_id, un0(iso_image_get_system_id(volset)), 32);
xorriso->system_id[32]= 0;
strncpy(xorriso->volset_id, un0(iso_image_get_volset_id(volset)), 128);
xorriso->volset_id[128]= 0;
strncpy(xorriso->copyright_file,
un0(iso_image_get_copyright_file_id(volset)), 37);
xorriso->copyright_file[37]= 0;
strncpy(xorriso->biblio_file, un0(iso_image_get_biblio_file_id(volset)), 37);
xorriso->biblio_file[37]= 0;
strncpy(xorriso->abstract_file,
un0(iso_image_get_abstract_file_id(volset)), 37);
xorriso->abstract_file[37]= 0;
if(xorriso->out_drive_handle != NULL &&
xorriso->out_drive_handle != xorriso->in_drive_handle) {
start_lba= -1;
ret= Xorriso_get_drive_handles(xorriso, &in_dinfo, &in_drive,
"on attempt to attach ISO image volset to outdev", 16);
if(ret > 0)
start_lba= isoburn_get_attached_start_lba(in_drive);
ret= Xorriso_get_drive_handles(xorriso, &out_dinfo, &out_drive,
"on attempt to attach ISO image volset to outdev", 2);
if(ret<=0)
goto ex;
iso_image_ref((IsoImage *) xorriso->in_volset_handle);
isoburn_attach_image(out_drive, xorriso->in_volset_handle);
if(start_lba >= 0)
isoburn_attach_start_lba(out_drive, ret, 0);
}
Xorriso_process_msg_queues(xorriso,0);
isoburn_ropt_get_size_what(ropts, &size, &has_what);
if(has_what & isoburn_ropt_has_el_torito) {
if(xorriso->boot_image_bin_path[0])
boot_fate= "replaced by new boot image";
else if(xorriso->patch_isolinux_image & 1)
boot_fate= "patched at boot info table";
else if(xorriso->keep_boot_image)
boot_fate= "kept unchanged";
else
boot_fate= "discarded";
sprintf(xorriso->info_text,
"Detected El-Torito boot information which currently is set to be %s",
boot_fate);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
Xorriso_record_boot_info(xorriso, 0);
}
if(flag & 1) {
ret= Xorriso_grasp_loaded_aaip(xorriso, volset, 0);
if(ret <= 0)
goto ex;
}
if(!(flag&32)) {
Xorriso_toc(xorriso, 1 | 8);
if(xorriso->loaded_volid[0] != 0 &&
(state == BURN_DISC_APPENDABLE || state == BURN_DISC_FULL)) {
sprintf(xorriso->info_text,"Volume id : '%s'\n",
xorriso->loaded_volid);
Xorriso_info(xorriso, 0);
}
if(strcmp(xorriso->loaded_volid, xorriso->volid) != 0 &&
!xorriso->volid_default) {
sprintf(xorriso->info_text, "New volume id: '%s'\n", xorriso->volid);
Xorriso_info(xorriso, 0);
}
}
ret= 1+not_writeable;
ex:
Xorriso_process_msg_queues(xorriso,0);
if(ret<=0) {
hret= Xorriso_give_up_drive(xorriso, (flag&3)|((flag&32)>>2));
if(hret<ret)
ret= hret;
} else {
if(drive != NULL && (xorriso->do_calm_drive & 1) && !(flag & 64))
burn_drive_snooze(drive, 0); /* No need to make noise from start */
}
if(ropts!=NULL)
isoburn_ropt_destroy(&ropts, 0);
Xorriso_free_meM(off_adr);
Xorriso_free_meM(libburn_adr);
Xorriso_free_meM(adr_data);
return(ret);
}
/* @param flag bit0=input drive
bit1=output drive
bit2=eject
bit3=no info message or toc
*/
int Xorriso_give_up_drive(struct XorrisO *xorriso, int flag)
{
int in_is_out_too, ret, do_eject;
struct burn_drive_info *dinfo;
struct burn_drive *drive;
in_is_out_too= (xorriso->in_drive_handle == xorriso->out_drive_handle);
if((flag&4) && in_is_out_too && (flag&(1|2))) {
if((flag&3)!=3) {
sprintf(xorriso->info_text,"Giving up for -eject whole -dev ");
Text_shellsafe(xorriso->indev, xorriso->info_text, 1);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
}
flag|= 3; /* give up in/out drive to eject it */
}
if((flag&1) && xorriso->in_drive_handle != NULL) {
Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
"on attempt to give up drive", 0);
if(!in_is_out_too) {
do_eject= !!(flag&4);
if((flag & 4) && !xorriso->indev_is_exclusive) {
sprintf(xorriso->info_text,
"Will not eject medium in non-exclusively aquired input drive.");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
do_eject= 0;
}
if(drive!=NULL)
isoburn_drive_release(drive, do_eject);
if(dinfo!=NULL)
burn_drive_info_free(dinfo);
}
xorriso->in_drive_handle= NULL;
xorriso->indev[0]= 0;
if(xorriso->in_volset_handle!=NULL)
iso_image_unref((IsoImage *) xorriso->in_volset_handle);
xorriso->in_volset_handle= NULL;
Sectorbitmap_destroy(&(xorriso->in_sector_map), 0);
Xorriso_destroy_di_array(xorriso, 0);
Xorriso_destroy_hln_array(xorriso, 0);
xorriso->loaded_volid[0]= 0;
xorriso->isofs_st_out= time(0) - 1;
xorriso->isofs_st_in= 0;
xorriso->volset_change_pending= 0;
xorriso->no_volset_present= 0;
xorriso->loaded_boot_bin_lba= 0;
xorriso->loaded_boot_cat_path[0]= 0;
xorriso->boot_count= 0;
in_is_out_too= 0;
}
if((flag&2) && xorriso->out_drive_handle!=NULL) {
do_eject= !!(flag&4);
if((flag & 4) && !xorriso->outdev_is_exclusive) {
sprintf(xorriso->info_text,
"Will not eject medium in non-exclusively aquired drive.");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
do_eject= 0;
}
Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
"on attempt to give up drive", 2);
if(!in_is_out_too) {
if(drive!=NULL)
isoburn_drive_release(drive, do_eject);
if(dinfo!=NULL)
burn_drive_info_free(dinfo);
}
xorriso->out_drive_handle= NULL;
xorriso->outdev[0]= 0;
xorriso->outdev_off_adr[0]= 0;
} else if((flag&1) && xorriso->out_drive_handle!=NULL) {
ret= Xorriso_create_empty_iso(xorriso, 0);
if(ret<=0)
return(ret);
if(!(flag&8)) {
sprintf(xorriso->info_text,
"Only the output drive remains. Created empty ISO image.\n");
Xorriso_info(xorriso, 0);
Xorriso_toc(xorriso, 1 | 2 | 8);
}
}
Xorriso_process_msg_queues(xorriso,0);
return(1);
}
int Xorriso_may_burn(struct XorrisO *xorriso, int flag)
{
if(xorriso->outdev_is_exclusive)
return(1);
sprintf(xorriso->info_text, "The output drive was not aquired exclusively.");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
sprintf(xorriso->info_text, "A possible remedy is: -osirrox 'o_excl_on'");
if(xorriso->outdev[0]) {
strcat(xorriso->info_text," -outdev ");
Text_shellsafe(xorriso->outdev, xorriso->info_text, 1);
}
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0);
return(0);
}
/* @param flag bit1=report about output drive rather than input drive
bit2=do not try to read ISO heads
*/
int Xorriso_toc_to_string(struct XorrisO *xorriso, char **toc_text, int flag)
{
int ret, stack_handle, toc_ret, l;
struct Xorriso_lsT *results= NULL, *infos= NULL, *lpt;
*toc_text= NULL;
ret= Xorriso_push_outlists(xorriso, &stack_handle, 1);
if(ret <= 0)
goto ex;
toc_ret= Xorriso_toc(xorriso, flag & (2 | 4));
ret= Xorriso_pull_outlists(xorriso, stack_handle, &results, &infos, 0);
if(ret <= 0)
goto ex;
if(toc_ret <= 0)
{ret= toc_ret; goto ex;}
l= 0;
for(lpt= results; lpt != NULL; lpt= Xorriso_lst_get_next(lpt, 0))
l+= strlen(Xorriso_lst_get_text(lpt, 0));
*toc_text= calloc(l + 1, 1);
l= 0;
for(lpt= results; lpt != NULL; lpt= Xorriso_lst_get_next(lpt, 0)) {
strcpy((*toc_text) + l, Xorriso_lst_get_text(lpt, 0));
l+= strlen(Xorriso_lst_get_text(lpt, 0));
}
ex:;
Xorriso_lst_destroy_all(&results, 0);
Xorriso_lst_destroy_all(&infos, 0);
return(ret);
}
/* @param flag bit0+1= what to give up and/or re-assess in what role
0=give up outdev
1=give up indev if not outdev, re-assess outdev as indev
2=re-assess outdev as outdev
3=give up indev if not outdev, re-assess outdev as dev
*/
int Xorriso_reaquire_outdev(struct XorrisO *xorriso, int flag)
{
int ret, aq_flag;
char *drive_name= NULL, *off_name= NULL;
Xorriso_alloc_meM(drive_name, char, SfileadrL);
Xorriso_alloc_meM(off_name, char, SfileadrL);
aq_flag= flag&3;
strcpy(drive_name, xorriso->outdev);
if(xorriso->outdev_off_adr[0])
strcpy(off_name, xorriso->outdev_off_adr);
else
strcpy(off_name, drive_name);
if(aq_flag == 0) {
Xorriso_give_up_drive(xorriso, 2);
sprintf(xorriso->info_text,"Gave up -outdev ");
Text_shellsafe(xorriso->indev, xorriso->info_text, 1);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
{ret= 1; goto ex;}
}
/* Only give up indev, and only if it is not outdev */;
if(xorriso->in_drive_handle != xorriso->out_drive_handle &&
xorriso->in_drive_handle != NULL && (aq_flag & 1))
Xorriso_give_up_drive(xorriso, 1 | 8);
sprintf(xorriso->info_text,"Re-assessing -outdev ");