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.

2162 lines
62 KiB

/*
cc -g -c \
-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1 -D_LARGEFILE64_SOURCE \
burn_wrap.c
*/
/* libburn wrappers for libisoburn
Copyright 2007 - 2017 Thomas Schmitt, <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
/* <<< A70929 : hardcoded CD-RW with fabricated -msinfo
#define Hardcoded_cd_rW 1
#define Hardcoded_cd_rw_c1 12999
#define Hardcoded_cd_rw_nwA 152660
*/
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <regex.h>
#ifndef Xorriso_standalonE
#include <libburn/libburn.h>
#include <libisofs/libisofs.h>
#ifdef Xorriso_with_libjtE
#include <libjte/libjte.h>
#endif
#else /* ! Xorriso_standalonE */
#include "../libisofs/libisofs.h"
#include "../libburn/libburn.h"
#ifdef Xorriso_with_libjtE
#include "../libjte/libjte.h"
#endif
#endif /* Xorriso_standalonE */
#include "libisoburn.h"
#include "isoburn.h"
/* The global list of isoburn objects. Usually there is only one. */
extern struct isoburn *isoburn_list_start; /* in isoburn.c */
/* Default values for application provided msgs_submit methods.
To be attached to newly acquired drives.
Storage location is isoburn.c
*/
extern int (*libisoburn_default_msgs_submit)
(void *handle, int error_code, char msg_text[],
int os_errno, char severity[], int flag);
extern void *libisoburn_default_msgs_submit_handle;
extern int libisoburn_default_msgs_submit_flag;
static int isoburn_emulate_toc(struct burn_drive *d, int flag);
int isoburn_initialize(char msg[1024], int flag)
{
int major, minor, micro, bad_match= 0, no_iso_init= 0;
/* First the ugly compile time checks for header version compatibility.
If everything matches, then they produce no C code. In case of mismatch,
intentionally faulty C code will be inserted.
*/
#ifdef iso_lib_header_version_major
/* The minimum requirement of libisoburn towards the libisofs header
at compile time is defined in libisoburn/libisoburn.h :
isoburn_libisofs_req_major
isoburn_libisofs_req_minor
isoburn_libisofs_req_micro
It gets compared against the version macros in libisofs/libisofs.h :
iso_lib_header_version_major
iso_lib_header_version_minor
iso_lib_header_version_micro
If the header is too old then the following code shall cause failure of
libisoburn 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: 'LIBISOFS_MISCONFIGURATION' undeclared (first use in this function)
error: 'INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libisofs_dot_h_TOO_OLD__SEE_libisoburn_dot_h_AND_burn_wrap_dot_h' undeclared (first use in this function)
error: 'LIBISOFS_MISCONFIGURATION_' undeclared (first use in this function)
*/
/* The indentation is an advise of man gcc to help old compilers ignoring */
#if isoburn_libisofs_req_major > iso_lib_header_version_major
#define Isoburn_libisofs_dot_h_too_olD 1
#endif
#if isoburn_libisofs_req_major == iso_lib_header_version_major && isoburn_libisofs_req_minor > iso_lib_header_version_minor
#define Isoburn_libisofs_dot_h_too_olD 1
#endif
#if isoburn_libisofs_req_minor == iso_lib_header_version_minor && isoburn_libisofs_req_micro > iso_lib_header_version_micro
#define Isoburn_libisofs_dot_h_too_olD 1
#endif
#ifdef Isoburn_libisofs_dot_h_too_olD
LIBISOFS_MISCONFIGURATION = 0;
INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libisofs_dot_h_TOO_OLD__SEE_libisoburn_dot_h_AND_burn_wrap_dot_c = 0;
LIBISOFS_MISCONFIGURATION_ = 0;
#endif
#endif /* iso_lib_header_version_major */
/* The minimum requirement of libisoburn towards the libburn header
at compile time is defined in libisoburn/libisoburn.h :
isoburn_libburn_req_major
isoburn_libburn_req_minor
isoburn_libburn_req_micro
It gets compared against the version macros in libburn/libburn.h :
burn_header_version_major
burn_header_version_minor
burn_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: 'LIBBURN_MISCONFIGURATION' undeclared (first use in this function)
error: 'INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libburn_dot_h_TOO_OLD__SEE_libisoburn_dot_h_and_burn_wrap_dot_h' undeclared (first use in this function)
error: 'LIBBURN_MISCONFIGURATION_' undeclared (first use in this function)
*/
/* The indentation is an advise of man gcc to help old compilers ignoring */
#if isoburn_libburn_req_major > burn_header_version_major
#define Isoburn_libburn_dot_h_too_olD 1
#endif
#if isoburn_libburn_req_major == burn_header_version_major && isoburn_libburn_req_minor > burn_header_version_minor
#define Isoburn_libburn_dot_h_too_olD 1
#endif
#if isoburn_libburn_req_minor == burn_header_version_minor && isoburn_libburn_req_micro > burn_header_version_micro
#define Isoburn_libburn_dot_h_too_olD 1
#endif
#ifdef Isoburn_libburn_dot_h_too_olD
LIBBURN_MISCONFIGURATION = 0;
INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libburn_dot_h_TOO_OLD__SEE_libisoburn_dot_h_and_burn_wrap_dot_h = 0;
LIBBURN_MISCONFIGURATION_ = 0;
#endif
#ifdef Xorriso_with_libjtE
/* The minimum requirement of libisoburn towards the libjte header
at compile time is the same as the one of a usable libisofs towards libjte.
So the requirement is defined in libisofs/libisofs.h :
iso_libjte_req_major , iso_libjte_req_minor , iso_libjte_req_micro
*/
/* The indentation is an advise of man gcc to help old compilers ignoring */
#if iso_libjte_req_major > LIBJTE_VERSION_MAJOR
#define Libisofs_libjte_dot_h_too_olD 1
#endif
#if iso_libjte_req_major == LIBJTE_VERSION_MAJOR && iso_libjte_req_minor > LIBJTE_VERSION_MINOR
#define Libisofs_libjte_dot_h_too_olD 1
#endif
#if iso_libjte_req_minor == LIBJTE_VERSION_MINOR && iso_libjte_req_micro > LIBJTE_VERSION_MICRO
#define Libisofs_libjte_dot_h_too_olD 1
#endif
#ifdef Libisofs_libjte_dot_h_too_olD
LIBJTE_MISCONFIGURATION = 0;
INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_libjte_dot_h_TOO_OLD__SEE_libisofs_dot_h_AND_burn_wrap.c_c = 0;
LIBJTE_MISCONFIGURATION_ = 0;
#endif
#endif /* Xorriso_with_libjtE */
/* End of ugly compile time tests (scroll up for explanation) */
msg[0]= 0;
#ifdef Xorriso_with_libjtE
libjte__version(&major, &minor, &micro);
sprintf(msg + strlen(msg), "libjte-%d.%d.%d ", major, minor, micro);
if (libjte__is_compatible(LIBJTE_VERSION_MAJOR, LIBJTE_VERSION_MINOR,
LIBJTE_VERSION_MICRO, 0)) {
sprintf(msg+strlen(msg), "ok, ");
} else {
sprintf(msg + strlen(msg),
"- TOO OLD -, need at least libjte-%d.%d.%d ,\n",
LIBJTE_VERSION_MAJOR, LIBJTE_VERSION_MINOR,
LIBJTE_VERSION_MICRO);
bad_match= 1;
no_iso_init= 1; /* iso_init() will fail anyway */
}
#endif /* Xorriso_with_libjtE */
if(!no_iso_init) {
if(iso_init()<0) {
sprintf(msg+strlen(msg), "Cannot initialize libisofs\n");
return(0);
}
}
iso_lib_version(&major, &minor, &micro);
sprintf(msg+strlen(msg), "libisofs-%d.%d.%d ", major, minor, micro);
#ifdef iso_lib_header_version_major
if(iso_lib_is_compatible(iso_lib_header_version_major,
iso_lib_header_version_minor,
iso_lib_header_version_micro)) {
sprintf(msg+strlen(msg), "ok, ");
} else {
sprintf(msg+strlen(msg),"- TOO OLD -, need at least libisofs-%d.%d.%d ,\n",
iso_lib_header_version_major, iso_lib_header_version_minor,
iso_lib_header_version_micro);
bad_match= 1;
}
#else
if(iso_lib_is_compatible(isoburn_libisofs_req_major,
isoburn_libisofs_req_minor,
isoburn_libisofs_req_micro)) {
sprintf(msg+strlen(msg), "suspicious, ");
} else {
sprintf(msg+strlen(msg),"- TOO OLD -, need at least libisofs-%d.%d.%d ,\n",
isoburn_libisofs_req_major, isoburn_libisofs_req_minor,
isoburn_libisofs_req_micro);
bad_match= 1;
}
#endif /* ! iso_lib_header_version_major */
if(!burn_initialize()) {
sprintf(msg+strlen(msg), "Cannot initialize libburn\n");
return(0);
}
burn_version(&major, &minor, &micro);
sprintf(msg+strlen(msg), "libburn-%d.%d.%d ", major, minor, micro);
if(major > burn_header_version_major
|| (major == burn_header_version_major
&& (minor > burn_header_version_minor
|| (minor == burn_header_version_minor
&& micro >= burn_header_version_micro)))) {
sprintf(msg+strlen(msg), "ok, ");
} else {
sprintf(msg+strlen(msg), "- TOO OLD -, need at least libburn-%d.%d.%d ,\n",
burn_header_version_major, burn_header_version_minor,
burn_header_version_micro);
bad_match= 1;
}
isoburn_version(&major, &minor, &micro);
sprintf(msg+strlen(msg), "for libisoburn-%d.%d.%d", major, minor, micro);
if(bad_match)
return(0);
isoburn_destroy_all(&isoburn_list_start, 0); /* isoburn_list_start= NULL */
return(1);
}
/* API @since 0.1.0 */
int isoburn_libisofs_req(int *major, int *minor, int *micro)
{
*major= iso_lib_header_version_major;
*minor= iso_lib_header_version_minor;
*micro= iso_lib_header_version_micro;
return(1);
}
/* API @since 0.1.0 */
int isoburn_libburn_req(int *major, int *minor, int *micro)
{
*major= burn_header_version_major;
*minor= burn_header_version_minor;
*micro= burn_header_version_micro;
return(1);
}
/* API @since 0.6.4 */
int isoburn_libjte_req(int *major, int *minor, int *micro)
{
#ifdef Xorriso_with_libjtE
*major= LIBJTE_VERSION_MAJOR;
*minor= LIBJTE_VERSION_MINOR;
*micro= LIBJTE_VERSION_MICRO;
#else
*major= *minor= *micro= 0;
#endif /* ! Xorriso_with_libjtE */
return(1);
}
int isoburn_set_msgs_submit(int (*msgs_submit)(void *handle, int error_code,
char msg_text[], int os_errno,
char severity[], int flag),
void *submit_handle, int submit_flag, int flag)
{
libisoburn_default_msgs_submit= msgs_submit;
libisoburn_default_msgs_submit_handle= submit_handle;
libisoburn_default_msgs_submit_flag= submit_flag;
return(1);
}
int isoburn_is_intermediate_dvd_rw(struct burn_drive *d, int flag)
{
int profile, ret= 0, format_status, num_formats;
char profile_name[80];
enum burn_disc_status s;
off_t format_size= -1;
unsigned bl_sas;
s= isoburn_disc_get_status(d);
ret= burn_disc_get_profile(d, &profile, profile_name);
if(ret>0 && profile==0x13)
ret= burn_disc_get_formats(d, &format_status, &format_size,
&bl_sas, &num_formats);
if(ret>0 && profile==0x13 && s==BURN_DISC_BLANK &&
format_status==BURN_FORMAT_IS_UNKNOWN)
return(1);
return(0);
}
/** Examines the medium and sets appropriate emulation if needed.
@param flag bit0= pretent blank on overwritable media
bit3= if the drive reports a -ROM profile then try to read
table of content by scanning for ISO image headers.
bit4= do not emulate TOC on overwritable media
bit5= ignore ACL from external filesystems
bit6= ignore POSIX Extended Attributes from external filesystems
bit7= pretend -ROM and scan for table of content
bit9= when scanning for ISO 9660 sessions on overwritable
media: Do not demand a valid superblock at LBA 0
and scan until end of medium.
bit10= if not bit6: accept all xattr namespaces from external
filesystems, not only "user.".
*/
static int isoburn_welcome_media(struct isoburn **o, struct burn_drive *d,
int flag)
{
int ret, profile, readonly= 0, role, random_access;
int emulation_started= 0;
struct burn_multi_caps *caps= NULL;
struct isoburn_toc_entry *t;
char profile_name[80];
struct isoburn_toc_disc *disc= NULL;
struct isoburn_toc_session **sessions;
struct isoburn_toc_track **tracks;
int num_sessions= 0, num_tracks= 0, track_count= 0, session_no= 0;
char msg[80];
enum burn_disc_status s;
#ifndef Hardcoded_cd_rW
int lba, nwa;
#endif
s= burn_disc_get_status(d);
profile_name[0]= 0;
ret= burn_disc_get_profile(d, &profile, profile_name);
if(ret<=0)
profile= 0x00;
ret= burn_disc_get_multi_caps(d, BURN_WRITE_NONE, &caps, 0);
if(ret<0) /*== 0 is read-only medium, but it is too early to reject it here */
goto ex;
if(ret==0 || (flag & 128))
readonly= 1;
if(flag & 128)
flag = (flag & ~ 16) | 8;
ret= isoburn_find_emulator(o, d, 0);
if(ret >= 0 && *o != NULL)
isoburn_destroy(o, 0);
ret= isoburn_new(o, 0);
if(ret<=0)
goto ex;
(*o)->drive= d;
(*o)->msgs_submit= libisoburn_default_msgs_submit;
(*o)->msgs_submit_handle= libisoburn_default_msgs_submit_handle;
(*o)->msgs_submit_flag= libisoburn_default_msgs_submit_flag;
iso_image_set_ignore_aclea((*o)->image,
((flag >> 5 ) & 3) | ((!!(flag & 1024)) << 3));
#ifdef Hardcoded_cd_rW
/* <<< A70929 : hardcoded CD-RW with fabricated -msinfo */
caps->start_adr= 0;
(*o)->fabricated_disc_status= BURN_DISC_APPENDABLE;
#endif
role= burn_drive_get_drive_role(d);
random_access= caps->start_adr || role == 4;
if(random_access)
(*o)->emulation_mode= 1;
if(random_access && !readonly) { /* set emulation to overwritable */
ret= isoburn_is_intermediate_dvd_rw(d, 0);
if(ret>0) {
(*o)->min_start_byte= 0;
(*o)->nwa= 0;
(*o)->zero_nwa= 0;
}
if((flag & 1) && role != 4 && role != 5) {
(*o)->nwa= (*o)->zero_nwa;
(*o)->fabricated_disc_status= BURN_DISC_BLANK;
} else {
ret= isoburn_start_emulation(*o, 0);
if(ret<=0) {
(*o)->emulation_mode= -1;
goto ex;
}
emulation_started= 1;
/* try to read emulated toc */
ret= isoburn_emulate_toc(d, (flag & 16) | ((!!(flag & 512)) << 1));
if(ret<0) {
(*o)->emulation_mode= -1;
goto ex;
}
}
} else {
/* >>> recognize unsuitable media (but allow read-only media) */;
if(readonly && s != BURN_DISC_EMPTY) {
/* >>> ts B10712: This maps BURN_DISC_UNSUITABLE to BURN_DISC_FULL
which can hardly be correct in general.
??? What reason does this have ?
*/
(*o)->fabricated_disc_status= BURN_DISC_FULL;
/* This might be an overwritable medium in a -ROM drive.
Pitfall:
Multi-session media which bear a xorriso image for overwritables
in their first session would get a TOC of that first image rather
than of the medium.
It is not possible to distinguish a BD-RE from a single session
BD-R with an image for overwritables. But as soon as the medium
bears 2 logical tracks it cannot be overwritable.
So count the number of tracks first.
*/
disc= isoburn_toc_drive_get_disc(d);
if(disc != NULL) {
sessions= isoburn_toc_disc_get_sessions(disc, &num_sessions);
for(session_no= 0; session_no < num_sessions; session_no++) {
tracks= isoburn_toc_session_get_tracks(sessions[session_no],
&num_tracks);
if(tracks != NULL)
track_count+= num_tracks;
}
isoburn_toc_disc_free(disc);
}
sprintf(msg, "ROM medium has libburn track count = %d", track_count);
isoburn_msgs_submit(*o, 0x00060000, msg, 0, "DEBUG", 0);
if((flag & 16) || track_count >= 2) {
ret= 0; /* toc emulation off, or not overwritable */
} else {
ret= isoburn_start_emulation(*o, 1);
if(ret<=0) {
(*o)->emulation_mode= -1;
goto ex;
}
emulation_started= 1;
ret= isoburn_emulate_toc(d, 1 | ((!!(flag & 512)) << 1));
if(ret<0)
goto ex;
else if(ret > 0)
(*o)->emulation_mode= 1;
}
if(ret == 0 && (profile != 0x08 || (flag & 128)) && (flag & 8)) {
/* This might also be multi-session media which do not
get shown with a decent TOC.
CD-R TOC (profile 0x08) can be trusted. Others not.
Do a scan search of ISO headers.
*/
if(!emulation_started) {
ret= isoburn_start_emulation(*o, 1);
if(ret<=0) {
(*o)->emulation_mode= -1;
goto ex;
}
}
ret= isoburn_emulate_toc(d, 1 | 2);
if(ret<0)
goto ex;
if(ret>0) { /* point msc1 to last session */
if((*o)->toc!=NULL) {
for(t= (*o)->toc; t->next!=NULL; t= t->next)
; /* clang wants newline in empty loops */
(*o)->fabricated_msc1= t->start_lba;
}
}
}
}
#ifdef Hardcoded_cd_rW
(*o)->nwa= Hardcoded_cd_rw_nwA;
#else
ret= burn_disc_track_lba_nwa(d, NULL, 0, &lba, &nwa);
if(ret>0)
(*o)->nwa= nwa;
if((*o)->nwa < (*o)->zero_nwa)
(*o)->zero_nwa= 0;
#endif
}
ret= 1;
ex:
if(caps!=NULL)
burn_disc_free_multi_caps(&caps);
return(ret);
}
/**
@param flag bit0= load
bit1= regard overwritable media as blank
bit2= if the drive is a regular disk file: truncate it to
the write start address
bit3= if the drive reports a -ROM profile then try to read
table of content by scanning for ISO image headers.
(depending on media type and drive state this might
help or it might make the resulting toc even worse)
bit4= do not emulate TOC on overwritable media
bit5= ignore ACL from external filesystems
bit6= ignore POSIX Extended Attributes from external filesystems
bit7= pretend -ROM profile and scan for table of content
bit8= re-assess (*drive_infos)[0] rather than acquiring adr
bit9= when scanning for ISO 9660 sessions on overwritable
media: Do not demand a valid superblock at LBA 0
and scan until end of medium.
bit10= if not bit6: accept all xattr namespaces from external
filesystems, not only "user.".
*/
int isoburn_drive_aquire(struct burn_drive_info *drive_infos[],
char *adr, int flag)
{
int ret, drive_grabbed= 0;
struct isoburn *o= NULL;
int conv_ret;
char *libburn_drive_adr= NULL;
/* Should be obsolete by new drive addressing of libburn-0.5.2 */
/* but helps with kernel 2.4 to use /dev/sr */
libburn_drive_adr= calloc(1, BURN_DRIVE_ADR_LEN);
if(libburn_drive_adr == NULL)
{ret= -1; goto ex;}
conv_ret= burn_drive_convert_fs_adr(adr, libburn_drive_adr);
if(conv_ret<=0)
strcpy(libburn_drive_adr, adr);
if(flag & 256)
ret= burn_drive_re_assess((*drive_infos)[0].drive, 0);
else
ret= burn_drive_scan_and_grab(drive_infos, libburn_drive_adr, flag&1);
if(ret<=0)
goto ex;
drive_grabbed= 1;
ret= isoburn_welcome_media(&o, (*drive_infos)[0].drive,
(flag & (8 | 16 | 32 | 64 | 128 | 512 | 1024)) |
!!(flag&2));
if(ret<=0)
goto ex;
if(flag&4) {
ret= isoburn_find_emulator(&o, (*drive_infos)[0].drive, 0);
if(ret>0 && o!=NULL)
o->truncate= 1;
}
ret= 1;
ex:
if(ret<=0) {
if(drive_grabbed)
burn_drive_release((*drive_infos)[0].drive, 0);
isoburn_destroy(&o, 0);
}
if(libburn_drive_adr != NULL)
free(libburn_drive_adr);
return(ret);
}
int isoburn_drive_scan_and_grab(struct burn_drive_info *drive_infos[],
char *adr, int load)
{
int ret;
ret= isoburn_drive_aquire(drive_infos, adr, !!load);
return(ret);
}
int isoburn_drive_grab(struct burn_drive *drive, int load)
{
int ret;
struct isoburn *o= NULL;
ret= burn_drive_grab(drive, load);
if(ret<=0)
goto ex;
ret= isoburn_welcome_media(&o, drive, 0);
if(ret<=0)
goto ex;
ret= 1;
ex:
if(ret<=0)
isoburn_destroy(&o,0);
return(ret);
}
/** Retrieve medium emulation and eventual isoburn emulator of drive.
@return -1 unsuitable medium, 0 generic medium, 1 emulated medium.
*/
int isoburn_find_emulator(struct isoburn **pt,
struct burn_drive *drive, int flag)
{
int ret;
ret= isoburn_find_by_drive(pt, drive, 0);
if(ret<=0)
return(0);
if((*pt)->emulation_mode==-1) {
isoburn_msgs_submit(*pt, 0x00060000,
"Unsuitable drive and medium state", 0, "FAILURE", 0);
return(-1);
}
if((*pt)->emulation_mode==0)
return(0);
return(1);
}
enum burn_disc_status isoburn_disc_get_status(struct burn_drive *drive)
{
int ret;
struct isoburn *o;
ret= isoburn_find_emulator(&o, drive, 0);
if(ret<0)
return(BURN_DISC_UNSUITABLE);
if(o!=NULL)
if(o->fabricated_disc_status!=BURN_DISC_UNREADY)
return(o->fabricated_disc_status);
if(ret==0)
return(burn_disc_get_status(drive));
/* emulated status */
if(o->emulation_mode==-1)
return(BURN_DISC_UNSUITABLE);
if(o->nwa>o->zero_nwa)
return(BURN_DISC_APPENDABLE);
return(BURN_DISC_BLANK);
}
int isoburn_disc_pretend_full_uncond(struct burn_drive *drive)
{
int ret;
struct isoburn *o;
ret= isoburn_find_emulator(&o, drive, 0);
if(ret > 0 && o != NULL)
o->fabricated_disc_status= BURN_DISC_FULL;
ret= burn_disc_pretend_full_uncond(drive);
return(ret);
}
int isoburn_disc_erasable(struct burn_drive *d)
{
int ret;
struct isoburn *o;
ret= isoburn_find_emulator(&o, d, 0);
if(ret>0)
if(o->emulation_mode==1)
return(1);
return burn_disc_erasable(d);
}
static int isoburn_is_overwritable(struct burn_drive *drive, int flag)
{
char name[80];
int profile, ret;
ret= burn_disc_get_profile(drive, &profile, name);
if(ret <= 0)
return(0);
if(profile == 0x12 || profile == 0x13 || profile == 0x1a || profile == 0x43)
return(1);
return(0);
}
void isoburn_disc_erase(struct burn_drive *drive, int fast)
{
int ret, do_pseudo_blank= 0, role;
struct isoburn *o;
enum burn_disc_status s;
char *zero_buffer= NULL;
struct burn_multi_caps *caps= NULL;
zero_buffer= calloc(1, Libisoburn_target_head_sizE);
if(zero_buffer == NULL) {
/* To cause a negative reply with burn_drive_wrote_well() */
burn_drive_cancel(drive);
goto ex;
}
ret= isoburn_find_emulator(&o, drive, 0);
if(ret>0) {
if(o->emulation_mode==-1) {
/* To cause a negative reply with burn_drive_wrote_well() */
burn_drive_cancel(drive);
goto ex;
}
role = burn_drive_get_drive_role(drive);
if (role == 5) {
/* libburn will truncate the random-access write-only file
to zero size and change its state */
burn_disc_erase(drive, fast);
o->fabricated_disc_status= burn_disc_get_status(drive);
o->nwa= o->zero_nwa= 0;
goto ex;
}
if(o->emulation_mode > 0) { /* might be readonly with emulated sessions */
ret= burn_disc_get_multi_caps(drive, BURN_WRITE_NONE, &caps, 0);
if(ret <= 0) /* Maybe because of burn_disc_pretend_full() */
do_pseudo_blank= isoburn_is_overwritable(drive, 0); /* known profiles */
else if(caps->start_adr)
do_pseudo_blank= 1;
}
if(do_pseudo_blank) {
s= isoburn_disc_get_status(drive);
if(s==BURN_DISC_FULL) { /* unknown data format in first 64 kB */
memset(zero_buffer, 0, Libisoburn_target_head_sizE);
ret= burn_random_access_write(drive, (off_t) 0, zero_buffer,
(off_t) Libisoburn_target_head_sizE, 1);
} else {
ret= isoburn_invalidate_iso(o, 0);
}
if(ret<=0)
burn_drive_cancel(drive); /* mark run as failure */
goto ex;
}
}
burn_disc_erase(drive, fast);
ex:;
if(caps!=NULL)
burn_disc_free_multi_caps(&caps);
if(zero_buffer != NULL)
free(zero_buffer);
}
off_t isoburn_disc_available_space(struct burn_drive *d,
struct burn_write_opts *opts)
{
int ret;
struct isoburn *o;
struct burn_write_opts *eff_opts= NULL, *local_opts= NULL;
enum burn_disc_status s;
off_t avail;
eff_opts= opts;
ret= isoburn_find_emulator(&o, d, 0);
if(ret>0 && o!=NULL)
if(o->emulation_mode!=0) {
s= isoburn_disc_get_status(d);
if(s==BURN_DISC_FULL) /* unknown data format in first 64 kB */
return((off_t) 0);
local_opts= burn_write_opts_new(d);
eff_opts= local_opts;
burn_write_opts_set_start_byte(eff_opts, ((off_t) o->nwa) * (off_t) 2048);
}
avail= burn_disc_available_space(d, eff_opts);
if(local_opts!=NULL)
burn_write_opts_free(local_opts);
local_opts= NULL;
return(avail);
}
int isoburn_disc_get_msc1(struct burn_drive *d, int *start_lba)
{
int ret;
struct isoburn *o;
#ifdef Hardcoded_cd_rW
/* <<< A70929 : hardcoded CD-RW with fabricated -msinfo */
*start_lba= Hardcoded_cd_rw_c1;
return(1);
#endif
if(isoburn_disc_get_status(d)!=BURN_DISC_APPENDABLE &&
isoburn_disc_get_status(d)!=BURN_DISC_FULL) {