392 lines
8.1 KiB
C
392 lines
8.1 KiB
C
|
|
/*
|
|
cc -g -c \
|
|
-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1 -D_LARGEFILE64_SOURCE \
|
|
burn_wrap.c
|
|
*/
|
|
/* libburn wrappers for libisoburn
|
|
|
|
Copyright 2007 Thomas Schmitt, <scdbackup@gmx.net>
|
|
*/
|
|
|
|
/* <<< A70929 : hardcoded CD-RW with fabricated -msinfo = 0,1600
|
|
#define Hardcoded_cd_rW 1
|
|
#define Hardcoded_cd_rw_c1 0
|
|
#define Hardcoded_cd_rw_nwA 1600
|
|
*/
|
|
|
|
|
|
#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 <libburn/libburn.h>
|
|
#include <libisofs/libisofs.h>
|
|
#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 */
|
|
|
|
|
|
int isoburn_initialize(void)
|
|
{
|
|
if(!iso_init())
|
|
return(0);
|
|
if(!burn_initialize())
|
|
return(0);
|
|
isoburn_destroy_all(&isoburn_list_start, 0); /* isoburn_list_start= NULL */
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
/** Examine the media and sets appropriate emulation if needed.
|
|
*/
|
|
static int isoburn_welcome_media(struct isoburn **o, struct burn_drive *d,
|
|
int flag)
|
|
{
|
|
int ret;
|
|
struct burn_multi_caps *caps= NULL;
|
|
|
|
ret= burn_disc_get_multi_caps(d, BURN_WRITE_NONE, &caps, 0);
|
|
if(ret<=0)
|
|
goto ex;
|
|
ret= isoburn_new(o, 0);
|
|
if(ret<=0)
|
|
goto ex;
|
|
(*o)->drive= d;
|
|
ret= isoburn_create_data_source(*o);
|
|
if(ret<=0)
|
|
goto ex;
|
|
|
|
#ifdef Hardcoded_cd_rW
|
|
/* <<< A70929 : hardcoded CD-RW with fabricated -msinfo */
|
|
caps->start_adr= 0;
|
|
(*o)->fabricated_disc_status= BURN_DISC_APPENDABLE;
|
|
/* is not set with MMC multi-session: (*o)->nwa= Hardcoded_cd_rw_nwA; */
|
|
#endif
|
|
|
|
if(caps->start_adr) { /* set emulation to overwriteable */
|
|
(*o)->emulation_mode= 1;
|
|
ret= isoburn_start_emulation(*o, 0);
|
|
if(ret<=0) {
|
|
(*o)->emulation_mode= -1;
|
|
goto ex;
|
|
}
|
|
} else {
|
|
|
|
/* >>> recognize unsuitable media */;
|
|
|
|
}
|
|
ret= 1;
|
|
ex:
|
|
if(caps!=NULL)
|
|
burn_disc_free_multi_caps(&caps);
|
|
return(ret);
|
|
}
|
|
|
|
|
|
int isoburn_drive_scan_and_grab(struct burn_drive_info *drive_infos[],
|
|
char *adr, int load)
|
|
{
|
|
int ret, conv_ret;
|
|
char libburn_drive_adr[BURN_DRIVE_ADR_LEN];
|
|
struct isoburn *o= NULL;
|
|
char msg[BURN_MSGS_MESSAGE_LEN+4096];
|
|
|
|
conv_ret= burn_drive_convert_fs_adr(adr, libburn_drive_adr);
|
|
if(conv_ret<=0) {
|
|
sprintf(msg, "Unsuitable drive address: '%s'\n",adr);
|
|
msg[BURN_MSGS_MESSAGE_LEN-1]= 0;
|
|
burn_msgs_submit(0, msg, 0, "SORRY", NULL);
|
|
ret= 0; goto ex;
|
|
}
|
|
|
|
ret= burn_drive_scan_and_grab(drive_infos, libburn_drive_adr, load);
|
|
if(ret<=0)
|
|
goto ex;
|
|
ret= isoburn_welcome_media(&o, (*drive_infos)[0].drive, 0);
|
|
if(ret<=0)
|
|
goto ex;
|
|
|
|
ret= 1;
|
|
ex:
|
|
if(ret<=0)
|
|
isoburn_destroy(&o,0);
|
|
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 media emulation and eventual isoburn emulator of drive.
|
|
@return -1 unsuitable media, 0 generic media, 1 emulated media.
|
|
*/
|
|
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)
|
|
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>0)
|
|
return(BURN_DISC_APPENDABLE);
|
|
return(BURN_DISC_BLANK);
|
|
}
|
|
|
|
|
|
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);
|
|
}
|
|
|
|
|
|
void isoburn_disc_erase(struct burn_drive *drive, int fast)
|
|
{
|
|
int ret;
|
|
struct isoburn *o;
|
|
|
|
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);
|
|
return;
|
|
}
|
|
if(o->emulation_mode>0) {
|
|
ret= isoburn_invalidate_iso(o, 0);
|
|
if(ret<=0)
|
|
burn_drive_cancel(drive);
|
|
return;
|
|
}
|
|
}
|
|
burn_disc_erase(drive, fast);
|
|
}
|
|
|
|
|
|
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)
|
|
return(0);
|
|
ret= isoburn_find_emulator(&o, d, 0);
|
|
if(ret<0)
|
|
return(0);
|
|
if(ret>0) if(o->emulation_mode>0) {
|
|
*start_lba= 0;
|
|
return(1);
|
|
}
|
|
return(burn_disc_get_msc1(d, start_lba));
|
|
}
|
|
|
|
|
|
int isoburn_disc_track_lba_nwa(struct burn_drive *d,
|
|
struct burn_write_opts *opts,
|
|
int trackno, int *lba, int *nwa)
|
|
{
|
|
int ret;
|
|
struct isoburn *o;
|
|
|
|
#ifdef Hardcoded_cd_rW
|
|
/* <<< A70929 : hardcoded CD-RW with fabricated -msinfo */
|
|
*lba= Hardcoded_cd_rw_c1;
|
|
*nwa= Hardcoded_cd_rw_nwA;
|
|
return(1);
|
|
#endif
|
|
|
|
ret= isoburn_find_emulator(&o, d, 0);
|
|
if(ret<0)
|
|
return(0);
|
|
if(ret>0) if(o->emulation_mode>0) {
|
|
*lba= 0;
|
|
*nwa= o->nwa;
|
|
return(1);
|
|
}
|
|
return(burn_disc_track_lba_nwa(d, opts, trackno, lba, nwa));
|
|
}
|
|
|
|
|
|
void isoburn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
|
|
{
|
|
int ret, multi= 1;
|
|
struct isoburn *o;
|
|
struct burn_drive *drive;
|
|
|
|
drive= burn_write_opts_get_drive(opts);
|
|
ret= isoburn_find_emulator(&o, drive, 0);
|
|
if(ret<0)
|
|
return;
|
|
if(o!=NULL) {
|
|
if(o->emulation_mode!=0) {
|
|
multi= 0;
|
|
if(o->emulation_mode>0 && o->nwa >= 0)
|
|
burn_write_opts_set_start_byte(opts, ((off_t) o->nwa) * (off_t) 2048);
|
|
}
|
|
}
|
|
burn_write_opts_set_multi(opts, multi);
|
|
|
|
#ifdef Hardcoded_cd_rW
|
|
/* <<< A70929 : hardcoded CD-RW with fabricated -msinfo */
|
|
burn_write_opts_set_start_byte(opts,
|
|
((off_t) Hardcoded_cd_rw_nwA) * (off_t) 2048);
|
|
#endif
|
|
|
|
burn_disc_write(opts, disc);
|
|
}
|
|
|
|
|
|
void isoburn_drive_release(struct burn_drive *drive, int eject)
|
|
{
|
|
int ret;
|
|
struct isoburn *o;
|
|
|
|
ret= isoburn_find_emulator(&o, drive, 0);
|
|
if(ret<0)
|
|
return;
|
|
if(o!=NULL) {
|
|
isoburn_free_data_source(o);
|
|
isoburn_destroy(&o, 0);
|
|
}
|
|
burn_drive_release(drive, eject);
|
|
}
|
|
|
|
|
|
void isoburn_finish(void)
|
|
{
|
|
isoburn_destroy_all(&isoburn_list_start, 0);
|
|
burn_finish();
|
|
iso_finish();
|
|
}
|
|
|
|
|
|
int isoburn_needs_emulation(struct burn_drive *drive)
|
|
{
|
|
int ret;
|
|
struct isoburn *o;
|
|
enum burn_disc_status s;
|
|
|
|
s= isoburn_disc_get_status(drive);
|
|
if(s!=BURN_DISC_BLANK && s!=BURN_DISC_APPENDABLE)
|
|
return(-1);
|
|
ret= isoburn_find_emulator(&o, drive, 0);
|
|
if(ret<0)
|
|
return(-1);
|
|
if(ret>0)
|
|
if(o->emulation_mode>0)
|
|
return(1);
|
|
return(0);
|
|
}
|
|
|
|
|
|
int isoburn_set_start_byte(struct isoburn *o, off_t value, int flag)
|
|
{
|
|
int ret;
|
|
struct burn_drive *drive = o->drive;
|
|
struct burn_multi_caps *caps= NULL;
|
|
|
|
ret= burn_disc_get_multi_caps(drive, BURN_WRITE_NONE, &caps, 0);
|
|
if(ret<=0)
|
|
goto ex;
|
|
if(!caps->start_adr)
|
|
{ret= 0; goto ex;}
|
|
o->min_start_byte= value;
|
|
if(value % caps->start_alignment)
|
|
value+= caps->start_alignment - (value % caps->start_alignment);
|
|
o->nwa= value/2048;
|
|
ret= 1;
|
|
ex:
|
|
if(caps!=NULL)
|
|
burn_disc_free_multi_caps(&caps);
|
|
return(ret);
|
|
}
|
|
|
|
|
|
#ifdef Libburn_obsoleted_on_its_way_ouT
|
|
|
|
void isoburn_write_opts_set_start_byte(struct burn_write_opts *opts,
|
|
off_t value)
|
|
{
|
|
int ret;
|
|
struct isoburn *o;
|
|
struct burn_drive *drive;
|
|
|
|
drive= burn_write_opts_get_drive(opts);
|
|
ret= isoburn_find_emulator(&o, drive, 0);
|
|
if(ret<=0) /* no emulation, no burn_write_opts_set_start_byte() */
|
|
return;
|
|
ret = isoburn_set_start_byte(o, value, 0);
|
|
if(ret<=0)
|
|
return;
|
|
burn_write_opts_set_start_byte(opts, ((off_t) o->nwa) * (off_t) 2048);
|
|
}
|
|
|
|
#endif /* Libburn_obsoleted_on_its_way_ouT */
|
|
|