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.
13001 lines
402 KiB
13001 lines
402 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-2009 Thomas Schmitt, <scdbackup@gmx.net> |
|
|
|
Provided under GPL version 2. |
|
*/ |
|
|
|
#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_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)); |
|
} |
|
|
|
|
|
/* ------------------------------------------------------------------------ */ |
|
|
|
|
|
int Xorriso_startup_libraries(struct XorrisO *xorriso, int flag) |
|
{ |
|
int ret, major, minor, micro; |
|
char *handler_prefix= NULL; |
|
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) */ |
|
|
|
handler_prefix= calloc(strlen(xorriso->progname)+3+1, 1); |
|
if(handler_prefix==NULL) { |
|
sprintf(xorriso->info_text, |
|
"Cannot allocate memory for initializing libraries"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); |
|
return(-1); |
|
} |
|
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); |
|
free(handler_prefix); |
|
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, µ); |
|
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); |
|
|
|
sprintf(handler_prefix, "%s : ", xorriso->progname); |
|
burn_set_signal_handling(handler_prefix, NULL, 0); |
|
|
|
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); |
|
} |
|
free(handler_prefix); |
|
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); |
|
isoburn_ropt_destroy(&ropts, 0); |
|
if(ret<=0) { |
|
sprintf(xorriso->info_text, "Failed to create new empty ISO image object"); |
|
Xorriso_report_iso_error(xorriso, "", ret, xorriso->info_text, 0, "FATAL", |
|
0); |
|
return(-1); |
|
} |
|
xorriso->in_volset_handle= (void *) volset; |
|
xorriso->in_sector_map= NULL; |
|
Xorriso_update_volid(xorriso, 0); |
|
xorriso->volset_change_pending= 0; |
|
xorriso->no_volset_present= 0; |
|
return(1); |
|
} |
|
|
|
|
|
int Xorriso_record_boot_info(struct XorrisO *xorriso, int flag) |
|
{ |
|
int ret; |
|
struct burn_drive_info *dinfo; |
|
struct burn_drive *drive; |
|
IsoImage *image; |
|
ElToritoBootImage *bootimg; |
|
IsoFile *bootimg_node; |
|
IsoBoot *bootcat_node; |
|
|
|
xorriso->loaded_boot_bin_lba= -1; |
|
xorriso->loaded_boot_cat_path[0]= 0; |
|
ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, |
|
"on attempt to record boot LBAs", 0); |
|
if(ret<=0) |
|
return(0); |
|
image= isoburn_get_attached_image(drive); |
|
if(image == NULL) |
|
return(0); |
|
ret= iso_image_get_boot_image(image, &bootimg, |
|
&bootimg_node, &bootcat_node); |
|
iso_image_unref(image); /* release obtained reference */ |
|
if(ret != 1) |
|
return(0); |
|
if(bootimg_node != NULL) |
|
Xorriso__file_start_lba((IsoNode *) bootimg_node, |
|
&(xorriso->loaded_boot_bin_lba), 0); |
|
if(bootcat_node != NULL) |
|
Xorriso_path_from_lba(xorriso, (IsoNode *) bootcat_node, 0, |
|
xorriso->loaded_boot_cat_path, 0); |
|
return(1); |
|
} |
|
|
|
|
|
int Xorriso_assert_volid(struct XorrisO *xorriso, int msc1, int flag) |
|
{ |
|
int ret, image_blocks; |
|
char volid[33]; |
|
struct burn_drive_info *dinfo; |
|
struct burn_drive *drive; |
|
|
|
if(xorriso->assert_volid[0] == 0) |
|
return(1); |
|
ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, |
|
"on attempt to perform -assert_volid", 0); |
|
if(ret<=0) |
|
return(0); |
|
ret= isoburn_read_iso_head(drive, msc1, &image_blocks, volid, 1); |
|
Xorriso_process_msg_queues(xorriso,0); |
|
if(ret <= 0) { |
|
sprintf(xorriso->info_text, |
|
"-assert_volid: Cannot determine Volume Id at LBA %d.", msc1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, |
|
xorriso->assert_volid_sev, 0); |
|
return(0); |
|
} |
|
ret= Sregex_match(xorriso->assert_volid, volid, 0); |
|
if(ret < 0) |
|
return(2); |
|
if(ret == 0) { |
|
strcpy(xorriso->info_text, |
|
"-assert_volid: Volume id does not match pattern: "); |
|
Text_shellsafe(xorriso->assert_volid, xorriso->info_text, 1); |
|
strcat(xorriso->info_text, " <> "); |
|
Text_shellsafe(volid, xorriso->info_text, 1); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, |
|
xorriso->assert_volid_sev, 0); |
|
return(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 |
|
@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, 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; |
|
uint32_t size; |
|
struct burn_drive_info *dinfo= NULL, *out_dinfo, *in_dinfo; |
|
struct burn_drive *drive, *out_drive, *in_drive; |
|
enum burn_disc_status state; |
|
IsoImage *volset = NULL; |
|
IsoNode *root_node; |
|
struct isoburn_read_opts *ropts= NULL; |
|
char libburn_adr[SfileadrL], *boot_fate, *sev; |
|
size_t value_length; |
|
char *value= NULL; |
|
double num; |
|
char volid[33], adr_data[163], *adr_pt; |
|
|
|
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); |
|
return(-1); |
|
} |
|
ret= Xorriso_give_up_drive(xorriso, (flag&3)|8); |
|
if(ret<=0) |
|
return(ret); |
|
if(flag & 1) |
|
xorriso->isofs_st_out= time(0) - 1; |
|
|
|
ret= Xorriso_auto_driveadr(xorriso, adr, libburn_adr, 0); |
|
if(ret <= 0) |
|
return(ret); |
|
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&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) { |
|
aquire_flag= 1 | ((flag&(8|4))>>1) | ((xorriso->toc_emulation_flag & 3)<<3); |
|
if(xorriso->toc_emulation_flag & 4) |
|
aquire_flag|= 128; |
|
if(!(xorriso->do_aaip & 1)) |
|
aquire_flag|= 32; |
|
if((xorriso->ino_behavior & (1 | 2)) && !(xorriso->do_aaip & (4 | 32))) |
|
aquire_flag|= 64; |
|
burn_preset_device_open(xorriso->drives_exclusive, 0, 0); |
|
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) { |
|
sprintf(xorriso->info_text,"Cannot aquire drive '%s'", adr); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
ret= 0; goto ex; |
|
} |
|
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; |
|
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 */ |
|
} |
|
} |
|
state= isoburn_disc_get_status(drive); |
|
Xorriso_process_msg_queues(xorriso,0); |
|
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, adr, 0)<=0) |
|
{ret= -1; goto ex;} |
|
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, adr, 0)<=0) |
|
{ret= -1; goto ex;} |
|
} 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); |
|
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(!(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); |
|
|
|
/* 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"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "SORRY", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
/* fill read opts */ |
|
ret= isoburn_ropt_new(&ropts, 0); |
|
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)) |
|
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; |
|
|
|
#ifdef isoburn_ropt_nomd5 |
|
if(!(xorriso->do_md5 & 1)) |
|
ext|= isoburn_ropt_nomd5; |
|
#endif |
|
|
|
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)); |
|
|
|
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; |
|
} |
|
|
|
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 == ISO_SB_TREE_CORRUPTED && (xorriso->do_md5 & 1)) { |
|
Xorriso_msgs_submit(xorriso, 0, |
|
"You might get a questionable ISO image tree by option -md5 '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; |
|
|
|
/* <<< can be removed as soon as libisofs-0.6.24 is mandatory |
|
*/ |
|
if(strcmp(un0(iso_image_get_copyright_file_id(volset)), "_") == 0 && |
|
strcmp(un0(iso_image_get_abstract_file_id(volset)), "_") == 0 && |
|
strcmp(un0(iso_image_get_biblio_file_id(volset)), "_") == 0) { |
|
/* This is bug output from libisofs <= 0.6.23 . The texts mean file names |
|
and should have been empty to indicate that there are no such files. |
|
It is obvious that not all three roles can be fulfilled by one file "_" |
|
so that one cannot spoil anything by assuming them empty now. |
|
Modern versions of libisofs are supposed to do this themselves. |
|
*/ |
|
iso_image_set_copyright_file_id(volset, ""); |
|
iso_image_set_abstract_file_id(volset, ""); |
|
iso_image_set_biblio_file_id(volset, ""); |
|
} |
|
|
|
if(xorriso->out_drive_handle != NULL && |
|
xorriso->out_drive_handle != xorriso->in_drive_handle) { |
|
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); |
|
} |
|
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 an isolinux image"; |
|
else if(xorriso->patch_isolinux_image) |
|
boot_fate= "patched as isolinux image"; |
|
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) { |
|
/* 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(!(flag&32)) { |
|
Xorriso_toc(xorriso, 1 | 8); |
|
if(xorriso->loaded_volid[0]!=0) { |
|
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((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); |
|
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; |
|
char sfe[5*SfileadrL]; |
|
|
|
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 %s", |
|
Text_shellsafe(xorriso->indev, sfe, 0)); |
|
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 media 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; |
|
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 media 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; |
|
} 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_make_write_options( |
|
struct XorrisO *xorriso, struct burn_drive *drive, |
|
struct burn_write_opts **burn_options, int flag) |
|
{ |
|
int drive_role, stream_mode= 0; |
|
|
|
*burn_options= burn_write_opts_new(drive); |
|
if(*burn_options==NULL) { |
|
Xorriso_process_msg_queues(xorriso,0); |
|
sprintf(xorriso->info_text,"Cannot allocate option set"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
return(0); |
|
} |
|
burn_write_opts_set_simulate(*burn_options, !!xorriso->do_dummy); |
|
drive_role= burn_drive_get_drive_role(drive); |
|
burn_write_opts_set_multi(*burn_options, |
|
!(xorriso->do_close || drive_role==0 || drive_role==3)); |
|
burn_drive_set_speed(drive, xorriso->speed, xorriso->speed); |
|
if(xorriso->do_stream_recording == 1) |
|
stream_mode= 1; |
|
else if(xorriso->do_stream_recording == 2) |
|
stream_mode= 51200; /* 100 MB */ |
|
else if(xorriso->do_stream_recording >= 16) |
|
stream_mode= xorriso->do_stream_recording; |
|
burn_write_opts_set_stream_recording(*burn_options, stream_mode); |
|
|
|
#ifdef Xorriso_dvd_obs_default_64K |
|
if(xorriso->dvd_obs == 0) |
|
burn_write_opts_set_dvd_obs(*burn_options, 64 * 1024); |
|
else |
|
#endif |
|
burn_write_opts_set_dvd_obs(*burn_options, xorriso->dvd_obs); |
|
|
|
burn_write_opts_set_stdio_fsync(*burn_options, xorriso->stdio_sync); |
|
burn_write_opts_set_underrun_proof(*burn_options, 1); |
|
return(1); |
|
} |
|
|
|
|
|
/* @param flag bit0= do not write but only prepare and return size in sectors |
|
bit1= do not use isoburn wrappers |
|
*/ |
|
int Xorriso_sanitize_image_size(struct XorrisO *xorriso, |
|
struct burn_drive *drive, struct burn_disc *disc, |
|
struct burn_write_opts *burn_options, int flag) |
|
{ |
|
int ret, img_sectors, num_sessions= 0, num_tracks= 0, padding= 0, profile; |
|
int media_space, lba, nwa; |
|
char profile_name[80]; |
|
struct burn_session **sessions; |
|
struct burn_track **tracks; |
|
|
|
img_sectors= burn_disc_get_sectors(disc); |
|
|
|
sessions= burn_disc_get_sessions(disc, &num_sessions); |
|
if(sessions==NULL || num_sessions < 1) { |
|
no_track:; |
|
Xorriso_process_msg_queues(xorriso,0); |
|
sprintf(xorriso->info_text,"Program error : no track in prepared disc"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); |
|
{ret= -1; goto ex;} |
|
} |
|
tracks= burn_session_get_tracks(sessions[0], &num_tracks); |
|
if(tracks==NULL || num_tracks < 1) |
|
goto no_track; |
|
|
|
padding= 0; |
|
ret= burn_disc_get_profile(drive, &profile, profile_name); |
|
padding= xorriso->padding / 2048; |
|
if(xorriso->padding > padding * 2048) |
|
padding++; |
|
if(img_sectors>0 && ret>0 && |
|
(profile==0x09 || profile==0x0a)) { /* CD-R , CD-RW */ |
|
if(img_sectors + padding < Xorriso_cd_min_track_sizE) { |
|
padding= Xorriso_cd_min_track_sizE - img_sectors; |
|
sprintf(xorriso->info_text, |
|
"Expanded track to minimum size of %d sectors", |
|
Xorriso_cd_min_track_sizE); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); |
|
} |
|
} |
|
if(xorriso->alignment == 0) { |
|
ret= isoburn_needs_emulation(drive); |
|
if(ret > 0) { |
|
/* Take care that the session is padded up to the future NWA. |
|
Else with padding < 32 it could happen that PVDs from older |
|
sessions survive and confuse -rom_toc_scan. |
|
*/ |
|
xorriso->alignment= 32; |
|
} |
|
} |
|
if(xorriso->alignment > 0) { |
|
if(img_sectors > 0) { |
|
ret= isoburn_disc_track_lba_nwa(drive, burn_options, 0, &lba, &nwa); |
|
if(ret <= 0) |
|
nwa= 0; |
|
lba= (nwa + img_sectors + padding) % xorriso->alignment; |
|
if(lba > 0) |
|
padding+= xorriso->alignment - lba; |
|
} else if(padding < xorriso->alignment) |
|
padding= xorriso->alignment; |
|
} |
|
burn_track_define_data(tracks[0], 0, padding * 2048, 0, BURN_MODE1); |
|
Xorriso_process_msg_queues(xorriso,0); |
|
|
|
if(flag&2) |
|
media_space= burn_disc_available_space(drive, burn_options) / |
|
(off_t) 2048; |
|
else |
|
media_space= isoburn_disc_available_space(drive, burn_options) / |
|
(off_t) 2048; |
|
if(media_space < img_sectors + padding) { |
|
Xorriso_process_msg_queues(xorriso,0); |
|
sprintf(xorriso->info_text,"Image size %ds exceeds free space on media %ds", |
|
img_sectors + padding, media_space); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
if(flag&1) { |
|
ret= img_sectors+padding; |
|
} else |
|
ret= 1; |
|
ex:; |
|
return(ret); |
|
} |
|
|
|
|
|
/* @return <0 yes , 0 no , <0 error */ |
|
int Xorriso_is_isohybrid(struct XorrisO *xorriso, IsoFile *bootimg_node, |
|
int flag) |
|
{ |
|
int ret; |
|
unsigned char buf[68]; |
|
void *data_stream= NULL; |
|
|
|
ret= Xorriso_iso_file_open(xorriso, "", (void *) bootimg_node, |
|
&data_stream, 1); |
|
if(ret <= 0) |
|
return(-1); |
|
ret= Xorriso_iso_file_read(xorriso, data_stream, (char *) buf, 68, 0); |
|
Xorriso_iso_file_close(xorriso, &data_stream, 0); |
|
if(ret <= 0) |
|
return(0); |
|
if(buf[64] == 0xfb && buf[65] == 0xc0 && buf[66] == 0x78 && buf[67] == 0x70) |
|
return(1); |
|
return(0); |
|
} |
|
|
|
|
|
int Xorriso_set_isolinux_options(struct XorrisO *xorriso, |
|
IsoImage *image, int flag) |
|
{ |
|
int make_isohybrid_mbr= 0, ret; |
|
ElToritoBootImage *bootimg; |
|
IsoFile *bootimg_node; |
|
|
|
ret= iso_image_get_boot_image(image, &bootimg, &bootimg_node, NULL); |
|
if(ret != 1) { |
|
sprintf(xorriso->info_text, "Programming error: No boot image available in Xorriso_set_isolinux_options()"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); |
|
return(-1); |
|
} |
|
|
|
if(xorriso->boot_image_isohybrid == 0) { |
|
ret= el_torito_set_isolinux_options(bootimg, 1, 0); |
|
return(ret == 1); |
|
} |
|
if(xorriso->boot_image_isohybrid == 3) { |
|
make_isohybrid_mbr= 1; |
|
} else { |
|
ret= Xorriso_is_isohybrid(xorriso, bootimg_node, 0); |
|
if(ret < 0) |
|
return(0); |
|
if(ret > 0) |
|
make_isohybrid_mbr= 1; |
|
} |
|
|
|
if(xorriso->boot_image_isohybrid == 2 && !make_isohybrid_mbr) { |
|
sprintf(xorriso->info_text, |
|
"Isohybrid signature is demanded but not found in boot image file."); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
return(0); |
|
} |
|
if(make_isohybrid_mbr) { |
|
sprintf(xorriso->info_text, "Will write isohybrid MBR."); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); |
|
xorriso->alignment= 512; |
|
} |
|
|
|
ret= el_torito_set_isolinux_options(bootimg, 1 | (make_isohybrid_mbr << 1),0); |
|
return(ret == 1); |
|
} |
|
|
|
|
|
int Xorriso_auto_format(struct XorrisO *xorriso, int flag) |
|
{ |
|
int ret, profile, status, num_formats; |
|
char profile_name[80]; |
|
struct burn_drive_info *dinfo; |
|
struct burn_drive *drive; |
|
off_t size; |
|
unsigned dummy; |
|
|
|
ret= Xorriso_may_burn(xorriso, 0); |
|
if(ret <= 0) |
|
return(0); |
|
|
|
ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, |
|
"on attempt to autoformat", 2); |
|
if(ret<=0) |
|
return(0); |
|
ret= burn_disc_get_profile(drive, &profile, profile_name); |
|
if(ret>0 && (profile==0x12 || profile==0x43)) { /* DVD-RAM or BD-RE */ |
|
ret= burn_disc_get_formats(drive, &status, &size, &dummy, &num_formats); |
|
if(ret>0 && status==BURN_FORMAT_IS_UNFORMATTED) { |
|
sprintf(xorriso->info_text, |
|
"Unformatted %s media detected. Trying -format fast.", |
|
profile_name); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); |
|
ret= Xorriso_format_media(xorriso, (off_t) 0, 1 | 4); |
|
if(ret<=0) { |
|
sprintf(xorriso->info_text, "Automatic formatting of %s failed", |
|
profile_name); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
return(ret); |
|
} |
|
} |
|
} |
|
return(1); |
|
} |
|
|
|
|
|
#define Xorriso_with_make_isohybrid_mbR 1 |
|
|
|
|
|
/* @param flag bit0= do not write but only prepare and return size in sectors |
|
*/ |
|
int Xorriso_write_session(struct XorrisO *xorriso, int flag) |
|
{ |
|
int ret, relax= 0, i, pacifier_speed= 0, data_lba, ext; |
|
int major, minor, micro; |
|
char xorriso_id[256], *img_id, sfe[5*SfileadrL], *cpt, *out_cs; |
|
struct isoburn_imgen_opts *sopts= NULL; |
|
struct burn_drive_info *dinfo, *source_dinfo; |
|
struct burn_drive *drive, *source_drive; |
|
struct burn_disc *disc= NULL; |
|
struct burn_write_opts *burn_options; |
|
off_t readcounter= 0,writecounter= 0; |
|
int num_sessions= 0, num_tracks= 0; |
|
struct burn_session **sessions; |
|
struct burn_track **tracks; |
|
enum burn_disc_status s; |
|
IsoImage *image= NULL; |
|
IsoNode *node, *root_node; |
|
ElToritoBootImage *bootimg; |
|
enum eltorito_boot_media_type emul_type= ELTORITO_NO_EMUL; |
|
int profile_number; |
|
char profile_name[80]; |
|
|
|
ret= Xorriso_finish_hl_update(xorriso, 0); |
|
if(ret <= 0) |
|
return(ret); |
|
|
|
out_cs= xorriso->out_charset; |
|
if(out_cs == NULL) |
|
Xorriso_get_local_charset(xorriso, &out_cs, 0); |
|
|
|
if(!(flag & 1)) { |
|
ret= Xorriso_auto_format(xorriso, 0); |
|
if(ret <=0 ) |
|
return(0); |
|
} |
|
ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, |
|
"on attempt to write", 2); |
|
if(ret<=0) |
|
return(0); |
|
if(xorriso->out_drive_handle == xorriso->in_drive_handle) { |
|
source_drive= drive; |
|
} else { |
|
if(xorriso->in_drive_handle == NULL) { |
|
source_drive= drive; |
|
} else { |
|
ret= Xorriso_get_drive_handles(xorriso, &source_dinfo, &source_drive, |
|
"on attempt to get source for write", 0); |
|
if(ret<=0) |
|
goto ex; |
|
} |
|
s= isoburn_disc_get_status(drive); |
|
if(s!=BURN_DISC_BLANK) { |
|
s= burn_disc_get_status(drive); |
|
if(s!=BURN_DISC_BLANK) |
|
sprintf(xorriso->info_text, |
|
"-indev differs from -outdev and -outdev media is not blank"); |
|
else |
|
sprintf(xorriso->info_text, |
|
"-indev differs from -outdev and -outdev media holds non-zero data"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
} |
|
ret= Xorriso_get_profile(xorriso, &profile_number, profile_name, 2); |
|
if(ret == 2) |
|
pacifier_speed= 1; |
|
else if(ret == 3) |
|
pacifier_speed= 2; |
|
|
|
ret= isoburn_igopt_new(&sopts, 0); |
|
if(ret<=0) { |
|
Xorriso_process_msg_queues(xorriso, 0); |
|
return(ret); |
|
} |
|
relax= xorriso->relax_compliance; |
|
|
|
xorriso->alignment= 0; |
|
image= isoburn_get_attached_image(source_drive); |
|
if(image != NULL) { |
|
iso_image_set_application_id(image, xorriso->application_id); |
|
iso_image_set_publisher_id(image, xorriso->publisher); |
|
iso_image_set_system_id(image, xorriso->system_id); |
|
iso_image_set_volset_id(image, xorriso->volset_id); |
|
} |
|
|
|
if((xorriso->do_aaip & 256) && out_cs != NULL) { |
|
static char *names = "isofs.cs"; |
|
size_t value_lengths[1]; |
|
|
|
value_lengths[0]= strlen(out_cs); |
|
ret= Xorriso_setfattr(xorriso, NULL, "/", |
|
(size_t) 1, &names, value_lengths, &out_cs, 2 | 8); |
|
if(ret<=0) |
|
goto ex; |
|
} |
|
|
|
/* Activate, adjust or discard boot image */ |
|
/* >>> ??? move down to libisoburn ? */ |
|
if(image!=NULL && !(flag&1)) { |
|
ret= iso_image_get_boot_image(image, &bootimg, NULL, NULL); |
|
|
|
if(xorriso->boot_image_bin_path[0]) { |
|
/* discard old boot image, set new one */ |
|
if(ret == 1) |
|
iso_image_remove_boot_image(image); |
|
if(xorriso->boot_image_emul == 1) |
|
emul_type= ELTORITO_HARD_DISC_EMUL; |
|
else if(xorriso->boot_image_emul == 2) |
|
emul_type= ELTORITO_FLOPPY_EMUL; |
|
if(xorriso->boot_image_cat_path[0] == 0) { |
|
strcpy(xorriso->boot_image_cat_path, xorriso->boot_image_bin_path); |
|
cpt= strrchr(xorriso->boot_image_cat_path, '/'); |
|
if(cpt == NULL) |
|
cpt= xorriso->boot_image_cat_path; |
|
else |
|
cpt++; |
|
strcpy(cpt, "boot.cat"); |
|
} |
|
sprintf(xorriso->info_text, "Activating alleged isolinux boot image %s", |
|
Text_shellsafe(xorriso->boot_image_bin_path, sfe, 0)); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); |
|
sprintf(xorriso->info_text, "Creating El Torito boot catalog file %s", |
|
Text_shellsafe(xorriso->boot_image_cat_path, sfe, 0)); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); |
|
|
|
ret= Xorriso_node_from_path(xorriso, image, xorriso->boot_image_bin_path, |
|
&node, 1); |
|
if(ret <= 0) { |
|
sprintf(xorriso->info_text, |
|
"Cannot find in ISO image: -boot_image ... bin_path=%s", |
|
Text_shellsafe(xorriso->boot_image_bin_path, sfe, 0)); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
ret= Xorriso_node_from_path(xorriso, image, xorriso->boot_image_cat_path, |
|
&node, 1); |
|
if(ret > 0) { |
|
if(!xorriso->do_overwrite) { |
|
sprintf(xorriso->info_text, |
|
"May not overwite existing -boot_image ... cat_path=%s", |
|
Text_shellsafe(xorriso->boot_image_cat_path, sfe, 0)); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
ret= Xorriso_rmi(xorriso, NULL, (off_t) 0, xorriso->boot_image_cat_path, |
|
8 | (xorriso->do_overwrite == 1)); |
|
if(ret != 1) { |
|
sprintf(xorriso->info_text, |
|
"Could not remove existing -boot_image cat_path=%s", |
|
Text_shellsafe(xorriso->boot_image_cat_path, sfe, 0)); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
} |
|
|
|
ret= iso_image_set_boot_image(image, xorriso->boot_image_bin_path, |
|
emul_type, xorriso->boot_image_cat_path, |
|
&bootimg); |
|
if(ret < 0) { |
|
Xorriso_process_msg_queues(xorriso,0); |
|
Xorriso_report_iso_error(xorriso, "", ret, |
|
"Error when attaching El-Torito boot image to ISO 9660 image", |
|
0, "FAILURE", 1); |
|
sprintf(xorriso->info_text, |
|
"Could not attach El-Torito boot image to ISO 9660 image"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
el_torito_set_load_size(bootimg, xorriso->boot_image_load_size / 512); |
|
|
|
#ifdef Xorriso_with_make_isohybrid_mbR |
|
|
|
ret= Xorriso_set_isolinux_options(xorriso, image, 0); |
|
if(ret <= 0) |
|
goto ex; |
|
|
|
#else |
|
el_torito_patch_isolinux_image(bootimg); |
|
#endif |
|
|
|
} else if(xorriso->patch_isolinux_image) { |
|
if(ret==1) { |
|
relax|= isoburn_igopt_allow_full_ascii; |
|
sprintf(xorriso->info_text, "Patching alleged isolinux boot image"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); |
|
|
|
ret= Xorriso_path_from_lba(xorriso, NULL, xorriso->loaded_boot_bin_lba, |
|
sfe, 1); |
|
if(ret < 0) |
|
goto ex; |
|
if(ret == 0) { |
|
sprintf(xorriso->info_text, |
|
"Cannot patch boot image: no file found for its LBA."); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
sprintf(xorriso->info_text, |
|
"Probably the loaded boot image file was deleted in this session."); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
sprintf(xorriso->info_text, |
|
"Use -boot_image \"any\" \"discard\" or set new boot image"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "HINT", 0); |
|
goto ex; |
|
} |
|
|
|
#ifdef Xorriso_with_make_isohybrid_mbR |
|
|
|
ret= Xorriso_set_isolinux_options(xorriso, image, 0); |
|
if(ret <= 0) |
|
goto ex; |
|
|
|
#else |
|
el_torito_patch_isolinux_image(bootimg); |
|
#endif |
|
|
|
} else { |
|
sprintf(xorriso->info_text, |
|
"Could not find any boot image for -boot_image isolinux patch"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0); |
|
} |
|
} else if(xorriso->keep_boot_image && ret==1) { |
|
relax|= isoburn_igopt_allow_full_ascii; |
|
sprintf(xorriso->info_text, "Keeping boot image unchanged"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); |
|
} else if(ret==1) { |
|
iso_image_remove_boot_image(image); |
|
sprintf(xorriso->info_text, "Discarded boot image from old session"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); |
|
} |
|
} |
|
|
|
if((xorriso->do_aaip & 16) || !(xorriso->ino_behavior & 2)) { |
|
/* Overwrite isofs.st of root node by xorriso->isofs_st_out */ |
|
char *name= "isofs.st"; |
|
char timestamp[16], *value= timestamp; |
|
size_t value_length; |
|
|
|
sprintf(timestamp, "%.f", (double) xorriso->isofs_st_out); |
|
value_length= strlen(timestamp); |
|
Xorriso_setfattr(xorriso, NULL, "/", (size_t) 1, &name, |
|
&value_length, &value, 2 | 8); |
|
} |
|
|
|
isoburn_igopt_set_level(sopts, 3); |
|
ext= isoburn_igopt_rockridge | |
|
((!!xorriso->do_joliet) * isoburn_igopt_joliet) | |
|
(( !(xorriso->ino_behavior & 2)) * isoburn_igopt_hardlinks) | |
|
(( (!(xorriso->ino_behavior & 2)) || |
|
(xorriso->do_aaip & (2 | 8 | 16 | 256)) || |
|
(xorriso->do_md5 & (2 | 4)) |
|
) * isoburn_igopt_aaip) | |
|
((!!(xorriso->do_md5 & 2)) * isoburn_igopt_session_md5) | |
|
((!!(xorriso->do_md5 & 4)) * isoburn_igopt_file_md5) | |
|
((!!(xorriso->do_md5 & 8)) * isoburn_igopt_file_stability); |
|
isoburn_igopt_set_extensions(sopts, ext); |
|
isoburn_igopt_set_relaxed(sopts, relax); |
|
isoburn_igopt_set_sort_files(sopts, 1); |
|
isoburn_igopt_set_over_mode(sopts, 0, 0, (mode_t) 0, (mode_t) 0); |
|
isoburn_igopt_set_over_ugid(sopts, 0, 0, (uid_t) 0, (gid_t) 0); |
|
isoburn_igopt_set_out_charset(sopts, out_cs); |
|
isoburn_igopt_set_fifo_size(sopts, xorriso->fs * 2048); |
|
Ftimetxt(time(NULL), xorriso->scdbackup_tag_time, 8); |
|
isoburn_igopt_set_scdbackup_tag(sopts, xorriso->scdbackup_tag_name, |
|
xorriso->scdbackup_tag_time, |
|
xorriso->scdbackup_tag_written); |
|
if(image!=NULL && |
|
strlen(Xorriso_program_versioN)+strlen(Xorriso_timestamP)<80) { |
|
sprintf(xorriso_id, "XORRISO-%s %s", |
|
Xorriso_program_versioN, Xorriso_timestamP); |
|
isoburn_version(&major, &minor, µ); |
|
if(strlen(xorriso_id)<80) |
|
sprintf(xorriso_id+strlen(xorriso_id), |
|
", LIBISOBURN-%d.%d.%d", major, minor, micro); |
|
iso_lib_version(&major, &minor, µ); |
|
if(strlen(xorriso_id)<80) |
|
sprintf(xorriso_id+strlen(xorriso_id), |
|
", LIBISOFS-%d.%d.%d", major, minor, micro); |
|
burn_version(&major, &minor, µ); |
|
if(strlen(xorriso_id)<80) |
|
sprintf(xorriso_id+strlen(xorriso_id), |
|
", LIBBURN-%d.%d.%d", major, minor, micro); |
|
xorriso_id[128]= 0; |
|
img_id= (char *) iso_image_get_data_preparer_id(image); |
|
if(img_id!=NULL) { |
|
for(i= strlen(img_id)-1; i>=0 && img_id[i]==' '; i--); |
|
if(i>0) { |
|
sprintf(xorriso->info_text, "Overwrote previous preparer id '%s'", |
|
img_id); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "DEBUG", 0); |
|
} |
|
} |
|
iso_image_set_data_preparer_id(image, xorriso_id); |
|
} |
|
|
|
/* Make final abort check before starting expensive activities */ |
|
ret= Xorriso_eval_problem_status(xorriso, 1, 0); |
|
if(ret<0) |
|
{ret= 0; goto ex;} |
|
|
|
if(xorriso->zisofs_by_magic) { |
|
sprintf(xorriso->info_text, |
|
"Checking disk file content for zisofs compression headers."); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0); |
|
root_node= (IsoNode *) iso_image_get_root(image); |
|
ret= iso_node_zf_by_magic(root_node, |
|
(xorriso->out_drive_handle == xorriso->in_drive_handle) | 2 | 16); |
|
if(ret<0) { |
|
Xorriso_report_iso_error(xorriso, "", ret, |
|
"Error when examining file content for zisofs headers", |
|
0, "FAILURE", 1); |
|
} |
|
ret= Xorriso_eval_problem_status(xorriso, 1, 0); |
|
if(ret<0) |
|
{ret= 0; goto ex;} |
|
sprintf(xorriso->info_text, |
|
"Check for zisofs compression headers done."); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0); |
|
} |
|
|
|
/* >>> omit iso_image_update_sizes if the image was filled up very quickly */; |
|
|
|
ret= iso_image_update_sizes(image); |
|
if(ret < 0) { |
|
Xorriso_process_msg_queues(xorriso, 0); |
|
if(ret<0) { |
|
Xorriso_report_iso_error(xorriso, "", ret, |
|
"Error when updating file sizes", |
|
0, "FAILURE", 1); |
|
} |
|
ret= Xorriso_eval_problem_status(xorriso, 1, 0); |
|
if(ret<0) |
|
{ret= 0; goto ex;} |
|
} |
|
|
|
Xorriso_set_abort_severity(xorriso, 1); |
|
if (xorriso->grow_blindly_msc2 >= 0 && |
|
xorriso->out_drive_handle != xorriso->in_drive_handle) { |
|
ret= isoburn_prepare_blind_grow(source_drive, &disc, sopts, drive, |
|
xorriso->grow_blindly_msc2); |
|
if(ret>0) { |
|
/* Allow the consumer of output to access the input drive */ |
|
source_drive= NULL; |
|
ret= Xorriso_give_up_drive(xorriso, 1|8); |
|
if(ret<=0) |
|
goto ex; |
|
} |
|
} else if(xorriso->out_drive_handle == xorriso->in_drive_handle || |
|
xorriso->in_drive_handle == NULL) { |
|
ret= isoburn_prepare_disc(source_drive, &disc, sopts); |
|
} else { |
|
ret= isoburn_prepare_new_image(source_drive, &disc, sopts, drive); |
|
} |
|
if(ret <= 0) { |
|
Xorriso_process_msg_queues(xorriso,0); |
|
sprintf(xorriso->info_text,"Failed to prepare session write run"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
{ret= 0; goto ex;} |
|
} |
|
|
|
ret= Xorriso_make_write_options(xorriso, drive, &burn_options, 0); |
|
if(ret<=0) |
|
goto ex; |
|
isoburn_igopt_get_effective_lba(sopts, &(xorriso->session_lba)); |
|
if(xorriso->do_stream_recording == 2) { |
|
ret= isoburn_igopt_get_data_start(sopts, &data_lba); |
|
if(ret > 0 && data_lba >= 16) |
|
burn_write_opts_set_stream_recording(burn_options, data_lba); |
|
} |
|
|
|
ret= Xorriso_sanitize_image_size(xorriso, drive, disc, burn_options, flag&1); |
|
if(ret<=0 || (flag&1)) { |
|
Xorriso_process_msg_queues(xorriso,0); |
|
if(flag&1) /* set queue severity to FAILURE */ |
|
Xorriso_set_image_severities(xorriso, 2); |
|
isoburn_cancel_prepared_write(source_drive, drive, 0); |
|
if(flag&1) /* reset queue severity */ |
|
Xorriso_set_image_severities(xorriso, 0); |
|
goto ex; |
|
} |
|
|
|
ret= Xorriso_may_burn(xorriso, 0); |
|
if(ret <= 0) |
|
goto ex; |
|
|
|
xorriso->run_state= 1; /* Indicate that burning has started */ |
|
isoburn_disc_write(burn_options, disc); |
|
burn_write_opts_free(burn_options); |
|
|
|
ret= Xorriso_pacifier_loop(xorriso, drive, pacifier_speed << 4); |
|
if(ret<=0) |
|
goto ex; |
|
if(!isoburn_drive_wrote_well(drive)) { |
|
isoburn_cancel_prepared_write(source_drive, drive, 0); |
|
Xorriso_process_msg_queues(xorriso,0); |
|
sprintf(xorriso->info_text, |
|
"libburn indicates failure with writing."); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); |
|
ret= 0; goto ex; |
|
} |
|
|
|
sessions= burn_disc_get_sessions(disc, &num_sessions); |
|
if(num_sessions>0) { |
|
tracks= burn_session_get_tracks(sessions[0], &num_tracks); |
|
if(tracks!=NULL && num_tracks>0) { |
|
burn_track_get_counters(tracks[0],&readcounter,&writecounter); |
|
xorriso->session_blocks= (int) (writecounter/ (off_t) 2048); |
|
sprintf(xorriso->info_text, |
|
"ISO image produced: %d sectors\nWritten to media : %d sectors at LBA %d\n", |
|
(int) (readcounter/ (off_t) 2048), |
|
xorriso->session_blocks, xorriso->session_lba); |
|
Xorriso_info(xorriso, 0); |
|
} |
|
} |
|
ret= isoburn_activate_session(drive); |
|
Xorriso_process_msg_queues(xorriso,0); |
|
if(ret<=0) { |
|
sprintf(xorriso->info_text, |
|
"Could not write new set of volume descriptors"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0); |
|
goto ex; |
|
} |
|
/* Done early to free any reference to the libisofs resources via disc */ |
|
if(disc!=NULL) |
|
burn_disc_free(disc); |
|
disc= NULL; |
|
/* To wait for the end of the libisofs threads and their messages. */ |
|
isoburn_sync_after_write(source_drive, drive, 0); |
|
Xorriso_process_msg_queues(xorriso,0); |
|
|
|
sprintf(xorriso->info_text, "Writing to %s completed sucessfully.\n\n", |
|
Text_shellsafe(xorriso->outdev,sfe,0)); |
|
Xorriso_info(xorriso, 0); |
|
ret= 1; |
|
ex:; |
|
xorriso->run_state= 0; /* Indicate that burning has ended */ |
|
Xorriso_set_abort_severity(xorriso, 0); |
|
|
|
if(ret<=0) { |
|
|
|
/* >>> ??? revive discarded boot image */; |
|
|
|
} |
|
if(disc!=NULL) |
|
burn_disc_free(disc); |
|
if(image != NULL) |
|
iso_image_unref(image); |
|
isoburn_igopt_destroy(&sopts, 0); |
|
Xorriso_process_msg_queues(xorriso,0); |
|
Xorriso_append_scdbackup_record(xorriso, 0); |
|
return(ret); |
|
} |
|
|
|
|
|
int Xorriso_check_burn_abort(struct XorrisO *xorriso, int flag) |
|
{ |
|
int ret; |
|
struct burn_drive_info *dinfo; |
|
struct burn_drive *drive; |
|
|
|
if(xorriso->run_state!=1) |
|
return(0); |
|
ret= Xorriso_eval_problem_status(xorriso, 1, 1); |
|
if(ret>=0) |
|
return(0); |
|
sprintf(xorriso->info_text, |
|
"-abort_on '%s' encountered '%s' during image writing", |
|
xorriso->abort_on_text, xorriso->problem_status_text); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, |
|
xorriso->problem_status_text, 0); |
|
|
|
ret= Xorriso_get_drive_handles(xorriso, &dinfo, &drive, |
|
"on attempt to abort burn run", 2); |
|
if(ret<=0) |
|
return(0); |
|
|
|
burn_drive_cancel(drive); |
|
sprintf(xorriso->info_text, |
|
"libburn has now been urged to cancel its operation"); |
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0); |
|
return(1); |
|
} |
|
|
|
|
|
/* This loop watches burn runs until they end. |
|
It issues pacifying update messages to the user. |
|
@param flag bit0-3 = emulation mode |
|
0= xorriso |
|
1= mkisofs |
|
2= cdrecord |
|
bit4= report speed in CD units |
|
bit5= report speed in BD units |
|
*/ |
|
int Xorriso_pacifier_loop(struct XorrisO *xorriso, struct burn_drive *drive, |
|
int flag) |
|
{ |
|
int ret, size, free_bytes, i, aborting= 0, emul, buffer_fill= 50, last_sector; |
|
struct burn_progress progress; |
|
char *status_text, date_text[80], *speed_unit, mem_text[8]; |
|
enum burn_drive_status drive_status; |
|
double start_time, current_time, last_time, base_time= 0.0, base_count= 0.0; |
|
double next_base_time= 0.0, next_base_count= 0.0, first_base_time= 0.0; |
|
double first_base_count= 0.0, norm= 0.0, now_time, fract_offset= 0.0; |
|
double measured_speed, speed_factor= 1385000, quot; |
|
time_t time_prediction; |
|
|
|
start_time= Sfile_microtime(0); |
|
while(burn_drive_get_status(drive, NULL) == BURN_DRIVE_SPAWNING) |
|
usleep(100002); |
|
|
|
emul= flag&15; |
|
fract_offset= 0.2 * (double) emul - ((int) (0.2 * (double) emul)); |
|
if(emul==0) |
|
emul= xorriso->pacifier_style; |
|
speed_unit= "D"; |
|
if(flag&16) { |
|
speed_factor= 150.0*1024; |
|
speed_unit= "C"; |
|
} else if(flag & 32) { |
|
speed_factor= 4495625; |
|
speed_unit= "B"; |
|
} |
|
progress.sector= 0; |
|
current_time= Sfile_microtime(0); |
|
measured_speed= 0.0; |
|
while(1) { |
|
last_time= current_time; |
|
last_sector= progress.sector; |
|
drive_status= burn_drive_get_status(drive, &progress); |
|
if(drive_status == BURN_DRIVE_IDLE) |
|
break; |
|
current_time= Sfile_microtime(0); |
|
if(drive_status == BURN_DRIVE_WRITING && progress.sectors > 0) { |
|
if(current_time-last_time>0.2) |
|
measured_speed= (progress.sector - last_sector) * 2048.0 / |
|
(current_time - last_time); |
|
buffer_fill= 50; |
|
if(progress.buffer_capacity>0) |
|
buffer_fill= (double) (progress.buffer_capacity |
|
- progress.buffer_available) * 100.0 |
|
/ (double) progress.buffer_capacity; |
|
if(emul==2) { |
|
if(progress.sector<=progress.sectors) |
|
sprintf(xorriso->info_text, "%4d of %4d MB written", |
|
progress.sector / 512, progress.sectors / 512); |
|
else |
|
sprintf(xorriso->info_text, "%4d MB written", |
|
progress.sector / 512); |
|
|
|
if(xorriso->pacifier_fifo!=NULL) |
|
ret= burn_fifo_inquire_status(xorriso->pacifier_fifo, |
|
&size, &free_bytes, &status_text); |
|
else |
|
ret= isoburn_get_fifo_status(drive, &size, &free_bytes, &status_text); |
|
if(ret>0 ) |
|
sprintf(xorriso->info_text+strlen(xorriso->info_text), |
|
" (fifo %2d%%)", |
|
(int) (100.0-100.0*((double) free_bytes)/(double) size)); |
|
|
|
sprintf(xorriso->info_text+strlen(xorriso->info_text), " [buf %3d%%]", |
|
buffer_fill); |
|
|
|
if(current_time-last_time>0.2) |
|
sprintf(xorriso->info_text+strlen(xorriso->info_text), " %4.1fx.", |
|
measured_speed/speed_factor); |
|
|
|
} else if(emul == 1 && |
|
progress.sectors > 0 && progress.sector <= |