libisoburn/xorriso/drive_mgt.c

3611 lines
115 KiB
C
Raw Normal View History

/* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images.
Copyright 2007-2020 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>
2012-05-01 07:49:46 +00:00
#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= set read speed
bit1= set write speed
*/
int Xorriso_set_speed(struct XorrisO *xorriso, struct burn_drive *drive,
int read_speed, int write_speed, int flag)
{
int r_speed = 0, w_speed = 0, ret = 0, profile_no= 0;
char profile_name[80];
if((flag & 3) == 0)
return(0);
if(xorriso->read_speed == -2) {
if(!(flag & 2))
return(0);
}
if(flag & 1)
r_speed= read_speed;
if(flag & 2)
w_speed= write_speed;
ret= burn_disc_get_profile(drive, &profile_no, profile_name);
if(ret <= 0)
profile_no= 0;
if((r_speed > 0 || w_speed > 0) && profile_no >= 0x10) {
ret= burn_drive_set_speed_exact(drive, r_speed, w_speed);
if(ret > 0)
goto ex;
}
burn_drive_set_speed(drive, r_speed, w_speed);
ret= 2;
ex:;
Xorriso_process_msg_queues(xorriso,0);
return(ret);
}
/* @param flag bit0= acquire as isoburn input drive
bit1= acquire as libburn output drive (as isoburn drive if bit0)
bit2= regard overwritable 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 acquiring it
bit7= re-assess rather than acquire:
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;
int truncate_mode;
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;
xorriso->outdev_access= xorriso->indev_access;
}
} else if(out_dinfo != NULL && in_dinfo == NULL) {
dinfo= out_dinfo;
if(flag & 1) {
xorriso->indev_is_exclusive= xorriso->outdev_is_exclusive;
xorriso->indev_access= xorriso->outdev_access;
}
} 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 acquired 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;
xorriso->indev_access= xorriso->outdev_access;
}
} 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;
xorriso->outdev_access= xorriso->indev_access;
}
}
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;
2012-08-14 10:32:35 +00:00
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;
} else if(xorriso->do_aaip & 1024) {
aquire_flag|= 1024;
}
if(flag & 128)
aquire_flag|= 256;
burn_preset_device_open(xorriso->drives_exclusive |
(xorriso->linux_scsi_dev_family << 2), 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 | (xorriso->linux_scsi_dev_family << 2), 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
2016-02-05 14:57:52 +00:00
sprintf(xorriso->info_text,"Cannot acquire drive '%s'", adr);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
ret= 0; goto ex;
}
xorriso->use_immed_bit_default= burn_drive_get_immed(dinfo[0].drive) > 0 ?
1 : -1;
if(xorriso->use_immed_bit != 0)
burn_drive_set_immed(dinfo[0].drive, xorriso->use_immed_bit > 0);
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&(1u<<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;
xorriso->indev_access= xorriso->drives_access;
}
if(flag & 2) {
xorriso->outdev_is_exclusive= xorriso->drives_exclusive;
xorriso->outdev_access= xorriso->drives_access;
}
}
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);
iso_image_unref(volset);
volset= NULL;
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&(1u<<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&(1u<<31))
xorriso->image_start_mode= 0; /* disable msc1 setting completely */
else
xorriso->image_start_mode|= (1u<<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);
volset= NULL;
}
}
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;
xorriso->system_area_clear_loaded=
(strcmp(xorriso->system_area_disk_path, "/dev/zero") == 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;
2012-03-11 16:41:10 +00:00
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;
2015-09-22 15:59:16 +00:00
if(xorriso->read_fs & 1)
ext|= isoburn_ropt_norock;
if(xorriso->read_fs & 2)
ext|= isoburn_ropt_nojoliet;
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;
2015-08-17 20:08:42 +00:00
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;
2020-11-22 13:51:26 +00:00
if(xorriso->joliet_map == 0)
ext|= isoburn_ropt_joliet_unmapped;
else
ext|= isoburn_ropt_joliet_stripped;
2015-08-17 20:08:42 +00:00
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));
2010-11-30 09:43:32 +00:00
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;
}
Xorriso_set_speed(xorriso, drive, xorriso->read_speed, 0, 1);
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);
/* Might have changed due to isofs.nt */
iso_image_get_truncate_mode(volset, &truncate_mode,
&(xorriso->file_name_limit));
Xorriso_process_msg_queues(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_access == 0) {
sprintf(xorriso->info_text,
"Will not eject medium in readonly acquired 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_access == 0) {
sprintf(xorriso->info_text,
"Will not eject medium in readonly acquired drive.");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
do_eject= 0;
}
ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
"on attempt to give up drive", 2);
if(ret >= 0 && !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_access == 1)
return(1);
sprintf(xorriso->info_text, "The output drive was acquired readonly.");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
sprintf(xorriso->info_text, "Possible remedy: -drive_access \"exclusive:unrestricted\".");
strcat(xorriso->info_text," Then give up and re-acquire the drive.");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0);
if(!xorriso->outdev_is_exclusive) {
sprintf(xorriso->info_text, "If you insist in -drive_access \"shared:unrestricted\", first read man xorriso about the risks.");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0)