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.
libisoburn/xorriso/xorrisoburn.c

13086 lines
405 KiB

/* Adapter to libisoburn, libisofs and libburn for xorriso,
a command line oriented batch and dialog tool which creates, loads,
manipulates and burns ISO 9660 filesystem images.
Copyright 2007-2010 Thomas Schmitt, <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#include <ctype.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <fcntl.h>
#include <utime.h>
#include <sys/wait.h>
#include <pwd.h>
#include <grp.h>
/* for -charset */
#include <iconv.h>
#include <langinfo.h>
/* ------------------------------------------------------------------------ */
#ifndef Xorriso_standalonE
/* The library which does the ISO 9660 / RockRidge manipulations */
#include <libisofs/libisofs.h>
/* The library which does MMC optical drive operations */
#include <libburn/libburn.h>
/* The library which enhances overwriteable media with ISO 9660 multi-session
capabilities via the method invented by Andy Polyakov for growisofs */
#include <libisoburn/libisoburn.h>
/* The official xorriso options API. "No shortcuts" */
#include "xorriso.h"
/* The inner description of XorrisO */
#include "xorriso_private.h"
/* The inner isofs- and burn-library interface */
#include "xorrisoburn.h"
#else /* ! Xorriso_standalonE */
#include "../libisofs/libisofs.h"
#include "../libburn/libburn.h"
#include "../libisoburn/libisoburn.h"
#include "xorriso.h"
#include "xorriso_private.h"
#include "xorrisoburn.h"
#endif /* Xorriso_standalonE */
/* Some private in advance declarations */
int Xorriso_pacifier_loop(struct XorrisO *xorriso, struct burn_drive *drive,
int flag);
int Xorriso__read_pacifier(IsoImage *image, IsoFileSource *filesource);
int Xorriso_tree_graft_node(struct XorrisO *xorriso, IsoImage *volume,
IsoDir *dir, char *disk_path, char *img_name,
char *nominal_source, char *nominal_target,
off_t offset, off_t cut_size,
IsoNode **node, int flag);
int Xorriso_findi_iter(struct XorrisO *xorriso, IsoDir *dir_node, off_t *mem,
IsoDirIter **iter,
IsoNode ***node_array, int *node_count, int *node_idx,
IsoNode **iterated_node, int flag);
int Xorriso__file_start_lba(IsoNode *node, int *lba, int flag);
int Xorriso_read_file_data(struct XorrisO *xorriso, IsoNode *node,
char *img_path, char *disk_path,
off_t img_offset, off_t disk_offset,
off_t bytes, int flag);
int Xorriso_path_from_node(struct XorrisO *xorriso, IsoNode *in_node,
char path[SfileadrL], int flag);
int Xorriso_node_from_path(struct XorrisO *xorriso, IsoImage *volume,
char *path, IsoNode **node, int flag);
int Xorriso_path_from_lba(struct XorrisO *xorriso, IsoNode *node, int lba,
char path[SfileadrL], int flag);
int Xorriso__node_lba_cmp(const void *node1, const void *node2);
int Xorriso_search_hardlinks(struct XorrisO *xorriso, IsoNode *node,
int *node_idx, int *min_hl, int *max_hl, int flag);
#define LIBISO_ISDIR(node) (iso_node_get_type(node) == LIBISO_DIR)
#define LIBISO_ISREG(node) (iso_node_get_type(node) == LIBISO_FILE)
#define LIBISO_ISLNK(node) (iso_node_get_type(node) == LIBISO_SYMLINK)
#define LIBISO_ISCHR(node) (iso_node_get_type(node) == LIBISO_SPECIAL && \
S_ISCHR(iso_node_get_mode(node)))
#define LIBISO_ISBLK(node) (iso_node_get_type(node) == LIBISO_SPECIAL && \
S_ISBLK(iso_node_get_mode(node)))
#define LIBISO_ISFIFO(node) (iso_node_get_type(node) == LIBISO_SPECIAL && \
S_ISFIFO(iso_node_get_mode(node)))
#define LIBISO_ISSOCK(node) (iso_node_get_type(node) == LIBISO_SPECIAL && \
S_ISSOCK(iso_node_get_mode(node)))
#define LIBISO_ISBOOT(node) (iso_node_get_type(node) == LIBISO_BOOT)
/* CD specs say one shall not write tracks < 600 kiB */
#define Xorriso_cd_min_track_sizE 300
/* Default setting for -compliance */
#define Xorriso_relax_compliance_defaulT \
(isoburn_igopt_allow_deep_paths | isoburn_igopt_allow_longer_paths | \
isoburn_igopt_always_gmt | \
isoburn_igopt_rrip_version_1_10 | isoburn_igopt_aaip_susp_1_10 )
#ifdef NIX
/* <<< */
unsigned long Xorriso_get_di_counteR= 0;
#endif /* NIX */
/* ------------------------------------------------------------------------ */
static const char *un0(const char *text)
{
if(text == NULL)
return("");
return(text);
}
int Xorriso_abort(struct XorrisO *xorriso, int flag)
{
int ret;
ret= burn_abort(4440, burn_abort_pacifier, "xorriso : ");
if(ret<=0) {
fprintf(stderr,
"\nxorriso : ABORT : Cannot cancel burn session and release drive.\n");
return(0);
}
fprintf(stderr,
"xorriso : ABORT : Drive is released and library is shut down now.\n");
fprintf(stderr,
"xorriso : ABORT : Program done. Even if you do not see a shell prompt.\n");
fprintf(stderr, "\n");
exit(1);
}
int Xorriso_destroy_node_array(struct XorrisO *xorriso, int flag)
{
int i;
if(xorriso->node_array != NULL) {
for(i= 0; i < xorriso->node_counter; i++)
iso_node_unref((IsoNode *) xorriso->node_array[i]);
free(xorriso->node_array);
}
xorriso->node_array= NULL;
xorriso->node_counter= xorriso->node_array_size= 0;
Xorriso_lst_destroy_all(&(xorriso->node_disk_prefixes), 0);
Xorriso_lst_destroy_all(&(xorriso->node_img_prefixes), 0);
return(1);
}
/* @param flag bit0= do not destroy hln_array but only hln_targets
*/
int Xorriso_destroy_hln_array(struct XorrisO *xorriso, int flag)
{
int i;
if(xorriso->hln_array != NULL && !(flag & 1)) {
for(i= 0; i < xorriso->hln_count; i++)
iso_node_unref((IsoNode *) xorriso->hln_array[i]);
free(xorriso->hln_array);
xorriso->hln_array= NULL;
xorriso->hln_count= 0;
}
if(xorriso->hln_targets != NULL) {
for(i= 0; i < xorriso->hln_count; i++)
if(xorriso->hln_targets[i] != NULL)
free(xorriso->hln_targets[i]);
free(xorriso->hln_targets);
xorriso->hln_targets= NULL;
}
xorriso->node_targets_availmem= 0;
return(1);
}
int Xorriso_destroy_di_array(struct XorrisO *xorriso, int flag)
{
int i;
if(xorriso->di_array != NULL) {
for(i= 0; i < xorriso->di_count; i++)
if(xorriso->di_array[i] != NULL)
iso_node_unref((IsoNode *) xorriso->di_array[i]);
free(xorriso->di_array);
xorriso->di_array= NULL;
}
if(xorriso->di_do_widen != NULL) {
free(xorriso->di_do_widen);
xorriso->di_do_widen= NULL;
}
Xorriso_lst_destroy_all(&(xorriso->di_disk_paths), 0);
Xorriso_lst_destroy_all(&(xorriso->di_iso_paths), 0);
xorriso->di_count= 0;
#ifdef NIX
/* <<< */
fprintf(stderr, "xorriso_DEBUG: get_di_count= %lu\n",
Xorriso_get_di_counteR);
#endif /* NIX */
return(1);
}
int Xorriso_new_node_array(struct XorrisO *xorriso, off_t mem_limit,
int addon_nodes, int flag)
{
int i;
if(xorriso->node_counter <= 0)
return(1);
xorriso->node_array= calloc(xorriso->node_counter + addon_nodes,
sizeof(IsoNode *));
if(xorriso->node_array == NULL) {
Xorriso_no_malloc_memory(xorriso, NULL, 0);
return(-1);
}
for(i= 0; i < xorriso->node_counter + addon_nodes; i++)
xorriso->node_array[i]= NULL;
xorriso->node_array_size= xorriso->node_counter + addon_nodes;
xorriso->node_counter= 0;
return(1);
}
/* @param flag bit0= do not allocate hln_array but only hln_targets
*/
int Xorriso_new_hln_array(struct XorrisO *xorriso, off_t mem_limit, int flag)
{
int i;
Xorriso_destroy_hln_array(xorriso, flag & 1);
if(xorriso->hln_count <= 0)
return(1);
if(!(flag & 1)) {
xorriso->hln_array= calloc(xorriso->hln_count, sizeof(char *));
if(xorriso->hln_array == NULL) {
Xorriso_no_malloc_memory(xorriso, NULL, 0);
return(-1);
}
for(i= 0; i < xorriso->hln_count; i++)
xorriso->hln_array[i]= NULL;
}
xorriso->hln_targets= calloc(xorriso->hln_count, sizeof(char *));
if(xorriso->hln_targets == NULL) {
if(!(flag & 1)) {
free(xorriso->hln_array);
xorriso->hln_array= NULL;
}
Xorriso_no_malloc_memory(xorriso, NULL, 0);
return(-1);
}
for(i= 0; i < xorriso->hln_count; i++)
xorriso->hln_targets[i]= NULL;
xorriso->node_targets_availmem= mem_limit
- xorriso->hln_count * sizeof(void *)
- xorriso->hln_count * sizeof(char *);
if(xorriso->node_targets_availmem < 0)
xorriso->node_targets_availmem= 0;
return(1);
}
int Xorriso__findi_sorted_ino_cmp(const void *p1, const void *p2)
{
int ret;
IsoNode *n1, *n2;
n1= *((IsoNode **) p1);
n2= *((IsoNode **) p2);
ret= Xorriso__node_lba_cmp(&n1, &n2);
if(ret)
return (ret > 0 ? 1 : -1);
ret= iso_node_cmp_ino(n1, n2, 0);
return(ret);
}
/* Not suitable for qsort() but for cross-array comparisons.
p1 and p2 are actually IsoNode *p1, IsoNode *p2
*/
int Xorriso__hln_cmp(const void *p1, const void *p2)
{
int ret;
ret= Xorriso__findi_sorted_ino_cmp(&p1, &p2);
if(ret)
return (ret > 0 ? 1 : -1);
if(p1 != p2)
return(p1 < p2 ? -1 : 1);
return(0);
}
/*
p1 and p2 are actually IsoNode **p1, IsoNode **p2
*/
int Xorriso__findi_sorted_cmp(const void *p1, const void *p2)
{
int ret;
ret= Xorriso__findi_sorted_ino_cmp(p1, p2);
if(ret)
return (ret > 0 ? 1 : -1);
if(p1 != p2)
return(p1 < p2 ? -1 : 1);
return(0);
}
int Xorriso_sort_node_array(struct XorrisO *xorriso, int flag)
{
if(xorriso->node_counter <= 0)
return(0);
qsort(xorriso->node_array, xorriso->node_counter, sizeof(IsoNode *),
Xorriso__findi_sorted_cmp);
return(1);
}
int Xorriso__search_node(void *node_array[], int n,
int (*cmp)(const void *p1, const void *p2),
void *node, int *idx, int flag)
{
int ret, l, r, p, pos;
if(n == 0)
return(0);
l= 0;
r= n + 1;
while(1) {
p= (r - l) / 2;
if(p == 0)
break;
p+= l;
/* NULL elements may indicate invalid nodes. Their first valid right neigbor
will serve as proxy. If none exists, then the test pushes leftwards.
*/
for(pos= p - 1; pos < n; pos++)
if(node_array[pos] != NULL)
break;
if(pos < n)
ret= (*cmp)(&(node_array[pos]), &node);
else
ret= 1;
if(ret < 0)
l= p;
else if(ret > 0)
r= p;
else {
*idx= pos;
return(1);
}
}
return(0);
}
int Xorriso_search_in_hln_array(struct XorrisO *xorriso,
void *node, int *idx, int flag)
{
int ret;
if(xorriso->hln_array == NULL || xorriso->hln_count <= 0)
return(0);
ret= Xorriso__search_node(xorriso->hln_array, xorriso->hln_count,
Xorriso__findi_sorted_ino_cmp, node, idx, 0);
return ret;
}
int Xorriso__get_di(IsoNode *node, dev_t *dev, ino_t *ino, int flag)
{
int ret, i, i_end, imgid, error_code;
size_t value_length= 0;
char *value= NULL, msg[ISO_MSGS_MESSAGE_LEN], severity[80];
unsigned char *vpt;
static char *name= "isofs.di";
#ifdef NIX
/* <<< */
Xorriso_get_di_counteR++;
#endif /* NIX */
*dev= 0;
*ino= 0;
ret= iso_node_lookup_attr(node, name, &value_length, &value, 0);
if(ret <= 0) {
/* Drop any pending messages because there is no xorriso to take them */
iso_obtain_msgs("NEVER", &error_code, &imgid, msg, severity);
return(ret);
}
vpt= (unsigned char *) value;
for(i= 1; i <= vpt[0] && i < value_length; i++)
*dev= ((*dev) << 8) | vpt[i];
i_end= i + vpt[i] + 1;
for(i++; i < i_end && i < value_length; i++)
*ino= ((*ino) << 8) | vpt[i];
free(value);
return(1);
}
int Xorriso__di_ino_cmp(const void *p1, const void *p2)
{
int ret;
IsoNode *n1, *n2;
dev_t d1, d2;
ino_t i1, i2;
n1= *((IsoNode **) p1);
n2= *((IsoNode **) p2);
ret= Xorriso__get_di(n1, &d1, &i1, 0);
if(ret <= 0)
{d1= 0; i1= 0;}
ret= Xorriso__get_di(n2, &d2, &i2, 0);
if(ret <= 0)
{d2= 0; i2= 0;}
if(d1 < d2)
return(-1);
if(d1 > d2)
return(1);
if(i1 < i2)
return(-1);
if(i1 > i2)
return(1);
if(d1 == 0 && i1 == 0 && n1 != n2)
return(n1 < n2 ? -1 : 1);
return(0);
}
int Xorriso__di_cmp(const void *p1, const void *p2)
{
int ret;
IsoNode *n1, *n2;
ret= Xorriso__di_ino_cmp(p1, p2);
if(ret)
return(ret);
n1= *((IsoNode **) p1);
n2= *((IsoNode **) p2);
if(n1 != n2)
return(n1 < n2 ? -1 : 1);
return(0);
}
int Xorriso__sort_di(void *node_array[], int count, int flag)
{
if(count <= 0)
return(0);
qsort(node_array, count, sizeof(IsoNode *), Xorriso__di_cmp);
return(1);
}
int Xorriso_invalidate_di_item(struct XorrisO *xorriso, IsoNode *node,
int flag)
{
int ret, idx;
if(xorriso->di_array == NULL)
return(1);
ret= Xorriso__search_node(xorriso->di_array, xorriso->di_count,
Xorriso__di_cmp, node, &idx, 0);
if(ret <= 0)
return(ret == 0);
if(xorriso->di_array[idx] != NULL)
iso_node_unref(xorriso->di_array[idx]);
xorriso->di_array[idx]= NULL;
return(1);
}
/* @param flag bit0= return 1 even if matching nodes were found but node is
not among them
bit1= use Xorriso__di_cmp() rather than Xorriso__di_ino_cmp()
*/
int Xorriso_search_di_range(struct XorrisO *xorriso, IsoNode *node,
int *idx, int *low, int *high, int flag)
{
int ret, i, found;
int (*cmp)(const void *p1, const void *p2)= Xorriso__di_ino_cmp;
if(flag & 2)
cmp= Xorriso__di_cmp;
*high= *low= *idx= -1;
ret= Xorriso__search_node(xorriso->di_array, xorriso->di_count,
cmp, node, &found, 0);
if(ret <= 0)
return(0);
*low= *high= found;
for(i= found + 1; i < xorriso->di_count; i++)
if(xorriso->di_array[i] != NULL) {
if((*cmp)(&node, &(xorriso->di_array[i])) != 0)
break;
*high= i;
}
for(i= found - 1; i >= 0; i--)
if(xorriso->di_array[i] != NULL) {
if((*cmp)(&node, &(xorriso->di_array[i])) != 0)
break;
*low= i;
}
for(i= *low; i <= *high; i++)
if(xorriso->di_array[i] == node) {
*idx= i;
break;
}
return(*idx >= 0 || (flag & 1));
}
/* ------------------------------------------------------------------------ */
/* @param flag bit0= asynchronous handling (else catch thread, wait, and exit)
*/
int Xorriso_set_signal_handling(struct XorrisO *xorriso, int flag)
{
char *handler_prefix= NULL;
if(Xorriso__get_signal_behavior(0) != 1)
return(2);
handler_prefix= calloc(strlen(xorriso->progname)+3+1, 1);
if(handler_prefix==NULL) {
sprintf(xorriso->info_text,
"Cannot allocate memory for for setting signal handler");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
return(-1);
}
sprintf(handler_prefix, "%s : ", xorriso->progname);
burn_set_signal_handling(handler_prefix, NULL, (flag & 1) * 0x30);
free(handler_prefix);
return(1);
}
int Xorriso_startup_libraries(struct XorrisO *xorriso, int flag)
{
int ret, major, minor, micro;
char *queue_sev, *print_sev, reason[1024];
struct iso_zisofs_ctrl zisofs_ctrl= {0, 6, 15};
/* First an ugly compile time check for header version compatibility.
If everthing matches, then no C code is produced. In case of mismatch,
intentionally faulty C code will be inserted.
*/
/* The minimum requirement of xorriso towards the libisoburn header
at compile time is defined in xorriso/xorrisoburn.h
xorriso_libisoburn_req_major
xorriso_libisoburn_req_minor
xorriso_libisoburn_req_micro
It gets compared against the version macros in libburn/libburn.h :
isoburn_header_version_major
isoburn_header_version_minor
isoburn_header_version_micro
If the header is too old then the following code shall cause failure of
cdrskin compilation rather than to allow production of a program with
unpredictable bugs or memory corruption.
The compiler messages supposed to appear in this case are:
error: 'LIBISOBURN_MISCONFIGURATION' undeclared (first use in this function)
error: 'INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libisoburn_dot_h_TOO_OLD__SEE_xorrisoburn_dot_c' undeclared (first use in this function)
error: 'LIBISOBURN_MISCONFIGURATION_' undeclared (first use in this function)
*/
/* The indendation is an advise of man gcc to help old compilers ignoring */
#if xorriso_libisoburn_req_major > isoburn_header_version_major
#define Isoburn_libisoburn_dot_h_too_olD 1
#endif
#if xorriso_libisoburn_req_major == isoburn_header_version_major && xorriso_libisoburn_req_minor > isoburn_header_version_minor
#define Isoburn_libisoburn_dot_h_too_olD 1
#endif
#if xorriso_libisoburn_req_minor == isoburn_header_version_minor && xorriso_libisoburn_req_micro > isoburn_header_version_micro
#define Isoburn_libisoburn_dot_h_too_olD 1
#endif
#ifdef Isoburn_libisoburn_dot_h_too_olD
LIBISOBURN_MISCONFIGURATION = 0;
INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libisoburn_dot_h_TOO_OLD__SEE_xorrisoburn_dot_c = 0;
LIBISOBURN_MISCONFIGURATION_ = 0;
#endif
/* End of ugly compile time test (scroll up for explanation) */
reason[0]= 0;
ret= isoburn_initialize(reason, 0);
if(ret==0) {
sprintf(xorriso->info_text, "Cannot initialize libraries");
if(reason[0])
sprintf(xorriso->info_text+strlen(xorriso->info_text),
". Reason given:\n%s", reason);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
return(0);
}
ret= isoburn_is_compatible(isoburn_header_version_major,
isoburn_header_version_minor,
isoburn_header_version_micro, 0);
if(ret<=0) {
isoburn_version(&major, &minor, &micro);
sprintf(xorriso->info_text,
"libisoburn version too old: %d.%d.%d . Need at least: %d.%d.%d .\n",
major, minor, micro,
isoburn_header_version_major, isoburn_header_version_minor,
isoburn_header_version_micro);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
return(-1);
}
xorriso->libs_are_started= 1;
queue_sev= "ALL";
if(xorriso->library_msg_direct_print) {
/* >>> need option for controlling this in XorrisO.
See also Xorriso_msgs_submit */;
print_sev= xorriso->report_about_text;
} else
print_sev= "NEVER";
iso_set_msgs_severities(queue_sev, print_sev, "libsofs : ");
burn_msgs_set_severities(queue_sev, print_sev, "libburn : ");
/* ??? >>> do we want united queues ? */
/* burn_set_messenger(iso_get_messenger()); */
isoburn_set_msgs_submit(Xorriso_msgs_submit_void, (void *) xorriso,
(3<<2) | 128 , 0);
ret= Xorriso_set_signal_handling(xorriso, 0);
if(ret <= 0)
return(ret);
ret = iso_zisofs_get_params(&zisofs_ctrl, 0);
if (ret == 1) {
xorriso->zisofs_block_size= xorriso->zisofs_block_size_default=
(1 << zisofs_ctrl.block_size_log2);
xorriso->zlib_level= xorriso->zlib_level_default=
zisofs_ctrl.compression_level;
}
Xorriso_process_msg_queues(xorriso,0);
if(reason[0]) {
sprintf(xorriso->info_text, "%s", reason);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
}
strcpy(xorriso->info_text, "Using ");
strncat(xorriso->info_text, burn_scsi_transport_id(0), 1024);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0);
return(1);
}
/* @param flag bit0= global shutdown of libraries */
int Xorriso_detach_libraries(struct XorrisO *xorriso, int flag)
{
Xorriso_give_up_drive(xorriso, 3);
if(xorriso->in_volset_handle!=NULL) { /* standalone image */
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);
}
if(flag&1) {
if(xorriso->libs_are_started==0)
return(0);
isoburn_finish();
}
return(1);
}
/* @param flag
bit0= if not MMC drive print NOTE and return 2
bit1= obtain outdrive, else indrive
bit4= do not report failure
*/
int Xorriso_get_drive_handles(struct XorrisO *xorriso,
struct burn_drive_info **dinfo,
struct burn_drive **drive,
char *attempt, int flag)
{
int ret;
if(flag&2)
*dinfo= (struct burn_drive_info *) xorriso->out_drive_handle;
else
*dinfo= (struct burn_drive_info *) xorriso->in_drive_handle;
if(*dinfo==NULL && !(flag & 16)) {
Xorriso_process_msg_queues(xorriso,0);
sprintf(xorriso->info_text, "No %s drive aquired %s",
(flag&2 ? "output" : "input"), attempt);
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
}
if(*dinfo==NULL)
return(0);
*drive= (*dinfo)[0].drive;
if(flag & 1) {
ret= burn_drive_get_drive_role(*drive);
if(ret != 1) {
sprintf(xorriso->info_text,
"Output device is not an MMC drive. Desired operation does not apply.");
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
return(2);
}
}
return((*drive)!=NULL);
}
int Xorriso__sev_to_text(int severity, char **severity_name,
int flag)
{
int ret;
ret= iso_sev_to_text(severity, severity_name);
if(ret>0)
return(ret);
ret= burn_sev_to_text(severity, severity_name, 0);
if(ret>0)
return(ret);
*severity_name= "";
return(0);
}
int Xorriso__text_to_sev(char *severity_name, int *severity_number, int flag)
{
int ret= 1;
ret= iso_text_to_sev(severity_name, severity_number);
if(ret>0)
return(ret);
ret= burn_text_to_sev(severity_name, severity_number, 0);
return(ret);
}
/* @param flag bit0= report libisofs error text
bit1= victim is disk_path
bit2= do not inquire libisofs, report msg_text and min_severity
*/
int Xorriso_report_iso_error(struct XorrisO *xorriso, char *victim,
int iso_error_code, char msg_text[], int os_errno,
char min_severity[], int flag)
{
int error_code, iso_sev, min_sev, ret;
char *sev_text_pt, *msg_text_pt= NULL;
char sfe[6*SfileadrL];
static int sorry_sev= -1;
if(sorry_sev<0)
Xorriso__text_to_sev("SORRY", &sorry_sev, 0);
if(flag&4) {
error_code= 0x00050000;
Xorriso__text_to_sev(min_severity, &iso_sev, 0);
} else {
error_code= iso_error_get_code(iso_error_code);
if(error_code < 0x00030000 || error_code >= 0x00040000)
error_code= (error_code & 0xffff) | 0x00050000;
if(flag&1)
msg_text_pt= (char *) iso_error_to_msg(iso_error_code);
iso_sev= iso_error_get_severity(iso_error_code);
}
if(msg_text_pt==NULL)
msg_text_pt= msg_text;
if(iso_sev >= sorry_sev && (flag & 2) && victim[0])
Xorriso_msgs_submit(xorriso, 0, victim, 0, "ERRFILE", 0);
sev_text_pt= min_severity;
Xorriso__text_to_sev(min_severity, &min_sev, 0);
if(min_sev < iso_sev && !(flag&4))
Xorriso__sev_to_text(iso_sev, &sev_text_pt, 0);
strcpy(sfe, msg_text_pt);
if(victim[0]) {
strcat(sfe, ": ");
Text_shellsafe(victim, sfe+strlen(sfe), 0);
}
ret= Xorriso_msgs_submit(xorriso, error_code, sfe, os_errno, sev_text_pt, 4);
return(ret);
}
/* @param flag bit0= suppress messages below UPDATE
bit1= suppress messages below FAILURE
*/
int Xorriso_set_image_severities(struct XorrisO *xorriso, int flag)
{
char *queue_sev, *print_sev;
if(flag&2)
queue_sev= "FAILURE";
else if(flag&1)
queue_sev= "UPDATE";
else
queue_sev= "ALL";
if(xorriso->library_msg_direct_print)
print_sev= xorriso->report_about_text;
else
print_sev= "NEVER";
iso_set_msgs_severities(queue_sev, print_sev, "libisofs : ");
return(1);
}
int Xorriso_update_volid(struct XorrisO *xorriso, int flag)
{
int gret, sret= 1;
gret= Xorriso_get_volid(xorriso, xorriso->loaded_volid, 0);
if(gret<=0 || (!xorriso->volid_default) || xorriso->loaded_volid[0]==0)
sret= Xorriso_set_volid(xorriso, xorriso->volid, 1);
return(gret>0 && sret>0);
}
int Xorriso_create_empty_iso(struct XorrisO *xorriso, int flag)
{
int ret;
IsoImage *volset;
struct isoburn_read_opts *ropts;
struct burn_drive_info *dinfo= NULL;
struct burn_drive *drive= NULL;
if(xorriso->out_drive_handle != NULL) {
ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive,
"on attempt to attach volset to drive", 2);
if(ret<=0)
return(ret);
}
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->volset_change_pending= 0;
xorriso->no_volset_present= 0;
}
ret= isoburn_ropt_new(&ropts, 0);
if(ret<=0)
return(ret);
/* Note: no return before isoburn_ropt_destroy() */
isoburn_ropt_set_extensions(ropts, isoburn_ropt_pretend_blank);
isoburn_ropt_set_input_charset(ropts, xorriso->in_charset);
isoburn_set_read_pacifier(drive, NULL, NULL);
ret= isoburn_read_image(drive, ropts, &volset);
Xorriso_process_msg_queues(xorriso,0