libisoburn/src/burn_wrap.c

428 lines
9.4 KiB
C
Raw Normal View History

2007-09-01 18:20:53 +00:00
/*
2007-09-04 23:03:21 +00:00
cc -g -c \
-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1 -D_LARGEFILE64_SOURCE \
burn_wrap.c
2007-09-01 18:20:53 +00:00
*/
/* libburn wrappers for libisoburn
Copyright 2007 Thomas Schmitt, <scdbackup@gmx.net>
*/
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
2007-09-04 23:03:21 +00:00
#include <fcntl.h>
2007-09-01 18:20:53 +00:00
#include <libburn/libburn.h>
#include <libisofs/libisofs.h>
2007-09-01 18:20:53 +00:00
#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 */
2007-09-04 23:03:21 +00:00
return(1);
2007-09-01 18:20:53 +00:00
}
/** 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;
2007-09-01 18:20:53 +00:00
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;
2007-09-01 18:20:53 +00:00
goto ex;
}
} else {
/* >>> recognize unsuitable media */;
}
2007-09-06 11:58:51 +00:00
/* <<< now planned to be done by app
ret = isoburn_read_volset(*o);
if(ret<=0) {
(*o)->emulation_mode= -1;
goto ex;
2007-09-01 18:20:53 +00:00
}
2007-09-06 11:58:51 +00:00
*/
2007-09-01 18:20:53 +00:00
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)
2007-09-01 18:20:53 +00:00
{
int ret, treatment= 0, conv_ret;
2007-09-01 18:20:53 +00:00
struct stat stbuf;
char libburn_drive_adr[BURN_DRIVE_ADR_LEN], *adrpt, *stdio_adr= NULL;
2007-09-01 18:20:53 +00:00
struct isoburn *o= NULL;
/* Treatment decision criteria
Prefixes "grow:" leads to: treatment 1, image growing
Prefix "modify:" leads to: treatment 2, image modification
Anything else is decided automatically
If suitable as libburn drive address: treatment 1 ("stdio:" fits here)
else if non-existent or regular file: treatment 2
else if block device : treatment 1
else : unsuitable target
*/
adrpt= adr;
if(strncmp(adr, "grow:", 5)==0) {
treatment= 1;
adrpt+= 5;
if(stat(adrpt,&stbuf)!=-1) {
2007-09-01 18:20:53 +00:00
if(S_ISREG(stbuf.st_mode) || S_ISBLK(stbuf.st_mode)) {
stdio_adr= calloc(strlen(adrpt)+6+1, 1);
if(stdio_adr==NULL)
{ret= -1; goto ex;}
sprintf(stdio_adr, "stdio:%s", adrpt); /* use pseudo-drive */
adrpt= stdio_adr;
2007-09-01 18:20:53 +00:00
}
}
} else if(strncmp(adr, "modify:", 7)==0) {
adrpt+= 7;
treatment= 2;
if(stat(adrpt,&stbuf)!=-1) {
if(! S_ISREG(stbuf.st_mode)) {
2007-09-01 18:20:53 +00:00
/* >>> we need a gateway to the libisofs/libburn message system */;
fprintf(stderr, "LIBISOBURN: unsuitable target for modify: '%s'\n",adr);
2007-09-01 18:20:53 +00:00
ret= 0; goto ex;
}
}
sprintf(stdio_adr, "stdio:%s", adrpt); /* use pseudo-drive */
adrpt= stdio_adr;
} else {
/* >>> interpret "read:" , "write:" for modification on MMC drives */;
}
conv_ret= burn_drive_convert_fs_adr(adrpt, libburn_drive_adr);
if(treatment==0) { /* undecided yet, make a decision or declare failure */
if(conv_ret>0)
treatment= 1; /* Device file leading to MMC drive or "stdio:" address */
else {
if(stat(adrpt,&stbuf)==-1) {
/* burn_drive_scan_and_grab() will check whether the directory exists */
treatment= 2;
} else if(S_ISREG(stbuf.st_mode))
treatment= 2;
else if(S_ISBLK(stbuf.st_mode))
treatment= 1;
if(treatment>=0) {
sprintf(stdio_adr, "stdio:%s", adrpt); /* use pseudo-drive */
adrpt= stdio_adr;
conv_ret= 1; /* All "stdio:" addresses are ok for now */
}
}
}
if(conv_ret<=0 || treatment<=0) { /* Failure */
/* >>> we need a gateway to the libisofs/libburn message system */;
fprintf(stderr, "LIBISOBURN: unsuitable drive address: '%s'\n", adrpt);
ret= 0; goto ex;
2007-09-01 18:20:53 +00:00
}
ret= burn_drive_scan_and_grab(drive_infos, adrpt, load);
if(ret<=0)
goto ex;
ret= isoburn_welcome_media(&o, (*drive_infos)[0].drive, 0);
if(ret<=0)
goto ex;
if(o!=NULL)
o->treatment= treatment;
2007-09-01 18:20:53 +00:00
ret= 1;
ex:
if(ret<=0)
isoburn_destroy(&o,0);
if(stdio_adr!=NULL)
free(stdio_adr);
2007-09-01 18:20:53 +00:00
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;
2007-09-04 23:03:21 +00:00
ret= isoburn_welcome_media(&o, drive, 0);
2007-09-01 18:20:53 +00:00
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.
*/
2007-09-06 11:58:51 +00:00
int isoburn_find_emulator(struct isoburn **pt,
2007-09-01 18:20:53 +00:00
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);
2007-09-01 18:20:53 +00:00
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);
}
2007-09-01 18:20:53 +00:00
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) {
2007-09-04 23:03:21 +00:00
/* To cause a negative reply with burn_drive_wrote_well() */
burn_drive_cancel(drive);
2007-09-01 18:20:53 +00:00
return;
}
if(o->emulation_mode>0) {
ret= isoburn_invalidate_iso(o, 0);
2007-09-04 23:03:21 +00:00
if(ret<=0)
burn_drive_cancel(drive);
2007-09-01 18:20:53 +00:00
return;
}
}
burn_disc_erase(drive, fast);
}
int isoburn_disc_get_msc1(struct burn_drive *d, int *start_lba)
{
int ret;
struct isoburn *o;
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));
2007-09-01 18:20:53 +00:00
}
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;
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));
2007-09-01 18:20:53 +00:00
}
2007-09-04 23:03:21 +00:00
void isoburn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
2007-09-01 18:20:53 +00:00
{
int ret, multi= 1;
2007-09-04 23:03:21 +00:00
struct isoburn *o;
struct burn_drive *drive;
2007-09-04 23:03:21 +00:00
drive= burn_write_opts_get_drive(opts);
ret= isoburn_find_emulator(&o, drive, 0);
2007-09-04 23:03:21 +00:00
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);
burn_disc_write(opts, disc);
2007-09-01 18:20:53 +00:00
}
void isoburn_drive_release(struct burn_drive *drive, int eject)
{
2007-09-04 23:03:21 +00:00
int ret;
2007-09-01 18:20:53 +00:00
struct isoburn *o;
ret= isoburn_find_emulator(&o, drive, 0);
if(ret<0)
return;
if(o!=NULL)
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)
2007-09-01 18:20:53 +00:00
{
int ret;
struct burn_drive *drive = o->drive;
2007-09-01 18:20:53 +00:00
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;}
2007-09-01 18:20:53 +00:00
o->min_start_byte= value;
if(value % caps->start_alignment)
value+= caps->start_alignment - (value % caps->start_alignment);
o->nwa= value/2048;
ret= 1;
2007-09-01 18:20:53 +00:00
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);
2007-09-01 18:20:53 +00:00
}
#endif /* Libburn_obsoleted_on_its_way_ouT */
2007-09-01 18:20:53 +00:00