Initial content of libisoburn

This commit is contained in:
Thomas Schmitt 2007-09-01 18:20:53 +00:00
parent 51bd32d91d
commit 244f89e275
5 changed files with 898 additions and 0 deletions

328
libisoburn/burn_wrap.c Normal file
View File

@ -0,0 +1,328 @@
/*
cc -g -c burn_wrap.c
*/
/* 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>
#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)
{
int ret;
if(!iso_init())
return(0);
if(!burn_initialize())
return(0);
isoburn_destroy_all(&isoburn_list_start, 0); /* isoburn_list_start= NULL */
reurn(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;
if(caps->start_adr) { /* set emulation to overwriteable */
ret= isoburn_new(o, 0);
if(ret<=0)
goto ex;
(*o)->emulation_mode= 1;
(*o)->drive= d;
ret= isoburn_start_emulation(*o, 0);
if(ret<=0)
goto ex;
}
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;
struct stat stbuf;
char libburn_drive_adr[BURN_DRIVE_ADR_LEN];
struct isoburn *o= NULL;
ret= burn_drive_convert_fs_adr(adr, libburn_drive_adr);
if(ret<0)
return(ret);
if(ret==0) {
if(stat(adr,&stbuf)!=-1) {
if(S_ISREG(stbuf.st_mode) || S_ISBLK(stbuf.st_mode)) {
return(0);
/* >>> would be acceptable in future */;
/* >>> create null-drive */;
/* >>> set emulation to standard i/o */;
} else {
/* >>> unsuitable file type */;
return(0);
}
} else {
/* >>> file not found */;
return(0);
}
} else {
ret= burn_drive_scan_and_grab(drive_infos, adr, load);
if(ret<=0)
goto ex;
ret= isoburn_examine_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_examine_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.
*/
static 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(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);
}
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) {
/* >>> influence wrote_well reply or have wrote_well wrapper ? */
return;
}
if(o->emulation_mode>0) {
ret= isoburn_invalidate_iso(o, 0);
/* >>> influence wrote_well reply or have wrote_well wrapper ? */
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)
return(burn_disc_get_msc1(d, start_lba));
*start_lba= 0;
return(1);
}
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)
return(burn_disc_track_lba_nwa(d, opts, trackno, lba, nwa));
*lba= 0;
*nwa= o->nwa;
return(1);
}
int isoburn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
{
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)
return(0);
if(o->emulation_mode==2) {
return(0);
/* >>> implement an asynchronous standard i/o writer */;
}
burn_disc_write(opts, disc);
}
void isoburn_drive_release(struct burn_drive *drive, int eject)
{
int ret, no_drive_release= 0;
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);
}
void isoburn_write_opts_set_start_byte(struct burn_write_opts *opts,
off_t value)
{
int ret;
struct isoburn *o;
struct burn_drive *drive;
struct burn_multi_caps *caps= NULL;
drive= burn_write_opts_get_drive(opts);
ret= isoburn_find_emulator(&o, drive, 0);
if(ret<=0)
goto ex;
ret= burn_disc_get_multi_caps(drive, BURN_WRITE_NONE, &caps, 0);
if(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;
burn_write_opts_set_start_byte(opts, value);
ex:
if(caps!=NULL)
burn_disc_free_multi_caps(&caps);
}

231
libisoburn/isoburn.c Normal file
View File

@ -0,0 +1,231 @@
/*
cc -g -c isoburn.c
*/
/*
Class core of libisoburn.
Copyright 2007 Vreixo Formoso Lopez <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 "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;
int isoburn_new_rwopts(struct isoburn *o);
*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->target_ropts= NULL;
o->new_wopts= NULL;
for(i=0;i<65536;i++)
o->target_iso_head[i]= 0;
o->target_volset= NULL;
o->prev= NULL;
o->next= NULL;
if(isoburn_new_rwopts(o)<=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;
int isoburn_free_rwopts(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->drive!=NULL)
burn_drive_release(o->drive, 0);
isoburn_free_rwopts(o);
if(o->target_volset!=NULL)
iso_volset_free(o->target_volset);
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_emulation_mode(struct isoburn *o, int *pt, int flag)
{
*pt= o->emulation_mode;
return(1);
}
int isoburn_get_target_volset(struct isoburn *o, struct volset **pt, int flag)
{
*pt= o->target_volset;
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->prev!=NULL;o= o->prev)
if(o->drive==d) {
*pt= o;
return(1);
}
return(0);
}

91
libisoburn/isoburn.h Normal file
View File

@ -0,0 +1,91 @@
#ifndef Isoburn_includeD
#define Isoburn_includeD
/* <<< as long as no inclusion of libisofs.h */
struct volset;
/* 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 */
/* 2= standard i/o file */
int emulation_mode;
/* Although rarely used, libburn can operate on several */
/* drives simultaneously. */
/* >>> I propose to design isoburn as chain link of a list with its
/* >>> start stored globally. */
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;
/* --- Vreixo's part --- */
/* The options for reading the old image. */
/* target_ropts.size will contain the number of blocks of the image. */
struct ecma119_read_opts *target_ropts;
/* Buffered ISO head from media (should that become part of ecma119_read_opts ?) */
uint8_t target_iso_head[65536];
/* The filesystem structure of the old image from media. */
struct volset *target_volset;
/* The output options of the current run of libisofs. */
/* Element .overwrite eventually points to a buffered new head */
/* with size fields describing the new size alone, not the */
/* new combined size counted from block 0. */
/* (This head is to be merged with above target_iso_head.) */
struct ecma119_source_opts *new_wopts;
};
/* 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, struct volset **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 */
int isoburn_start_emulation(struct isoburn *o, int flag);
int isoburn_new_rwopts(struct isoburn *o);
int isoburn_free_rwopts(struct isoburn *o);
int isoburn_invalidate_iso(struct isoburn *o, int flag);
#endif /* Isoburn_includeD */

91
libisoburn/isofs_wrap.c Normal file
View File

@ -0,0 +1,91 @@
/*
cc -g -c isofs_wrap.c
*/
/*
libisofs related functions of libisoburn.
Copyright 2007 Vreixo Formoso Lopez <metalpain2002@yahoo.es>
*/
/* Vreixo:
This is now all yours. My text here is only a snapshot
of what i think we discussed in the last days.
If you change the prototypes of the functions listed
in this initial stub, then you have to change isoburn.h
and eventually libisoburn.h. And you have to tell me so
i can adjust burn_wrap.c .
*/
/* API function. See libisoburn.h
*/
int isoburn_update_iso_descriptors(struct burn_drive *drive)
{
/* >>> code <<< */
}
/** Allocate and initialize memory for libisofs related objects in
struct isoburn.
@param o A freshly created isoburn object with NULL pointers
@return <=0 error , 1 = success
*/
int isoburn_new_rwopts(struct isoburn *o)
{
/* >>> code <<< */
}
/** Dispose memory objects created by isoburn_new_rwopts(). This function
expect that the pointers in struct isoburn might still be NULL, i.e.
that isoburn_new_rwopts() was not called before.
@return <=0 error , 1 = success
*/
int isoburn_free_rwopts(struct isoburn *o)
{
/* >>> code <<< */
}
/** 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_new_rwopts() was
already called, nevertheless.
@return <=0 error , 1 = success
*/
int isoburn_start_emulation(struct isoburn *o, int flag)
{
/* >>> code <<< */
}
/** Reads, 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 libisofs 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)
{
/* >>> code <<< */
}

157
libisoburn/libisoburn.h Normal file
View File

@ -0,0 +1,157 @@
/*
API definition of libisoburn.
Copyright 2007 Vreixo Formoso Lopez <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
>>> to come: and even plain disk files or other random access file types.
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
idocumentation.
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.
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".
>>> Technical remark:
>>> For full support of plain files, libburn needs to get a null-drive
>>> which swallows all libburn calls which are not wrapped in isoburn calls.
>>> I had a count: ~ 50 API calls with struct burn_drive or
>>> struct burn_write_opts to curb :))
*/
/* 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);
/** 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);
/** Obtain the start block number of the most recent session on media. In
case of random access media this will always be 0. Succesfull return is
not a guarantee that there is a ISO-9660 image at all. The call will fail,
nevertheless,if isoburn_disc_get_status() returns not BURN_DISC_APPENDABLE.
Wrapper for: burn_disc_get_msc1()
*/
int isoburn_disc_get_msc1(struct burn_drive *d, int *start_lba);
/** Use this with trackno==0 to obtain the predicted start block number of the
new session. The interesting number is returned in parameter nwa.
Wrapper for: burn_disc_track_lba_nwa()
*/
int isoburn_disc_track_lba_nwa(struct burn_drive *d, struct burn_write_opts *o,
int trackno, int *lba, int *nwa);
/** Start writing of the new session.
This call is asynchrounous. I.e. it returns quite soon and the progress has
to be watched by a loop with call burn_drive_get_status() until
BURN_DRIVE_IDLE is returned.
Wrapper for: burn_disc_write()
*/
int isoburn_disc_write(struct burn_write_opts *o, struct burn_disc *disc);
/** Call this after isoburn_disc_write has finished and burn_drive_wrote_well()
indicates success. It will eventually complete the emulation of
multi-session functionality, if needed at all. Let libisoburn decide.
Not a wrapper, but peculiar to libburn.
*/
int isoburn_update_iso_descriptors(struct burn_drive *drive);
/** Release an aquired drive.
Wrapper for: burn_drive_release()
*/
void isoburn_drive_release(struct burn_drive *drive, int eject);
/** Shutdown all three libraries.
Wrapper for : iso_finish() and burn_finish().
*/
void isoburn_finish(void);
/*
The following two calls are for expert applications only.
An application should have a special reason to use them.
*/
/** Inquire wether the media needs emulation or would be suitable for
generic multi-session via libburn.
@return 0 is generic multi-session
1 is emulated multi-session
-1 is not suitable for isoburn
*/
int isoburn_needs_emulation(struct burn_drive *drive);
/** Caution: Use this with great care. It is not needed normally.
This call can set the nwa block number to an arbitrary value. If ever, do
this before preparing the session by libisofs. The drive must be grabbed,
though. This overrides the automated address computation. Call
isoburn_disc_track_lba_nwa() afterwards to learn the effective new
address which might be somewhat higher than set by parameter value.
Wrapper for: burn_write_opts_set_start_byte (if ever)
*/
void isoburn_write_opts_set_start_byte(struct burn_write_opts *opts,
off_t value);