Begin of porting to next generation libisofs

master
Thomas Schmitt 15 years ago
parent a1cd5596fc
commit dc2a8f1ab0
  1. 13
      Makefile.am
  2. 453
      ng_src/burn_wrap.c
  3. 74
      ng_src/data_source.c
  4. 335
      ng_src/isoburn.c
  5. 134
      ng_src/isoburn.h
  6. 314
      ng_src/isofs_wrap.c
  7. 379
      ng_src/libisoburn.h
  8. 2
      test/xorriso_timestamp.h

@ -25,12 +25,15 @@ libinclude_HEADERS = \
## ========================================================================= ##
## Build test applications
noinst_PROGRAMS = \
test/test
noinst_PROGRAMS =
test_test_CPPFLAGS = -Ilibisofs -Ilibburn -Ilibisoburn
test_test_LDADD = $(src_libisoburn_la_OBJECTS) $(THREAD_LIBS) -lburn -lisofs
test_test_SOURCES = test/test.c
# ts A80110 : I am too lazy for now to apply the ng patch to test.c .
# noinst_PROGRAMS =
# test/test
# test_test_CPPFLAGS = -Ilibisofs -Ilibburn -Ilibisoburn
# test_test_LDADD = $(src_libisoburn_la_OBJECTS) $(THREAD_LIBS) -lburn -lisofs
# test_test_SOURCES = test/test.c
bin_PROGRAMS =

@ -0,0 +1,453 @@
/*
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
#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 <libburn/libburn.h>
/* >>> NG */
#include <libisofs/nglibisofs.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(!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, lba, nwa;
struct burn_multi_caps *caps= NULL;
ret= burn_disc_get_multi_caps(d, BURN_WRITE_NONE, &caps, 0);
if(ret<0) /* == 0 is read-only media, but it is too early to reject it here */
goto ex;
ret= isoburn_new(o, 0);
if(ret<=0)
goto ex;
(*o)->drive= d;
#ifdef Hardcoded_cd_rW
/* <<< A70929 : hardcoded CD-RW with fabricated -msinfo */
caps->start_adr= 0;
(*o)->fabricated_disc_status= BURN_DISC_APPENDABLE;
#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 (but allow read-only media) */;
#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;
#endif
}
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, drive_grabbed= 0;
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;
drive_grabbed= 1;
ret= isoburn_welcome_media(&o, (*drive_infos)[0].drive, 0);
if(ret<=0)
goto ex;
ret= 1;
ex:
if(ret<=0) {
if(drive_grabbed)
burn_drive_release((*drive_infos)[0].drive, 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 &&
isoburn_disc_get_status(d)!=BURN_DISC_FULL)
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;
struct isoburn *o;
struct burn_drive *drive;
char reasons[BURN_REASONS_LEN],msg[160+BURN_REASONS_LEN];
enum burn_write_types write_type;
drive= burn_write_opts_get_drive(opts);
ret= isoburn_find_emulator(&o, drive, 0);
if(ret<0)
return;
if(o!=NULL) {
o->wrote_well= -1;
if(o->emulation_mode!=0) {
burn_write_opts_set_multi(opts, 0);
if(o->emulation_mode>0 && o->nwa >= 0)
burn_write_opts_set_start_byte(opts, ((off_t) o->nwa) * (off_t) 2048);
}
}
write_type= burn_write_opts_auto_write_type(opts, disc, reasons, 0);
if (write_type == BURN_WRITE_NONE) {
sprintf(msg, "Failed to find a suitable write mode:\n%s", reasons);
burn_msgs_submit(0, msg, 0, "SORRY", NULL);
if(o!=NULL)
o->wrote_well= 0;
/* To cause a negative reply with burn_drive_wrote_well() */
burn_drive_cancel(drive);
return;
}
/*
sprintf(reasons, "%d", (int) write_type);
fprintf(stderr, "isoburn_EXPERIMENTAL: write_type = %s\n",
(write_type == BURN_WRITE_SAO ? "SAO" :
(write_type == BURN_WRITE_TAO ? "TAO" : reasons)));
*/
#ifdef Hardcoded_cd_rW
/* <<< A70929 : hardcoded CD-RW with fabricated -msinfo */
fprintf(stderr, "Setting write address to LBA %d\n", Hardcoded_cd_rw_nwA);
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_destroy(&o, 0);
}
burn_drive_release(drive, eject);
}
void isoburn_finish(void)
{
isoburn_destroy_all(&isoburn_list_start, 0);
burn_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;
/* If suitable for alignment, round up to full 16 sector addresses */
if((o->nwa%16) && ((16*2048) % caps->start_alignment)==0 )
o->nwa+= 16 - (o->nwa%16);
ret= 1;
ex:
if(caps!=NULL)
burn_disc_free_multi_caps(&caps);
return(ret);
}
int isoburn_get_min_start_byte(struct burn_drive *d, off_t *start_byte,
int flag)
{
int ret;
struct isoburn *o;
ret= isoburn_find_emulator(&o, d, 0);
if(ret<0)
return(-1);
if(ret==0)
return(0);
*start_byte= o->min_start_byte;
if(o->min_start_byte<=0)
return(0);
return(1);
}
int isoburn_drive_wrote_well(struct burn_drive *d)
{
int ret;
struct isoburn *o;
ret= isoburn_find_emulator(&o, d, 0);
if(ret<0)
return(-1);
if(o!=NULL)
if(o->wrote_well>=0)
return(o->wrote_well);
ret= burn_drive_wrote_well(d);
return ret;
}
int isoburn_get_fifo_status(struct burn_drive *d, int *size, int *free_bytes,
char **status_text)
{
int ret;
struct isoburn *o;
ret= isoburn_find_emulator(&o, d, 0);
if(ret<0)
return(-1);
if(o==NULL)
return(0);
if(o->fifo==NULL)
return(0);
ret= burn_fifo_inquire_status(o->fifo, size, free_bytes, status_text);
return(ret);
}

@ -0,0 +1,74 @@
/*
data source for libisoburn.
Copyright 2007 Vreixo Formoso Lopes <metalpain2002@yahoo.es>
*/
#include <assert.h>
#include <stdlib.h>
#include <libburn/libburn.h>
/* >>> NG */
#include <libisofs/nglibisofs.h>
#include "isoburn.h"
static int
ds_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer)
{
int ret;
struct burn_drive *d;
off_t count;
assert(src && buffer);
d = (struct burn_drive*)src->data;
ret = burn_read_data(d, (off_t) lba * (off_t) 2048, (char *) buffer,
2048, &count, 0);
if (ret <= 0 )
return -1;
return 1;
}
static int
ds_open(IsoDataSource *src)
{
/* nothing to do, device is always grabbed */
return 1;
}
static int
ds_close(IsoDataSource *src)
{
/* nothing to do, device is always grabbed */
return 1;
}
static void
ds_free_data(IsoDataSource *src)
{
/* nothing to do */;
}
IsoDataSource *
isoburn_data_source_new(struct burn_drive *d)
{
IsoDataSource *ret;
if (d==NULL)
return NULL;
ret = malloc(sizeof(IsoDataSource));
if (!ret)
return NULL;
ret->refcount = 1;
ret->read_block = ds_read_block;
ret->open = ds_open;
ret->close = ds_close;
ret->free_data = ds_free_data;
ret->data = d;
return ret;
}

@ -0,0 +1,335 @@
/*
cc -g -c isoburn.c
*/
/*
Class core of libisoburn.
Copyright 2007 Vreixo Formoso Lopes <metalpain2002@yahoo.es>
and Thomas Schmitt <scdbackup@gmx.net>
*/
/* ( derived from stub generated by CgeN on Sat, 01 Sep 2007 12:04:36 GMT ) */
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <libburn/libburn.h>
/* >>> NG */
#include <libisofs/nglibisofs.h>
#include "libisoburn.h"
#include "isoburn.h"
/* -------------------------- isoburn ----------------------- */
/* The global list of isoburn objects. Usually there is only one.
>>> we are not ready for multiple control threads yet. See >>> mutex .
Multiple burns under one control thread should work.
*/
struct isoburn *isoburn_list_start= NULL;
int isoburn_new(struct isoburn **objpt, int flag)
{
struct isoburn *o;
int i, ret;
*objpt= o= (struct isoburn *) malloc(sizeof(struct isoburn));
if(o==NULL)
return(-1);
o->drive= NULL;
o->emulation_mode= 0;
o->min_start_byte= 0;
o->nwa= 0;
o->fifo= NULL;
o->wrote_well= -1;
o->fabricated_disc_status= BURN_DISC_UNREADY;
for(i=0;i<65536;i++)
o->target_iso_head[i]= 0;
o->image= NULL;
o->prev= NULL;
o->next= NULL;
ret= iso_image_new("NEW", &o->image);
if(ret<0)
goto failed;
isoburn_link(o, isoburn_list_start, 1);
return(1);
failed:;
isoburn_destroy(objpt, 0);
return(-1);
}
int isoburn_destroy(struct isoburn **objpt, int flag)
{
struct isoburn *o;
o= *objpt;
if(o==NULL)
return(0);
/* >>> mutex */
if(o==isoburn_list_start)
isoburn_list_start= o->next;
if(o->prev!=NULL)
o->prev->next= o->next;
if(o->next!=NULL)
o->next->prev= o->prev;
/* >>> end mutex */
if(o->image!=NULL)
iso_image_unref(o->image);
if(o->fifo!=NULL)
burn_source_free(o->fifo);
free((char *) o);
*objpt= NULL;
return(1);
}
int isoburn_destroy_all(struct isoburn **objpt, int flag)
{
struct isoburn *o,*n;
o= *objpt;
if(o==NULL)
return(0);
for(;o->prev!=NULL;o= o->prev);
for(;o!=NULL;o= n) {
n= o->next;
isoburn_destroy(&o,0);
}
*objpt= NULL;
return(1);
}
int isoburn_get_target_image(struct isoburn *o, IsoImage **pt, int flag)
{
*pt= o->image;
return(1);
}
int isoburn_get_prev(struct isoburn *o, struct isoburn **pt, int flag)
{
*pt= o->prev;
return(1);
}
int isoburn_get_next(struct isoburn *o, struct isoburn **pt, int flag)
{
*pt= o->next;
return(1);
}
int isoburn_link(struct isoburn *o, struct isoburn *link, int flag)
/*
bit0= insert as link->prev rather than as link->next
*/
{
/* >>> mutex */
if(isoburn_list_start==NULL ||
(isoburn_list_start==link && (flag&1)))
isoburn_list_start= o;
if(o->prev!=NULL)
o->prev->next= o->next;
if(o->next!=NULL)
o->next->prev= o->prev;
o->prev= o->next= NULL;
if(link==NULL)
return(1);
if(flag&1) {
o->next= link;
o->prev= link->prev;
if(o->prev!=NULL)
o->prev->next= o;
link->prev= o;
} else {
o->prev= link;
o->next= link->next;
if(o->next!=NULL)
o->next->prev= o;
link->next= o;
}
/* >>> end mutex */
return(1);
}
int isoburn_count(struct isoburn *o, int flag)
/* flag: bit1= count from start of list */
{
int counter= 0;
if(flag&2)
for(;o->prev!=NULL;o= o->prev);
for(;o!=NULL;o= o->next)
counter++;
return(counter);
}
int isoburn_by_idx(struct isoburn *o, int idx, struct isoburn **pt, int flag)
/* flag: bit0= fetch first (idx<0) or last (idx>0) item in list
bit1= address from start of list */
{
int i,abs_idx;
struct isoburn *npt;
if(flag&2)
for(;o->prev!=NULL;o= o->prev);
abs_idx= (idx>0?idx:-idx);
*pt= o;
for(i= 0;(i<abs_idx || (flag&1)) && *pt!=NULL;i++) {
if(idx>0)
npt= o->next;
else
npt= o->prev;
if(npt==NULL && (flag&1))
break;
*pt= npt;
}
return(*pt!=NULL);
}
int isoburn_find_by_drive(struct isoburn **pt, struct burn_drive *d, int flag)
{
struct isoburn *o;
*pt= NULL;
for(o= isoburn_list_start;o!=NULL;o= o->next)
if(o->drive==d) {
*pt= o;
return(1);
}
return(0);
}
static
int isoburn_prepare_disc_aux(struct burn_drive *d, struct burn_disc **disc,
struct isoburn_source_opts *opts, int new_img)
{
struct burn_source *wsrc;
struct burn_session *session;
struct burn_track *track;
struct isoburn *o;
Ecma119WriteOpts wopts;
enum burn_disc_status state;
int ret, chunks;
ret= isoburn_find_emulator(&o, d, 0);
if(ret<0 || o==NULL)
return -1;
o->wrote_well= 0; /* early end will be registered as failure */
state = isoburn_disc_get_status(d);
if (state != BURN_DISC_BLANK && state != BURN_DISC_APPENDABLE
&& (state != BURN_DISC_FULL || ! new_img)) {
/* unsuitable status */
return -2;
}
wopts.level = opts->level;
wopts.rockridge = opts->rockridge;
wopts.joliet = opts->joliet;
wopts.omit_version_numbers = opts->omit_version_numbers;
wopts.allow_deep_paths = opts->allow_deep_paths;
wopts.joliet_longer_paths = opts->joliet_longer_paths;
/* wopts.copy_eltorito = opts->copy_eltorito; */
wopts.sort_files = opts->sort_files;
wopts.replace_dir_mode = opts->replace_dir_mode;
wopts.replace_file_mode = opts->replace_file_mode;
wopts.replace_uid = opts->replace_uid;
wopts.replace_gid = opts->replace_gid;
wopts.dir_mode = opts->dir_mode;
wopts.file_mode = opts->file_mode;
wopts.gid = opts->gid;
wopts.uid = opts->uid;
wopts.output_charset = opts->ouput_charset;
if (new_img) {
wopts.ms_block = 0;
wopts.appendable = 0;
wopts.overwrite = NULL;
} else {
int lba, nwa;
ret = isoburn_disc_track_lba_nwa(d, NULL, 0, &lba, &nwa);
if (ret != 1)
return -3;
if (nwa == 0 && state == BURN_DISC_APPENDABLE) {
/* invalid nwa */
return -4;
}
wopts.ms_block = nwa;
wopts.appendable = 1;
wopts.overwrite = o->target_iso_head;
}
ret = iso_image_create_burn_source(o->image, &wopts, &wsrc);
if (ret < 0)
return -1;
/* TODO check return values for failure. propertly clean-up on error */
chunks= 32;
if(opts->fifo_size >= 64*1024 && opts->fifo_size <= 1024.0 * 1024.0 * 1024.0){
chunks= opts->fifo_size/2048;
if(chunks*2048 < opts->fifo_size)
chunks++;
}
o->fifo = burn_fifo_source_new(wsrc, 2048, chunks, 0);
burn_source_free(wsrc);
if (o->fifo == NULL) {
fprintf(stderr, "Cannot attach fifo\n");
return -1;
}
*disc = burn_disc_create();
session = burn_session_create();
burn_disc_add_session(*disc, session, BURN_POS_END);
track = burn_track_create();
burn_track_set_source(track, o->fifo);
burn_session_add_track(session, track, BURN_POS_END);
/* give up local references */
burn_track_free(track);
burn_session_free(session);
o->wrote_well= -1; /* neutral */
return 1;
}
int isoburn_prepare_disc(struct burn_drive *d, struct burn_disc **disc,
struct isoburn_source_opts *opts)
{
return isoburn_prepare_disc_aux(d, disc, opts, 0);
}
int isoburn_prepare_new_image(struct burn_drive *d, struct burn_disc **disc,
struct isoburn_source_opts *opts)
{
return isoburn_prepare_disc_aux(d, disc, opts, 1);
}

@ -0,0 +1,134 @@
/*
Class struct of libisoburn.
Copyright 2007 Vreixo Formoso Lopes <metalpain2002@yahoo.es>
and Thomas Schmitt <scdbackup@gmx.net>
*/
#ifndef Isoburn_includeD
#define Isoburn_includeD
/* for uint8_t */
#include <stdint.h>
struct isoburn {
/* The libburn drive to which this isoburn object is related
Most isoburn calls will use a burn_drive as object handle */
struct burn_drive *drive;
/* -1= inappropriate media state detected
0= libburn multi-session media, resp. undecided yet
1= random access media */
int emulation_mode;
/* Although rarely used, libburn can operate on several
drives simultaneously. */
struct isoburn *prev;
struct isoburn *next;
/* --- My part --- */
/* Start address as given by image examination (bytes, not blocks) */
off_t min_start_byte;
/* Aligned start address to be used for processing (counted in blocks) */
int nwa;
/* Eventual freely fabricated isoburn_disc_get_status().
BURN_DISC_UNREADY means that normally emulated status is in effect.
*/
enum burn_disc_status fabricated_disc_status;
/* The fifo which is installed between track and libisofs burn_source
*/
struct burn_source *fifo;
/* Indicator wether the most recent burn run worked :
-1 = undetermined, ask libburn , 0 = failure , 1 = success
To be inquired by isoburn_drive_wrote_well()
*/
int wrote_well;
/* --- Vreixo's part --- */
/* Buffered ISO head from media (should that become part of
ecma119_read_opts ?) */
uint8_t target_iso_head[65536];
/* Libisofs image context */
IsoImage *image;
};
/* Creation and disposal function */
int isoburn_new(struct isoburn **objpt, int flag);
int isoburn_destroy(struct isoburn **objpt, int flag);
/* Eventual readers for public attributes */
/* ( put into separate .h file then ) */
int isoburn_get_emulation_mode(struct isoburn *o, int *pt, int flag);
int isoburn_get_target_volset(struct isoburn *o, IsoImage **pt, int flag);
/* List management */
int isoburn_get_prev(struct isoburn *o, struct isoburn **pt, int flag);
int isoburn_get_next(struct isoburn *o, struct isoburn **pt, int flag);
int isoburn_destroy_all(struct isoburn **objpt, int flag);
int isoburn_link(struct isoburn *o, struct isoburn *link, int flag);
int isoburn_count(struct isoburn *o, int flag);
int isoburn_by_idx(struct isoburn *o, int idx, struct isoburn **pt, int flag);
int isoburn_find_by_drive(struct isoburn **pt, struct burn_drive *d, int flag);
/* Non API inner interfaces */
/* Calls from burn_wrap.c into isofs_wrap.c */
int isoburn_start_emulation(struct isoburn *o, int flag);
int isoburn_invalidate_iso(struct isoburn *o, int flag);
/* Calls from isofs_wrap.c into burn_wrap.c */
/** Get an eventual isoburn object which is wrapped around the drive.
@param pt Eventually returns a pointer to the found object.
It is allowed to become NULL if return value is -1 or 0.
In this case, the drive is a genuine libburn drive
with no emulation activated by isoburn.
@param drive The drive to be searched for
@param flag unused yet
@return -1 unsuitable media, 0 generic media, 1 emulated media.
*/
int isoburn_find_emulator(struct isoburn **pt,
struct burn_drive *drive, int flag);
/** Set the start address for an emulated add-on session. The value will
be rounded up to the alignment necessary for the media. The aligned
value will be divided by 2048 and then put into o->nwa .
@param o The isoburn object to be programmed.
@param value The start address in bytes
@param flag unused yet
@return <=0 is failure , >0 success
*/
int isoburn_set_start_byte(struct isoburn *o, off_t value, int flag);
/** Get a data source suitable for read from a drive using burn_read_data()
function.
@param d drive to read from. Must be grabbed.
@return the data source, NULL on error. Must be freed with libisofs
iso_data_source_unref() function. Note: this doesn't release
the drive.
*/
IsoDataSource *
isoburn_data_source_new(struct burn_drive *d);
#endif /* Isoburn_includeD */

@ -0,0 +1,314 @@
/*
cc -g -c isofs_wrap.c
*/
/*
libisofs related functions of libisoburn.
Copyright 2007 Vreixo Formoso Lopes <metalpain2002@yahoo.es>
Thomas Schmitt <scdbackup@gmx.net>
*/
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <libburn/libburn.h>
/* >>> NG */
#include <libisofs/nglibisofs.h>
#include "isoburn.h"
#include "libisoburn.h"
#define BP(a,b) [(b) - (a) + 1]
struct ecma119_pri_vol_desc
{
uint8_t vol_desc_type BP(1, 1);
uint8_t std_identifier BP(2, 6);
uint8_t vol_desc_version BP(7, 7);
uint8_t unused1 BP(8, 8);
uint8_t system_id BP(9, 40);
uint8_t volume_id BP(41, 72);
uint8_t unused2 BP(73, 80);
uint8_t vol_space_size BP(81, 88);
uint8_t unused3 BP(89, 120);
uint8_t vol_set_size BP(121, 124);
uint8_t vol_seq_number BP(125, 128);
uint8_t block_size BP(129, 132);
uint8_t path_table_size BP(133, 140);
uint8_t l_path_table_pos BP(141, 144);
uint8_t opt_l_path_table_pos BP(145, 148);
uint8_t m_path_table_pos BP(149, 152);
uint8_t opt_m_path_table_pos BP(153, 156);
uint8_t root_dir_record BP(157, 190);
uint8_t vol_set_id BP(191, 318);
uint8_t publisher_id BP(319, 446);
uint8_t data_prep_id BP(447, 574);
uint8_t application_id BP(575, 702);
uint8_t copyright_file_id BP(703, 739);
uint8_t abstract_file_id BP(740, 776);
uint8_t bibliographic_file_id BP(777, 813);
uint8_t vol_creation_time BP(814, 830);
uint8_t vol_modification_time BP(831, 847);
uint8_t vol_expiration_time BP(848, 864);
uint8_t vol_effective_time BP(865, 881);
uint8_t file_structure_version BP(882, 882);
uint8_t reserved1 BP(883, 883);
uint8_t app_use BP(884, 1395);
uint8_t reserved2 BP(1396, 2048);
};
static
uint32_t iso_read_lsb(const uint8_t *buf, int bytes)
{
int i;
uint32_t ret = 0;
for (i=0; i<bytes; i++) {
ret += ((uint32_t) buf[i]) << (i*8);
}
return ret;
}
/* API function. See libisoburn.h
*/
IsoImage *isoburn_get_attached_image(struct burn_drive *d)
{
int ret;
struct isoburn *o= NULL;
ret = isoburn_find_emulator(&o, d, 0);
if (ret < 0)
return NULL;
if (o == NULL) {
return NULL;
}
iso_image_ref(o->image);
return o->image;
}
/* API function. See libisoburn.h
*/
int isoburn_read_image(struct burn_drive *d,
struct isoburn_read_opts *read_opts,
IsoImage **image)
{
int ret;
struct iso_read_opts ropts;
struct iso_read_image_features features;
enum burn_disc_status status= BURN_DISC_BLANK;
IsoDataSource *ds= NULL;
struct isoburn *o= NULL;
if(read_opts==NULL) {
/* >>> program error */;
return(-1);
}
if(d != NULL) {
ret = isoburn_find_emulator(&o, d, 0);
if (ret < 0)
return 0;
if (o == NULL) {
return -1;
}
status = isoburn_disc_get_status(d);
}
if (d == NULL || status == BURN_DISC_BLANK || read_opts->pretend_blank) {
/*
* Blank disc, we create a new image without files.
*/
if (d == NULL) {
if (image==NULL)
return -1;
/* create a new image */
ret = iso_image_new("NEW", image);
if (ret < 0)
return ret;
} else {
/* use isoburn image */
if (image) {
*image = o->image;
iso_image_ref(*image); /*protects object from premature free*/
}
}
return 1;
}
if (status != BURN_DISC_APPENDABLE && status != BURN_DISC_FULL) {
/* incorrect disc status */
return -4;
}
ret = isoburn_disc_get_msc1(d, (int*) &ropts.block);
if (ret < 0)
return -2;
ropts.norock = read_opts->norock;
ropts.nojoliet = read_opts->nojoliet;
ropts.preferjoliet = read_opts->preferjoliet;
ropts.mode = read_opts->mode;
ropts.uid = read_opts->uid;
ropts.gid = read_opts->gid;
/* create the data source */
ds = isoburn_data_source_new(d);
ret = iso_image_import(o->image, ds, &ropts, &features);
iso_data_source_unref(ds);
if (ret < 0)
return ret;
if (image) {
*image = o->image;
iso_image_ref(*image); /*protects object from premature free*/
}
read_opts->hasRR = features.hasRR;
read_opts->hasJoliet = features.hasJoliet;
read_opts->size = features.size;
return 1;
}
/* API function. See libisoburn.h
*/
int isoburn_attach_image(struct burn_drive *d, IsoImage *image)
{
int ret;
struct isoburn *o;
if (image == NULL)
return -1;
ret = isoburn_find_emulator(&o, d, 0);
if (ret < 0)
return 0;
if (o == NULL)
return -1;
if(o->image != NULL)
iso_image_unref(o->image);
o->image = image;
return(1);
}
/* API function. See libisoburn.h
*/
int isoburn_activate_session(struct burn_drive *drive)
{
int ret;
struct isoburn *o;
ret = isoburn_find_emulator(&o, drive, 0);
if (ret < 0)
return -1;
if (o->emulation_mode != 1)
return 1; /* don't need to activate session */
if (o->fabricated_disc_status != BURN_DISC_APPENDABLE)
return 1;
ret = burn_random_access_write(drive, 0, (char*)o->target_iso_head,
32*2048, 1);
return ret;
}
/** Initialize the emulation of multi-session on random access media.
The need for emulation is confirmed already.
@param o A freshly created isoburn object. isoburn_create_data_source() was
already called, nevertheless.
@return <=0 error , 1 = success
*/
int isoburn_start_emulation(struct isoburn *o, int flag)
{
int ret, i;
off_t data_count;
struct burn_drive *drive;
struct ecma119_pri_vol_desc *pvm;
assert(o);
drive= o->drive;
/* we can assume 0 as start block for image */
/* TODO what about ms? where we validate valid iso image in ms disc? */
ret = burn_read_data(drive, (off_t) 0, (char*)o->target_iso_head,
sizeof(o->target_iso_head), &data_count, 1);
/* an error means an empty disc */
if (ret <= 0) {
o->fabricated_disc_status= BURN_DISC_BLANK;
return 1;
}
/* check first 64K. If 0's, the disc is treated as a blank disc, and thus
overwritten without extra check. */
i = sizeof(o->target_iso_head);
while (i && !o->target_iso_head[i-1])
--i;
if (!i) {
o->fabricated_disc_status= BURN_DISC_BLANK;
return 1;
}
pvm = (struct ecma119_pri_vol_desc *)(o->target_iso_head + 16 * 2048);
if (!strncmp((char*)pvm->std_identifier, "CD001", 5)) {
off_t size;
/* sanity check */
if (pvm->vol_desc_type[0] != 1 || pvm->vol_desc_version[0] != 1
|| pvm->file_structure_version[0] != 1 ) {
/* TODO for now I treat this as a full disc */
o->fabricated_disc_status= BURN_DISC_FULL;
return 1;
}
/* ok, PVM found, set size */
size = (off_t) iso_read_lsb(pvm->vol_space_size, 4);
size *= (off_t) 2048; /* block size in bytes */
isoburn_set_start_byte(o, size, 0);
o->fabricated_disc_status= BURN_DISC_APPENDABLE;
} else if (!strncmp((char*)pvm->std_identifier, "CDXX1", 5)) {
/* empty image */
isoburn_set_start_byte(o, (off_t) 0, 0);
o->fabricated_disc_status= BURN_DISC_BLANK;
} else {
/* treat any disc in an unknown format as full */
o->fabricated_disc_status= BURN_DISC_FULL;
}
return 1;
}
/** Alters and writes the first 64 kB of a "media" to invalidate
an ISO image. (It shall stay restorable by skilled humans, though).
The result shall especially keep libisoburn from accepting the media
image as ISO filesystem.
@param o A fully activated isoburn object. isoburn_start_emulation()
was already called.
@return <=0 error , 1 = success
*/
int isoburn_invalidate_iso(struct isoburn *o, int flag)
{
/*
* replace CD001 with CDXX1 in PVM.
* I think this is enought for invalidating an iso image
*/
strncpy((char*)o->target_iso_head + 16 * 2048 + 1, "CDXX1", 5);
return isoburn_activate_session(o->drive);
}

@ -0,0 +1,379 @@
/*
API definition of libisoburn.
Copyright 2007 Vreixo Formoso Lopes <metalpain2002@yahoo.es>
and Thomas Schmitt <scdbackup@gmx.net>
*/
/**
libisoburn is a frontend for libraries libburn and libisofs which enables
creation and expansion of ISO-9660 filesystems on all CD/DVD media supported
by libburn. This includes media like DVD+RW, which do not support multi-session
management on media level and even plain disk files or block devices.
The price for that is thorough specialization on data files in ISO-9660
filesystem images. So libisoburn is not suitable for audio (CD-DA) or any
other CD layout which does not entirely consist of ISO-9660 sessions.
The priciple of this frontend is that you may use any call of libisofs or
libburn unless it has a isoburn_*() wrapper listed in the following function
documentation.
E.g. call isoburn_initialize() rather than iso_init(); burn_initialize()
and call isoburn_drive_scan_and_grab() rather than burn_drive_scan_and_grab().
But you may call burn_disc_get_profile() directly if you want to display
the media type.
>>>
>>> Take into respect Vreixo's (mandatory ?) shortcuts which are to come
>>>
The usage model is like with libburn: the target is a "media" in a "drive".
The wrappers will transparently provide the necessary emulations which
are appropriate for particular target "drives".
*/
/* API functions */
/** Initialize libisoburn, libisofs and libburn.
Wrapper for : iso_init() and burn_initialize()
@return 1 indicates success, 0 is failure
*/
int isoburn_initialize(void);
/** Aquire a target drive by its filesystem path resp. libburn persistent
address.
Wrapper for: burn_drive_scan_and_grab()
*/
int isoburn_drive_scan_and_grab(struct burn_drive_info *drive_infos[],
char* adr, int load);
/** Aquire a drive from the burn_drive_info[] array which was obtained by
a previous call of burn_drive_scan().
Wrapper for: burn_drive_grab()
*/
int isoburn_drive_grab(struct burn_drive *drive, int load);
/** Inquire the media status. Expect the whole spectrum of libburn BURN_DISC_*
with multi-session media. Emulated states with random access media are
BURN_DISC_BLANK and BURN_DISC_APPENDABLE.
Wrapper for: burn_disc_get_status()
*/
enum burn_disc_status isoburn_disc_get_status(struct burn_drive *drive);
/** Tells whether the media can be treated by isoburn_disc_erase().
Wrapper for: burn_disc_erasable()
*/
int isoburn_disc_erasable(struct burn_drive *d);
/** Mark the media as blank. With multi-session media this will call
burn_disc_erase(). With random access media, an eventual ISO-9660
filesystem will get invalidated by altering its start blocks on media.
In case of success, the media is in status BURN_DISC_BLANK afterwards.
Wrapper for: burn_disc_erase()
*/
void isoburn_disc_erase(struct burn_drive *drive, int fast);
/**
* Options for image reading.
*/
struct isoburn_read_opts {
unsigned int norock:1; /*< Do not read Rock Ridge extensions */
unsigned int nojoliet:1; /*< Do not read Joliet extensions */
unsigned int preferjoliet:1;
/*< When both Joliet and RR extensions are present, the RR
* tree is used. If you prefer using Joliet, set this to 1. */
uid_t uid; /**< Default uid when no RR */
gid_t gid; /**< Default uid when no RR */
mode_t mode; /**< Default mode when no RR (only permissions) */
/**
* Input charset for RR file names. NULL to use default locale charset.
*/
char *input_charset;
/* modified by the function isoburn_read_image */
unsigned int hasRR:1; /*< It will be set to 1 if RR extensions are present,
to 0 if not. */
unsigned int hasJoliet:1; /*< It will be set to 1 if Joliet extensions are