You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
9563 lines
300 KiB
C
9563 lines
300 KiB
C
|
|
|
|
/* 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 */
|
|
|
|
#define Xorriso_with_aaiP yes
|
|
|
|
/* 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_node_from_path(struct XorrisO *xorriso, IsoImage *volume,
|
|
char *path, IsoNode **node, int flag);
|
|
|
|
int Xorriso_path_from_node(struct XorrisO *xorriso, IsoNode *node, int lba,
|
|
char path[SfileadrL], 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 -relax_compliance */
|
|
#define Xorriso_relax_compliance_defaulT \
|
|
(isoburn_igopt_allow_deep_paths | isoburn_igopt_allow_longer_paths | \
|
|
isoburn_igopt_always_gmt)
|
|
|
|
|
|
/* <<< Whether to allow xattr and ACL with the root node.
|
|
(It is supposed to work since libisofs-ng resision 479)
|
|
*/
|
|
#define Xorriso_root_with_aaiP yes
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
|
|
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];
|
|
|
|
|
|
/* 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()); */
|
|
|
|
sprintf(handler_prefix, "%s : ", xorriso->progname);
|
|
burn_set_signal_handling(handler_prefix, NULL, 0);
|
|
|
|
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);
|
|
}
|
|
if(flag&1) {
|
|
if(xorriso->libs_are_started==0)
|
|
return(0);
|
|
isoburn_finish();
|
|
}
|
|
return(1);
|
|
}
|
|
|
|
|
|
/* @param flag bit1= obtain outdrive, else indrive */
|
|
int Xorriso_get_drive_handles(struct XorrisO *xorriso,
|
|
struct burn_drive_info **dinfo,
|
|
struct burn_drive **drive,
|
|
char *attempt, int flag)
|
|
{
|
|
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) {
|
|
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);
|
|
return(0);
|
|
}
|
|
*drive= (*dinfo)[0].drive;
|
|
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->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);
|
|
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_node(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);
|
|
}
|
|
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
|
|
@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;
|
|
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;
|
|
struct isoburn_read_opts *ropts= NULL;
|
|
char libburn_adr[SfileadrL], *boot_fate, *sev;
|
|
|
|
static int no_rr_or_joliet= 0;
|
|
|
|
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);
|
|
|
|
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;
|
|
} 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;
|
|
}
|
|
|
|
if(dinfo==NULL) {
|
|
isoburn_set_msgs_submit(Xorriso_msgs_submit_void, (void *) xorriso,
|
|
(3<<2) | 128 , 0);
|
|
aquire_flag= 1 | ((flag&(8|4))>>1) | ((xorriso->toc_emulation_flag & 3)<<3);
|
|
if(!(xorriso->do_aaip & 1))
|
|
aquire_flag|= 32;
|
|
if(!(xorriso->do_aaip & 4))
|
|
aquire_flag|= 64;
|
|
ret= isoburn_drive_aquire(&dinfo, libburn_adr, aquire_flag);
|
|
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 */
|
|
}
|
|
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 */
|
|
ret= isoburn_set_msc1(drive, xorriso->image_start_mode & 0xffff,
|
|
xorriso->image_start_value,
|
|
!!(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);
|
|
|
|
/* 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;
|
|
#ifdef isoburn_ropt_noaaip
|
|
if(!(xorriso->do_aaip & (1 | 4 | 16)))
|
|
ext|= isoburn_ropt_noaaip;
|
|
#endif
|
|
#ifdef isoburn_ropt_noacl
|
|
if(!(xorriso->do_aaip & 1))
|
|
ext|= isoburn_ropt_noacl;
|
|
#endif
|
|
#ifdef isoburn_ropt_noea
|
|
if(!(xorriso->do_aaip & 4))
|
|
ext|= isoburn_ropt_noea;
|
|
#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);
|
|
|
|
Xorriso_set_image_severities(xorriso, 1); /* No DEBUG messages */
|
|
Xorriso_pacifier_reset(xorriso, 0);
|
|
isoburn_set_read_pacifier(drive, Xorriso__read_pacifier, (void *) xorriso);
|
|
|
|
/* <<< Trying to work around too much tolerance on bad image trees.
|
|
Better would be a chance to instruct libisofs what to do in
|
|
case of image read errors. There is a risk to mistake other SORRYs.
|
|
*/
|
|
if(xorriso->img_read_error_mode>0)
|
|
iso_set_abort_severity("SORRY");
|
|
|
|
if(state != BURN_DISC_BLANK) {
|
|
ret= isoburn_disc_get_msc1(drive, &load_lba);
|
|
if(ret > 0) {
|
|
sprintf(xorriso->info_text,
|
|
"Loading ISO image tree from LBA %d", load_lba);
|
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
|
|
}
|
|
ret= Xorriso_assert_volid(xorriso, load_lba, 0);
|
|
if(ret <= 0)
|
|
goto ex;
|
|
}
|
|
|
|
/* <<< */
|
|
if(no_rr_or_joliet) {
|
|
isoburn_ropt_set_extensions(ropts,
|
|
isoburn_ropt_noiso1999 | isoburn_ropt_norock | isoburn_ropt_nojoliet);
|
|
}
|
|
|
|
|
|
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(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'",
|
|
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);
|
|
|
|
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&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;
|
|
}
|
|
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;
|
|
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) {
|
|
if(drive!=NULL && !in_is_out_too)
|
|
isoburn_drive_release(drive,!!(flag&4));
|
|
if(dinfo!=NULL && !in_is_out_too)
|
|
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->loaded_volid[0]= 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) {
|
|
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,!!(flag&4));
|
|
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 >= 16)
|
|
stream_mode= xorriso->do_stream_recording;
|
|
burn_write_opts_set_stream_recording(*burn_options, stream_mode);
|
|
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) {
|
|
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_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;
|
|
int major, minor, micro;
|
|
char xorriso_id[256], *img_id, sfe[5*SfileadrL], *cpt;
|
|
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;
|
|
ElToritoBootImage *bootimg;
|
|
enum eltorito_boot_media_type emul_type= ELTORITO_NO_EMUL;
|
|
int profile_number;
|
|
char profile_name[80];
|
|
|
|
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);
|
|
}
|
|
|
|
/* 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_node(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);
|
|
}
|
|
}
|
|
isoburn_igopt_set_level(sopts, 3);
|
|
isoburn_igopt_set_extensions(sopts, 1 | ((!!xorriso->do_joliet)<<1) |
|
|
((!!(xorriso->do_aaip & (2 | 8 | 16))) << 5));
|
|
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, xorriso->out_charset);
|
|
isoburn_igopt_set_fifo_size(sopts, xorriso->fs * 2048);
|
|
|
|
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;}
|
|
|
|
/* >>> 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);
|
|
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)
|
|
data_lba= 51200; /* 100 MB */
|
|
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;
|
|
}
|
|
|
|
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);
|
|
isoburn_igopt_destroy(&sopts, 0);
|
|
Xorriso_process_msg_queues(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 <= progress.sectors) {
|
|
/* "37.87% done, estimate finish Tue Jul 15 18:55:07 2008" */
|
|
|
|
quot= ((double) progress.sector) / ((double) progress.sectors);
|
|
sprintf(xorriso->info_text, " %2.2f%% done", quot*100.0);
|
|
if(current_time - start_time >= 2 && quot > 0.0 &&
|
|
(quot >= 0.02 || progress.sector >= 5*1024)) {
|
|
if(base_time == 0.0 && progress.sector >= 16*1024) {
|
|
first_base_time= base_time= next_base_time= current_time;
|
|
first_base_count= next_base_count= progress.sector;
|
|
} else if(next_base_time > 0 && current_time - next_base_time >= 10) {
|
|
base_time= next_base_time;
|
|
base_count= next_base_count;
|
|
next_base_time= current_time;
|
|
next_base_count= progress.sector;
|
|
}
|
|
if(first_base_time > 0 &&
|
|
current_time - first_base_time >= 10 &&
|
|
progress.sectors > first_base_count &&
|
|
progress.sector > first_base_count) {
|
|
norm= (1.0 - quot);
|
|
if(norm < 0.0001)
|
|
norm= 0.0001;
|
|
quot= ((double) progress.sector - first_base_count)
|
|
/ ((double) progress.sectors - first_base_count);
|
|
time_prediction= norm * (1.0 - quot) / quot
|
|
* (current_time - first_base_time);
|
|
} else {
|
|
time_prediction= (1.0 - quot) / quot * (current_time - start_time);
|
|
norm= 1.0;
|
|
}
|
|
if(base_time > 0 &&
|
|
current_time - base_time >= 10 && progress.sectors > base_count) {
|
|
quot= ((double) progress.sector - base_count)
|
|
/ ((double) progress.sectors - base_count);
|
|
time_prediction+= (1.0 - quot) / quot * (current_time - base_time);
|
|
norm+= 1.0;
|
|
}
|
|
time_prediction/= norm;
|
|
if(time_prediction < 30*86400 && time_prediction > 0) {
|
|
time_prediction+= current_time + 1;
|
|
Ftimetxt(time_prediction, date_text, 4);
|
|
sprintf(xorriso->info_text+strlen(xorriso->info_text),
|
|
", estimate finish %s", date_text);
|
|
}
|
|
}
|
|
} else {
|
|
if(progress.sector<=progress.sectors) {
|
|
if(progress.sectors <= 0)
|
|
strcpy(mem_text, " 99.9");
|
|
else
|
|
sprintf(mem_text, "%5.1f",
|
|
100.0 * ((double) progress.sector) / ((double) progress.sectors));
|
|
mem_text[5]= 0;
|
|
sprintf(xorriso->info_text, "Writing: %10ds %s%% ",
|
|
progress.sector, mem_text);
|
|
} else {
|
|
Sfile_scale(2048.0 * (double) progress.sector, mem_text, 5, 1e4, 1);
|
|
sprintf(xorriso->info_text, "Writing: %10ds %s ",
|
|
progress.sector, mem_text);
|
|
}
|
|
ret= isoburn_get_fifo_status(drive, &size, &free_bytes, &status_text);
|
|
if(ret>0 )
|
|
sprintf(xorriso->info_text+strlen(xorriso->info_text),
|
|
" fifo %3d%% buf %3d%%",
|
|
(int) (100.0-100.0*((double) free_bytes)/(double) size),
|
|
buffer_fill);
|
|
if(current_time-last_time>0.2)
|
|
sprintf(xorriso->info_text+strlen(xorriso->info_text), " %5.1fx%s ",
|
|
measured_speed/speed_factor, speed_unit);
|
|
}
|
|
} else if(drive_status == BURN_DRIVE_CLOSING_SESSION ||
|
|
drive_status == BURN_DRIVE_CLOSING_TRACK)
|
|
sprintf(xorriso->info_text,
|
|
"Closing track/session. Working since %.f seconds",
|
|
current_time-start_time);
|
|
else if(drive_status == BURN_DRIVE_FORMATTING)
|
|
sprintf(xorriso->info_text, "Formatting. Working since %.f seconds",
|
|
current_time-start_time);
|
|
else
|
|
sprintf(xorriso->info_text,
|
|
"Thank you for being patient for %.f seconds",
|
|
current_time-start_time);
|
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "UPDATE", 0);
|
|
|
|
for(i= 0; i<12; i++) { /* 2 usleeps more than supposed to be needed */
|
|
Xorriso_process_msg_queues(xorriso, 0);
|
|
if(aborting<=0)
|
|
aborting= Xorriso_check_burn_abort(xorriso, 0);
|
|
usleep(100000);
|
|
now_time= Sfile_microtime(0);
|
|
if(((time_t) now_time) - ((time_t) current_time) >= 1 &&
|
|
now_time - ((time_t) now_time) >= fract_offset)
|
|
break;
|
|
}
|
|
}
|
|
return(1);
|
|
}
|
|
|
|
|
|
int Xorriso__read_pacifier(IsoImage *image, IsoFileSource *filesource)
|
|
{
|
|
struct XorrisO *xorriso;
|
|
|
|
xorriso= (struct XorrisO *) iso_image_get_attached_data(image);
|
|
if(xorriso==NULL)
|
|
return(1);
|
|
xorriso->pacifier_count++;
|
|
if(xorriso->pacifier_count%10)
|
|
return(1);
|
|
Xorriso_pacifier_callback(xorriso, "nodes read", xorriso->pacifier_count, 0,
|
|
"", 0);
|
|
return(1);
|
|
}
|
|
|
|
/* @param flag bit0=silently return 0 if no volume/image is present
|
|
*/
|
|
int Xorriso_get_volume(struct XorrisO *xorriso, IsoImage **volume,
|
|
int flag)
|
|
{
|
|
if(xorriso->in_volset_handle==NULL) {
|
|
if(flag & 1)
|
|
return(0);
|
|
Xorriso_process_msg_queues(xorriso,0);
|
|
sprintf(xorriso->info_text,"No ISO image present.");
|
|
if(xorriso->indev[0]==0 && xorriso->outdev[0]==0)
|
|
sprintf(xorriso->info_text+strlen(xorriso->info_text),
|
|
" No -dev, -indev, or -outdev selected.");
|
|
else
|
|
sprintf(xorriso->info_text+strlen(xorriso->info_text),
|
|
" Possible program error with drive '%s'.", xorriso->indev);
|
|
|
|
if(!xorriso->no_volset_present)
|
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
|
|
xorriso->no_volset_present= 1;
|
|
return(0);
|
|
}
|
|
*volume= (IsoImage *) xorriso->in_volset_handle;
|
|
xorriso->no_volset_present= 0;
|
|
return(*volume != NULL);
|
|
}
|
|
|
|
/*
|
|
@param flag bit0= do not issue warning
|
|
*/
|
|
int Xorriso_aaip_warn_of_root(struct XorrisO *xorriso, IsoNode *node, int flag)
|
|
{
|
|
|
|
#ifndef Xorriso_root_with_aaiP
|
|
|
|
int ret;
|
|
IsoDir *root= NULL;
|
|
IsoImage *volume;
|
|
|
|
ret= Xorriso_get_volume(xorriso, &volume, 0);
|
|
if(ret<=0)
|
|
return(ret);
|
|
root= iso_image_get_root(volume);
|
|
if(node == (IsoNode *) root) {
|
|
sprintf(xorriso->info_text,
|
|
"Cannot attach ACL or xattr to ISO root directory");
|
|
if(!(flag & 1))
|
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "WARNING", 0);
|
|
return(0);
|
|
}
|
|
|
|
#endif /* ! Xorriso_root_with_aaiP */
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
/* @param flag bit0=do not complain about non existent node */
|
|
int Xorriso_node_from_path(struct XorrisO *xorriso, IsoImage *volume,
|
|
char *path, IsoNode **node, int flag)
|
|
{
|
|
int ret;
|
|
char sfe[5*SfileadrL], *path_pt;
|
|
|
|
path_pt= path;
|
|
if(path[0]==0)
|
|
path_pt= "/";
|
|
*node= NULL;
|
|
ret= iso_tree_path_to_node(volume, path_pt, node);
|
|
Xorriso_process_msg_queues(xorriso,0);
|
|
if(ret<=0 || (*node)==NULL) {
|
|
if(!(flag&1)) {
|
|
sprintf(xorriso->info_text, "Cannot find path %s in loaded ISO image",
|
|
Text_shellsafe(path_pt, sfe, 0));
|
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
|
|
}
|
|
return(0);
|
|
}
|
|
return(1);
|
|
}
|
|
|
|
|
|
/* @param eff_path returns resulting effective path.
|
|
Must provide at least SfileadrL bytes of storage.
|
|
@param flag bit0= do not produce problem events (unless faulty path format)
|
|
bit1= work purely literally, do not use libisofs
|
|
bit2= (with bit1) this is an address in the disk world
|
|
bit3= return root directory as "/" and not as ""
|
|
bit4= (with bit2) determine type of disk file eff_path
|
|
and return 0 if not existing
|
|
bit5= (with bit3) this is not a parameter
|
|
bit6= insist in having an ISO image, even with bits1+2
|
|
@return -1 = faulty path format, 0 = not found ,
|
|
1 = found simple node , 2 = found directory
|
|
*/
|
|
int Xorriso_normalize_img_path(struct XorrisO *xorriso, char *wd,
|
|
char *img_path, char eff_path[], int flag)
|
|
{
|
|
int ret, is_dir= 0, done= 0;
|
|
IsoImage *volume;
|
|
IsoDir *dir= NULL;
|
|
IsoNode *node= NULL;
|
|
char path[SfileadrL], *apt, *npt, sfe[5*SfileadrL], *cpt;
|
|
|
|
if((flag&64) || !(flag&2)) {
|
|
ret= Xorriso_get_volume(xorriso, &volume, 0);
|
|
if(ret<=0)
|
|
return(ret);
|
|
}
|
|
|
|
eff_path[0]= 0;
|
|
if(img_path[0]==0) {
|
|
if(flag&8)
|
|
strcpy(eff_path, "/");
|
|
return(2); /* root directory */
|
|
}
|
|
|
|
apt= npt= path;
|
|
if(img_path[0]!='/') {
|
|
strcpy(path, wd);
|
|
ret= Sfile_add_to_path(path, img_path, 0);
|
|
if(ret<=0)
|
|
goto much_too_long;
|
|
} else
|
|
if(Sfile_str(path, img_path, 0)<=0)
|
|
return(-1);
|
|
|
|
if(path[0]!='/') {
|
|
sprintf(xorriso->info_text,
|
|
"Internal error: Unresolvable relative addressing in iso_rr_path '%s'",
|
|
img_path);
|
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FATAL", 0);
|
|
return(-1);
|
|
} else if(path[1]==0) {
|
|
if(flag&8)
|
|
strcpy(eff_path, "/");
|
|
return(2); /* root directory */
|
|
}
|
|
|
|
for(npt= apt; !done; apt= npt+1) {
|
|
npt= strchr(apt, '/');
|
|
if(npt==NULL) {
|
|
npt= apt+strlen(apt);
|
|
done= 1;
|
|
} else
|
|
*npt= 0;
|
|
if(*apt==0) {
|
|
*apt= '/';
|
|
apt++;
|
|
if(done)
|
|
break;
|
|
continue;
|
|
}
|
|
if(strcmp(apt,".")==0) {
|
|
is_dir= 1;
|
|
continue;
|
|
}
|
|
if(strcmp(apt,"..")==0) {
|
|
if(!(flag&2)) {
|
|
node= (IsoNode *) dir;
|
|
if(node==NULL) {
|
|
bonked_root:;
|
|
sprintf(xorriso->info_text,
|
|
"Relative addressing in path exceeds root directory: %s",
|
|
Text_shellsafe(img_path, sfe, 0));
|
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
|
|
return(-1);
|
|
}
|
|
dir= iso_node_get_parent(node);
|
|
}
|
|
/* truncate eff_path */;
|
|
cpt= strrchr(eff_path, '/');
|
|
if(cpt==NULL) /* ??? if not flag&2 then this is a bug */
|
|
goto bonked_root;
|
|
*cpt= 0;
|
|
is_dir= 1;
|
|
continue;
|
|
}
|
|
ret= Sfile_add_to_path(eff_path, apt, 0);
|
|
if(ret<=0) {
|
|
much_too_long:;
|
|
sprintf(xorriso->info_text, "Effective path gets much too long (%d)",
|
|
(int) (strlen(eff_path)+strlen(apt)+1));
|
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
|
|
return(-1);
|
|
}
|
|
if(!(flag&2)) {
|
|
dir= (IsoDir *) node;
|
|
ret= Xorriso_node_from_path(xorriso, volume, eff_path, &node, flag&1);
|
|
if(ret<=0)
|
|
return(0);
|
|
if(dir==NULL) /* could be false with "/dir/.." */
|
|
dir= iso_node_get_parent(node);
|
|
is_dir= LIBISO_ISDIR(node);
|
|
}
|
|
}
|
|
if(flag&16) {
|
|
ret= Sfile_type(eff_path,
|
|
1|(4*(xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&32)))
|
|
));
|
|
if(ret<0)
|
|
return(0);
|
|
if(ret==2)
|
|
is_dir= 1;
|
|
}
|
|
return(1+!!is_dir);
|
|
}
|
|
|
|
|
|
int Xorriso_get_node_by_path(struct XorrisO *xorriso,
|
|
char *in_path, char *eff_path,
|
|
IsoNode **node, int flag)
|
|
{
|
|
int ret;
|
|
char path[SfileadrL];
|
|
IsoImage *volume;
|
|
|
|
ret= Xorriso_normalize_img_path(xorriso, xorriso->wdi, in_path, path, 0);
|
|
if(ret<=0)
|
|
return(ret);
|
|
if(eff_path!=NULL)
|
|
strcpy(eff_path, path);
|
|
ret= Xorriso_get_volume(xorriso, &volume, 0);
|
|
if(ret<=0)
|
|
return(ret);
|
|
ret= Xorriso_node_from_path(xorriso, volume, path, node, 0);
|
|
if(ret<=0)
|
|
return(0);
|
|
return(1);
|
|
}
|
|
|
|
|
|
/* @param flag
|
|
*/
|
|
int Xorriso_node_get_dev(struct XorrisO *xorriso, IsoNode *node,
|
|
char *path, dev_t *dev, int flag)
|
|
{
|
|
*dev= iso_special_get_dev((IsoSpecial *) node);
|
|
return(1);
|
|
}
|
|
|
|
|
|
/* @param flag bit0= *node is already valid
|
|
bit1= add extra block for size estimation
|
|
bit2= complain loudely if path is missing in image
|
|
bit3= stbuf is to be used without eventual ACL
|
|
*/
|
|
int Xorriso_fake_stbuf(struct XorrisO *xorriso, char *path, struct stat *stbuf,
|
|
IsoNode **node, int flag)
|
|
{
|
|
int ret;
|
|
IsoImage *volume;
|
|
|
|
memset((char *) stbuf, 0, sizeof(struct stat));
|
|
if(!(flag&1)) {
|
|
ret= Xorriso_get_volume(xorriso, &volume, 0);
|
|
if(ret<=0)
|
|
return(-1);
|
|
ret= Xorriso_node_from_path(xorriso, volume, path, node, !(flag&4));
|
|
if(ret<=0)
|
|
*node= NULL;
|
|
}
|
|
if(*node==NULL)
|
|
return(0);
|
|
|
|
/* >>> stbuf->st_dev */
|
|
/* >>> stbuf->st_ino */
|
|
|
|
if(flag & 8)
|
|
stbuf->st_mode= iso_node_get_perms_wo_acl(*node) & 07777;
|
|
else
|
|
stbuf->st_mode= iso_node_get_permissions(*node) & 07777;
|
|
if(LIBISO_ISDIR(*node))
|
|
stbuf->st_mode|= S_IFDIR;
|
|
else if(LIBISO_ISREG(*node))
|
|
stbuf->st_mode|= S_IFREG;
|
|
else if(LIBISO_ISLNK(*node))
|
|
stbuf->st_mode|= S_IFLNK;
|
|
else if(LIBISO_ISCHR(*node)) {
|
|
stbuf->st_mode|= S_IFCHR;
|
|
Xorriso_node_get_dev(xorriso, *node, path, &(stbuf->st_rdev), 0);
|
|
} else if(LIBISO_ISBLK(*node)) {
|
|
stbuf->st_mode|= S_IFBLK;
|
|
Xorriso_node_get_dev(xorriso, *node, path, &(stbuf->st_rdev), 0);
|
|
} else if(LIBISO_ISFIFO(*node))
|
|
stbuf->st_mode|= S_IFIFO;
|
|
else if(LIBISO_ISSOCK(*node))
|
|
stbuf->st_mode|= S_IFSOCK;
|
|
else if(LIBISO_ISBOOT(*node))
|
|
stbuf->st_mode|= Xorriso_IFBOOT;
|
|
|
|
/* >>> With directories this should be : number of subdirs + 2 */
|
|
/* >>> ??? How to obtain RR hardlink number for other types ? */
|
|
stbuf->st_nlink= 1;
|
|
|
|
stbuf->st_uid= iso_node_get_uid(*node);
|
|
stbuf->st_gid= iso_node_get_gid(*node);
|
|
|
|
if(LIBISO_ISREG(*node))
|
|
stbuf->st_size= iso_file_get_size((IsoFile *) *node)+ (2048 * !!(flag&2));
|
|
else
|
|
stbuf->st_size= 0;
|
|
|
|
stbuf->st_blksize= 2048;
|
|
stbuf->st_blocks= stbuf->st_size / (off_t) 2048;
|
|
if(stbuf->st_blocks * (off_t) 2048 != stbuf->st_size)
|
|
stbuf->st_blocks++;
|
|
|
|
stbuf->st_atime= iso_node_get_atime(*node);
|
|
stbuf->st_mtime= iso_node_get_mtime(*node);
|
|
stbuf->st_ctime= iso_node_get_ctime(*node);
|
|
return(1);
|
|
}
|
|
|
|
|
|
/* @param flag >>> bit0= follow links (i.e. stat() rather than lstat()
|
|
bit1= do not return -2 on severe errors
|
|
bit2= complain loudely if path is missing in image
|
|
*/
|
|
int Xorriso_iso_lstat(struct XorrisO *xorriso, char *path, struct stat *stbuf,
|
|
int flag)
|
|
{
|
|
int ret;
|
|
IsoNode *node;
|
|
|
|
if(flag&1) {
|
|
|
|
/* >>> follow link in ISO image */;
|
|
|
|
}
|
|
|
|
ret= Xorriso_fake_stbuf(xorriso, path, stbuf, &node, flag&4);
|
|
if(ret>0)
|
|
return(0);
|
|
if(ret<0 && !(flag&2))
|
|
return(-2);
|
|
return(-1);
|
|
}
|
|
|
|
|
|
/* @param flag bit0= give directory x-permission where is r-permission
|
|
bit1= do not transfer ACL or xattr
|
|
bit2= record dev,inode (only if enabled by xorriso)
|
|
bit5= transfer ACL or xattr from eventual link target
|
|
*/
|
|
int Xorriso_transfer_properties(struct XorrisO *xorriso, struct stat *stbuf,
|
|
char *disk_path, IsoNode *node, int flag)
|
|
{
|
|
mode_t mode;
|
|
int ret= 1;
|
|
size_t num_attrs= 0, *value_lengths= NULL;
|
|
char **names= NULL, **values= NULL;
|
|
|
|
mode= stbuf->st_mode;
|
|
|
|
#ifdef Xorriso_with_aaiP
|
|
if((!(flag & 2)) && !(xorriso->do_aaip & 1))
|
|
/* Will drop ACL. Update mode S_IRWXG by eventual group:: ACL entry */
|
|
iso_local_get_perms_wo_acl(disk_path, &mode, flag & 32);
|
|
#endif
|
|
|
|
if((flag&1) && S_ISDIR(mode)) {
|
|
if(mode&S_IRUSR)
|
|
mode|= S_IXUSR;
|
|
if(mode&S_IRGRP)
|
|
mode|= S_IXGRP;
|
|
if(mode&S_IROTH)
|
|
mode|= S_IXOTH;
|
|
}
|
|
iso_node_set_permissions(node, mode & 07777);
|
|
iso_node_set_uid(node, stbuf->st_uid);
|
|
iso_node_set_gid(node, stbuf->st_gid);
|
|
iso_node_set_atime(node, stbuf->st_atime);
|
|
iso_node_set_mtime(node, stbuf->st_mtime);
|
|
iso_node_set_ctime(node, stbuf->st_ctime);
|
|
|
|
#ifdef Xorriso_with_aaiP
|
|
|
|
if((xorriso->do_aaip & 5) && !(flag & 2)) {
|
|
ret= iso_local_get_attrs(disk_path, &num_attrs, &names, &value_lengths,
|
|
&values, ((xorriso->do_aaip & 1) && !(flag & 2))
|
|
| ((!(xorriso->do_aaip & 4)) << 2)
|
|
| (flag & 32));
|
|
if(ret < 0) {
|
|
Xorriso_process_msg_queues(xorriso,0);
|
|
Xorriso_report_iso_error(xorriso, disk_path, ret,
|
|
"Error when obtaining local ACL and xattr", 0,
|
|
"FAILURE", 1 | 2);
|
|
ret= 0; goto ex;
|
|
}
|
|
ret= iso_node_set_attrs(node, num_attrs, names, value_lengths, values,
|
|
1 | 8);
|
|
if(ret < 0) {
|
|
Xorriso_process_msg_queues(xorriso,0);
|
|
Xorriso_report_iso_error(xorriso, "", ret,
|
|
"Error when setting ACL and xattr to image node",
|
|
0, "FAILURE", 1);
|
|
ret= 0; goto ex;
|
|
}
|
|
}
|
|
|
|
if((flag & 4) && (xorriso->do_aaip & 16)) {
|
|
ret= Xorriso_record_dev_inode(xorriso, disk_path, (dev_t) 0, (ino_t) 0,
|
|
(void *) node, "", flag & 32);
|
|
if(ret <= 0)
|
|
goto ex;
|
|
}
|
|
|
|
#endif /* Xorriso_with_aaiP */
|
|
|
|
ret= 1;
|
|
ex:;
|
|
Xorriso_process_msg_queues(xorriso,0);
|
|
|
|
#ifdef Xorriso_with_aaiP
|
|
iso_local_get_attrs(disk_path, &num_attrs, &names, &value_lengths,
|
|
&values, 1 << 15); /* free memory */
|
|
#endif /* Xorriso_with_aaiP */
|
|
|
|
return(ret);
|
|
}
|
|
|
|
|
|
int Xorriso_graft_split(struct XorrisO *xorriso, IsoImage *volume,
|
|
IsoDir *dir, char *disk_path, char *img_name,
|
|
char *nominal_source, char *nominal_target,
|
|
off_t size, IsoNode **node, int flag)
|
|
{
|
|
int ret;
|
|
IsoDir *new_dir= NULL;
|
|
IsoNode *part_node;
|
|
int partno, total_parts;
|
|
off_t offset;
|
|
char part_name[SfileadrL], sfe[5*SfileadrL];
|
|
|
|
ret= iso_tree_add_new_dir(dir, img_name, &new_dir);
|
|
if(ret<0)
|
|
return(ret);
|
|
*node= (IsoNode *) new_dir;
|
|
|
|
total_parts= size / xorriso->split_size;
|
|
if(size % xorriso->split_size)
|
|
total_parts++;
|
|
for(partno= 1; partno<=total_parts; partno++) {
|
|
offset = xorriso->split_size * (off_t) (partno-1);
|
|
Splitpart__compose(part_name, partno, total_parts, offset,
|
|
xorriso->split_size, size, 0);
|
|
ret= Xorriso_tree_graft_node(xorriso, volume,
|
|
new_dir, disk_path, part_name,
|
|
nominal_source, nominal_target,
|
|
offset, xorriso->split_size,
|
|
&part_node, 8);
|
|
if(ret<=0)
|
|
return(0);
|
|
}
|
|
sprintf(xorriso->info_text, "Split into %d parts: %s",
|
|
total_parts, Text_shellsafe(nominal_target, sfe, 0));
|
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
|
|
return(1);
|
|
}
|
|
|
|
|
|
/*
|
|
@param flag bit3= cut_out_node: offset and size are valid
|
|
*/
|
|
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 ret, stbuf_valid= 0;
|
|
struct stat stbuf;
|
|
char sfe[5*SfileadrL];
|
|
off_t size= 0;
|
|
|
|
if(lstat(disk_path, &stbuf) != -1) {
|
|
stbuf_valid= 1;
|
|
if(S_ISREG(stbuf.st_mode))
|
|
size= stbuf.st_size;
|
|
}
|
|
if(flag&8) {
|
|
if(cut_size > xorriso->file_size_limit && xorriso->file_size_limit > 0) {
|
|
sprintf(xorriso->info_text,
|
|
"File piece exceeds size limit of %.f bytes: %.f from %s\n",
|
|
(double) xorriso->file_size_limit, (double) cut_size,
|
|
Text_shellsafe(disk_path, sfe, 0));
|
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
|
|
return(0);
|
|
}
|
|
ret= iso_tree_add_new_cut_out_node(volume, dir, img_name, disk_path,
|
|
offset, cut_size, node);
|
|
if(ret<0)
|
|
goto ex;
|
|
} else {
|
|
if(xorriso->split_size > 0 && size > xorriso->split_size) {
|
|
ret= Xorriso_graft_split(xorriso, volume, dir, disk_path, img_name,
|
|
nominal_source, nominal_target, size,
|
|
node, 0);
|
|
if(ret<=0)
|
|
goto ex;
|
|
return(1);
|
|
} else if(size > xorriso->file_size_limit && xorriso->file_size_limit > 0) {
|
|
sprintf(xorriso->info_text,
|
|
"File exceeds size limit of %.f bytes: %s\n",
|
|
(double) xorriso->file_size_limit,
|
|
Text_shellsafe(disk_path, sfe, 0));
|
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
|
|
return(0);
|
|
}
|
|
ret= iso_tree_add_new_node(volume, dir, img_name, disk_path, node);
|
|
if(ret<0)
|
|
goto ex;
|
|
}
|
|
|
|
if(stbuf_valid && (xorriso->do_aaip & 16)) {
|
|
ret= Xorriso_record_dev_inode(xorriso, disk_path,
|
|
stbuf.st_dev, stbuf.st_ino, (void *) *node, "", 1);
|
|
if(ret <= 0)
|
|
goto ex;
|
|
}
|
|
|
|
ex:;
|
|
if(ret<0) {
|
|
Xorriso_process_msg_queues(xorriso,0);
|
|
Xorriso_report_iso_error(xorriso, nominal_source, ret,
|
|
"Cannot add node to tree", 0, "FAILURE", 1|2);
|
|
return(ret);
|
|
}
|
|
if(LIBISO_ISREG(*node))
|
|
xorriso->pacifier_byte_count+= iso_file_get_size((IsoFile *) *node);
|
|
return(1);
|
|
}
|
|
|
|
|
|
/* @param flag bit0= recursion is active
|
|
bit1= do not report added files
|
|
*/
|
|
int Xorriso_add_tree(struct XorrisO *xorriso, IsoDir *dir,
|
|
char *img_dir_path, char *disk_dir_path,
|
|
struct LinkiteM *link_stack, int flag)
|
|
{
|
|
IsoImage *volume;
|
|
IsoNode *node;
|
|
IsoSymlink *iso_symlink;
|
|
int ret, target_is_dir, source_is_dir, source_is_link, fret, was_failure= 0;
|
|
int do_not_dive, target_is_split= 0;
|
|
struct DirseQ *dirseq= NULL;
|
|
char *name, *img_name, *srcpt, *stbuf_src= "";
|
|
struct stat stbuf, hstbuf;
|
|
dev_t dir_dev;
|
|
struct LinkiteM *own_link_stack;
|
|
char *sfe= NULL, *sfe2= NULL;
|
|
char *disk_path= NULL, *img_path= NULL, *link_target= NULL;
|
|
|
|
/* Avoiding large local memory objects in order to save stack space */
|
|
sfe= malloc(5*SfileadrL);
|
|
sfe2= malloc(5*SfileadrL);
|
|
disk_path= malloc(2*SfileadrL);
|
|
img_path= malloc(2*SfileadrL);
|
|
link_target= calloc(SfileadrL, 1);
|
|
if(sfe==NULL || sfe2==NULL || disk_path==NULL || img_path==NULL ||
|
|
link_target==NULL) {
|
|
Xorriso_no_malloc_memory(xorriso, &sfe, 0);
|
|
{ret= -1; goto ex;}
|
|
}
|
|
|
|
own_link_stack= link_stack;
|
|
|
|
ret= Xorriso_get_volume(xorriso, &volume, 0);
|
|
if(ret<=0)
|
|
goto ex;
|
|
|
|
stbuf_src= disk_dir_path;
|
|
if(lstat(disk_dir_path, &stbuf)==-1)
|
|
goto cannot_open_dir;
|
|
dir_dev= stbuf.st_dev;
|
|
if(S_ISLNK(stbuf.st_mode)) {
|
|
if(!(xorriso->do_follow_links || (xorriso->do_follow_param && !(flag&1))))
|
|
{ret= 2; goto ex;}
|
|
stbuf_src= disk_dir_path;
|
|
if(stat(disk_dir_path, &stbuf)==-1)
|
|
goto cannot_open_dir;
|
|
if(dir_dev != stbuf.st_dev &&
|
|
!(xorriso->do_follow_mount || (xorriso->do_follow_param && !(flag&1))))
|
|
{ret= 2; goto ex;}
|
|
}
|
|
ret= Dirseq_new(&dirseq, disk_dir_path, 1);
|
|
if(ret<0) {
|
|
sprintf(xorriso->info_text,"Failed to create source filesystem iterator");
|
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
|
|
{ret= -1; goto ex;}
|
|
}
|
|
if(ret==0) {
|
|
cannot_open_dir:;
|
|
Xorriso_msgs_submit(xorriso, 0, disk_dir_path, 0, "ERRFILE", 0);
|
|
sprintf(xorriso->info_text,"Cannot open as source directory: %s",
|
|
Text_shellsafe(disk_dir_path, sfe, 0));
|
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
|
|
{ret= 0; goto ex;}
|
|
}
|
|
|
|
if(Sfile_str(disk_path, disk_dir_path,0)<=0)
|
|
{ret= -1; goto ex;}
|
|
if(disk_path[0]==0 || disk_path[strlen(disk_path)-1]!='/')
|
|
strcat(disk_path,"/");
|
|
name= disk_path+strlen(disk_path);
|
|
if(Sfile_str(img_path, img_dir_path, 0)<=0)
|
|
{ret= -1; goto ex;}
|
|
if(img_path[0] || img_path[strlen(img_path)-1]!='/')
|
|
strcat(img_path,"/");
|
|
img_name= img_path+strlen(img_path);
|
|
|
|
while(1) { /* loop over directory content */
|
|
stbuf_src= "";
|
|
Linkitem_reset_stack(&own_link_stack, link_stack, 0);
|
|
srcpt= disk_path;
|
|
Xorriso_process_msg_queues(xorriso,0);
|
|
ret= Dirseq_next_adr(dirseq,name,0); /* name is a pointer into disk_path */
|
|
if(ret==0)
|
|
break;
|
|
if(ret<0) {
|
|
sprintf(xorriso->info_text,"Failed to obtain next directory entry");
|
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
|
|
{ret= -1; goto ex;}
|
|
}
|
|
|
|
/* compare exclusions against disk_path resp. name */
|
|
ret= Xorriso_path_is_excluded(xorriso, disk_path, 0); /* (is never param) */
|
|
if(ret<0)
|
|
{ret= -1; goto ex;}
|
|
if(ret>0)
|
|
continue;
|
|
|
|
strcpy(img_name, name);
|
|
if(Xorriso_much_too_long(xorriso, strlen(img_path), 0)<=0)
|
|
{ret= 0; goto was_problem;}
|
|
if(Xorriso_much_too_long(xorriso, strlen(srcpt), 0)<=0)
|
|
{ret= 0; goto was_problem;}
|
|
stbuf_src= srcpt;
|
|
if(lstat(srcpt, &stbuf)==-1) {
|
|
cannot_lstat:;
|
|
Xorriso_msgs_submit(xorriso, 0, srcpt, 0, "ERRFILE", 0);
|
|
sprintf(xorriso->info_text,
|
|
"Cannot determine attributes of source file %s",
|
|
Text_shellsafe(srcpt, sfe, 0));
|
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
|
|
ret= 0; goto was_problem;
|
|
}
|
|
source_is_dir= 0;
|
|
source_is_link= S_ISLNK(stbuf.st_mode);
|
|
if(xorriso->do_follow_links && source_is_link) {
|
|
/* Xorriso_hop_link checks for wide link loops */
|
|
ret= Xorriso_hop_link(xorriso, srcpt, &own_link_stack, &hstbuf, 0);
|
|
if(ret<0)
|
|
goto was_problem;
|
|
if(ret==1) {
|
|
ret= Xorriso_resolve_link(xorriso, srcpt, link_target, 0);
|
|
if(ret<=0)
|
|
goto was_problem;
|
|
srcpt= link_target;
|
|
stbuf_src= srcpt;
|
|
if(lstat(srcpt, &stbuf)==-1)
|
|
goto cannot_lstat;
|
|
} else {
|
|
if(Xorriso_eval_problem_status(xorriso, 0, 1|2)<0)
|
|
{ret= 0; goto was_problem;}
|
|
ret= Xorriso_resolve_link(xorriso, srcpt, link_target, 1);
|
|
if(ret<=0)
|
|
goto was_problem;
|
|
}
|
|
} else if (S_ISLNK(stbuf.st_mode)) {
|
|
ret= Xorriso_resolve_link(xorriso, srcpt, link_target, 1);
|
|
if(ret<=0)
|
|
goto was_problem;
|
|
}
|
|
do_not_dive= 0;
|
|
if(S_ISDIR(stbuf.st_mode)) {
|
|
source_is_dir= 1;
|
|
if(dir_dev != stbuf.st_dev && !xorriso->do_follow_mount)
|
|
do_not_dive= 1;
|
|
}
|
|
|
|
/* does a node exist with this name ? */
|
|
node= NULL;
|
|
ret= Xorriso_node_from_path(xorriso, volume, img_path, &node, 1);
|
|
if(ret>0) {
|
|
target_is_dir= LIBISO_ISDIR(node);
|
|
target_is_split= 0;
|
|
if(target_is_dir)
|
|
target_is_split= Xorriso_is_split(xorriso, "", (void *) node, 1);
|
|
|
|
if(!((target_is_dir && !target_is_split) && source_is_dir)) {
|
|
Xorriso_process_msg_queues(xorriso,0);
|
|
|
|
/* handle overwrite situation */;
|
|
if(xorriso->do_overwrite==1 ||
|
|
(xorriso->do_overwrite==2 && !(target_is_dir && !target_is_split))) {
|
|
ret= Xorriso_rmi(xorriso, NULL, (off_t) 0, img_path, 1|8);
|
|
if(ret<=0)
|
|
goto was_problem;
|
|
if(ret==3) {
|
|
sprintf(xorriso->info_text, "User revoked adding of: %s",
|
|
Text_shellsafe(img_path, sfe, 0));
|
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
|
|
ret= 0; goto was_problem;
|
|
}
|
|
node= NULL;
|
|
} else {
|
|
Xorriso_msgs_submit(xorriso, 0, srcpt, 0, "ERRFILE", 0);
|
|
sprintf(xorriso->info_text,
|
|
"While grafting %s : file object exists and may not be overwritten by %s",
|
|
Text_shellsafe(img_path,sfe,0), Text_shellsafe(stbuf_src,sfe2,0));
|
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
|
|
ret= 0; goto was_problem;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(node==NULL) {
|
|
if(S_ISLNK(stbuf.st_mode)) {
|
|
|
|
/* ??? NG : A80107 : is this solved now ? */
|
|
/* <<< One should rather change libisofs so that iso_tree_add_node()
|
|
adds a disk_link as RR link, if RR is enabled */
|
|
|
|
ret= iso_tree_add_new_symlink(dir, img_name, link_target, &iso_symlink);
|
|
node= (IsoNode *) iso_symlink;
|
|
if(ret>0) {
|
|
ret= Xorriso_transfer_properties(xorriso, &stbuf, srcpt, node, 2 | 4);
|
|
if(ret<=0)
|
|
goto was_problem;
|
|
} else {
|
|
Xorriso_report_iso_error(xorriso, stbuf_src, ret,
|
|
"Cannot create symbolic link", 0, "FAILURE", 1|2);
|
|
{ret= 0; goto was_problem;}
|
|
}
|
|
} else {
|
|
ret= Xorriso_tree_graft_node(xorriso, volume, dir, srcpt, img_name,
|
|
"", img_path, (off_t) 0, (off_t) 0,
|
|
&node, 0);
|
|
}
|
|
}
|
|
if(node==NULL) {
|
|
Xorriso_process_msg_queues(xorriso,0);
|
|
Xorriso_msgs_submit(xorriso, 0, stbuf_src, 0, "ERRFILE", 0);
|
|
sprintf(xorriso->info_text, "Grafting failed: %s = %s",
|
|
Text_shellsafe(img_path,sfe,0), Text_shellsafe(stbuf_src,sfe2,0));
|
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
|
|
ret= 0; goto was_problem;
|
|
}
|
|
|
|
xorriso->pacifier_count++;
|