Branches 0.1.6 of libisoburn

This commit is contained in:
Mario Danic
2008-05-17 07:41:46 +00:00
parent ac41f4cfd9
commit 9ae2961be7
39 changed files with 32207 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,372 @@
/*
data source for libisoburn.
Copyright 2007 Vreixo Formoso Lopes <metalpain2002@yahoo.es>
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#ifndef Xorriso_standalonE
#include <libburn/libburn.h>
#include <libisofs/libisofs.h>
#else /* ! Xorriso_standalonE */
#include "../libisofs/libisofs.h"
#include "../libburn/libburn.h"
#endif /* Xorriso_standalonE */
#include "isoburn.h"
/* Powers of 2 only ! Less than 16 makes not much sense. */
#define Libisoburn_tile_blockS 32
/* Undef to get to older single tile version
*/
#define Libisoburn_cache_tileS 32
/* Debugging only: This reports cache loads on stderr.
#define Libisoburn_read_cache_reporT 1
*/
/* Cached reading of image tree data */
#ifdef Libisoburn_cache_tileS
/* Multi tile: 32 * 64 kB */
struct isoburn_cache_tile {
char cache_data[Libisoburn_tile_blockS * 2048];
uint32_t cache_lba;
uint32_t last_error_lba;
uint32_t last_aligned_error_lba;
int cache_hits;
int age;
};
struct isoburn_cached_drive {
struct burn_drive *drive;
struct isoburn_cache_tile tiles[Libisoburn_cache_tileS];
int current_age;
};
#define Libisoburn_max_agE 2000000000
static int ds_inc_age(struct isoburn_cached_drive *icd, int idx, int flag);
int ds_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer)
{
int ret, i, oldest, oldest_age;
struct burn_drive *d;
off_t count;
uint32_t aligned_lba;
char msg[80];
struct isoburn_cache_tile *tiles;
struct isoburn_cached_drive *icd;
if(src == NULL || buffer == NULL)
/* It is not required by the specs of libisofs but implicitely assumed
by its current implementation that a data source read result <0 is
a valid libisofs error code.
*/
return ISO_NULL_POINTER;
icd = (struct isoburn_cached_drive *) src->data;
d = (struct burn_drive*) icd->drive;
tiles = (struct isoburn_cache_tile *) icd->tiles;
aligned_lba= lba & ~(Libisoburn_tile_blockS - 1);
for(i=0; i<Libisoburn_cache_tileS; i++) {
if(aligned_lba == tiles[i].cache_lba && tiles[i].cache_lba != 0xffffffff) {
(tiles[i].cache_hits)++;
memcpy(buffer, tiles[i].cache_data + (lba - aligned_lba) * 2048, 2048);
count= 2048;
ds_inc_age(icd, i, 0);
return 1;
}
}
/* find oldest tile */
oldest_age= Libisoburn_max_agE;
oldest= 0;
for(i= 0; i<Libisoburn_cache_tileS; i++) {
if(tiles[i].cache_lba == 0xffffffff) {
oldest= i;
break;
}
if(tiles[i].age<oldest_age) {
oldest_age= tiles[i].age;
oldest= i;
}
}
tiles[oldest].cache_lba= 0xffffffff; /* invalidate cache */
if(tiles[oldest].last_aligned_error_lba == aligned_lba) {
ret = 0;
} else {
ret = burn_read_data(d, (off_t) aligned_lba * (off_t) 2048,
(char *) tiles[oldest].cache_data,
Libisoburn_tile_blockS * 2048, &count, 2);
}
if (ret <= 0 ) {
tiles[oldest].last_aligned_error_lba = aligned_lba;
/* Read-ahead failure ? Try to read 2048 directly. */
if(tiles[oldest].last_error_lba == lba)
ret = 0;
else
ret = burn_read_data(d, (off_t) lba * (off_t) 2048, (char *) buffer,
2048, &count, 0);
if (ret > 0)
return 1;
tiles[oldest].last_error_lba = lba;
/* It is not required by the specs of libisofs but implicitely assumed
...
But it is not possible to ignore FAILURE.
libisofs insists in original error codes, i.e. libisoburn cannot
change severity FAILURE associated with ISO_FILE_READ_ERROR.
So ISO_FILE_READ_ERROR is not an option and libisoburn has to
misuse ISO_FILE_CANT_WRITE, which is actually for image generation
and not for image reading.
This is quite wrong, although the error message text is unclear
enough to make it appear plausible.
*/
ret= ISO_FILE_CANT_WRITE;
if(ret >= 0)
ret = -1;
sprintf(msg, "ds_read_block(%lu) returns %d", (unsigned long) lba, ret);
burn_msgs_submit(0x00060000, msg, 0, "DEBUG", NULL);
return ret;
}
#ifdef Libisoburn_read_cache_reporT
fprintf(stderr, "Tile %2.2d : After %3d hits, new load from %8x , count= %d\n",
oldest, tiles[oldest].cache_hits, aligned_lba, (int) count);
#endif
tiles[oldest].cache_lba= aligned_lba;
tiles[oldest].cache_hits= 1;
ds_inc_age(icd, oldest, 0);
memcpy(buffer, tiles[oldest].cache_data + (lba - aligned_lba) * 2048, 2048);
count= 2048;
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 */;
if(src->data != NULL)
free(src->data);
src->data= NULL;
}
IsoDataSource *isoburn_data_source_new(struct burn_drive *d)
{
IsoDataSource *ret;
struct isoburn_cached_drive *icd= NULL;
int i;
if (d==NULL)
return NULL;
ret = malloc(sizeof(IsoDataSource));
icd = calloc(1,sizeof(struct isoburn_cached_drive));
if (ret == NULL || icd == NULL)
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 = icd;
icd->drive = d;
icd->current_age= 0;
for(i= 0; i<Libisoburn_cache_tileS; i++) {
icd->tiles[i].cache_lba = 0xffffffff;
icd->tiles[i].cache_hits = 0;
icd->tiles[i].last_error_lba = 0xffffffff;
icd->tiles[i].last_aligned_error_lba = 0xffffffff;
icd->tiles[i].age= 0;
}
return ret;
}
static int ds_inc_age(struct isoburn_cached_drive *icd, int idx, int flag)
{
int i;
(icd->current_age)++;
if(icd->current_age>=Libisoburn_max_agE) { /* reset all ages (allow waste) */
for(i= 0; i<Libisoburn_cache_tileS; i++)
(icd->tiles)[i].age= 0;
icd->current_age= 1;
}
(icd->tiles)[idx].age= icd->current_age;
return(1);
}
#else /* Libisoburn_cache_tileS */
/* Single tile 128 kB */
struct isoburn_cached_drive {
struct burn_drive *drive;
char cache_data[Libisoburn_tile_blockS * 2048];
uint32_t cache_lba;
uint32_t last_error_lba;
uint32_t last_aligned_error_lba;
int cache_hits;
};
/* Debugging only: This reports cache loads on stderr.
#define Libisoburn_read_cache_reporT 1
*/
int
ds_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer)
{
int ret;
struct burn_drive *d;
off_t count;
uint32_t aligned_lba;
char msg[80];
struct isoburn_cached_drive *icd;
if(src == NULL || buffer == NULL)
return -1;
icd = (struct isoburn_cached_drive *) src->data;
d = (struct burn_drive*) icd->drive;
aligned_lba= lba & ~(Libisoburn_tile_blockS - 1);
if(aligned_lba == icd->cache_lba && icd->cache_lba != 0xffffffff) {
(icd->cache_hits)++;
memcpy(buffer, icd->cache_data + (lba - aligned_lba) * 2048, 2048);
count= 2048;
return 1;
}
icd->cache_lba= 0xffffffff; /* invalidate cache */
if(icd->last_aligned_error_lba == aligned_lba) {
ret = 0;
} else {
ret = burn_read_data(d, (off_t) aligned_lba * (off_t) 2048,
(char *) icd->cache_data,
Libisoburn_tile_blockS * 2048, &count, 0);
}
if (ret <= 0 ) {
icd->last_aligned_error_lba = aligned_lba;
/* Read-ahead failure ? Try to read 2048 directly. */
if(icd->last_error_lba == lba)
ret = 0;
else
ret = burn_read_data(d, (off_t) lba * (off_t) 2048, (char *) buffer,
2048, &count, 0);
if (ret > 0)
return 1;
icd->last_error_lba = lba;
sprintf(msg, "ds_read_block(%lu) returns -1", (unsigned long) lba);
burn_msgs_submit(0x00060000, msg, 0, "DEBUG", NULL);
return -1;
}
#ifdef Libisoburn_read_cache_reporT
fprintf(stderr, "After %3d hits, new load from %8x , count= %d\n",
icd->cache_hits, aligned_lba, (int) count);
#endif
icd->cache_lba= aligned_lba;
icd->cache_hits= 1;
memcpy(buffer, icd->cache_data + (lba - aligned_lba) * 2048, 2048);
count= 2048;
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 */;
if(src->data != NULL)
free(src->data);
src->data= NULL;
}
IsoDataSource *
isoburn_data_source_new(struct burn_drive *d)
{
IsoDataSource *ret;
struct isoburn_cached_drive *icd= NULL;
if (d==NULL)
return NULL;
ret = malloc(sizeof(IsoDataSource));
icd = calloc(1,sizeof(struct isoburn_cached_drive));
if (ret == NULL || icd == NULL)
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 = icd;
icd->drive = d;
icd->cache_lba = 0xffffffff;
icd->cache_hits = 0;
icd->last_error_lba = 0xffffffff;
icd->last_aligned_error_lba = 0xffffffff;
return ret;
}
#endif /* ! Libisoburn_cache_tileS */

View File

@ -0,0 +1,866 @@
/*
cc -g -c isoburn.c
*/
/*
Class core of libisoburn.
Copyright 2007 - 2008 Vreixo Formoso Lopes <metalpain2002@yahoo.es>
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>
#ifndef Xorriso_standalonE
#include <libburn/libburn.h>
#include <libisofs/libisofs.h>
#else /* ! Xorriso_standalonE */
#include "../libisofs/libisofs.h"
#include "../libburn/libburn.h"
#endif /* Xorriso_standalonE */
#include "libisoburn.h"
#include "isoburn.h"
/* No more: version numbers out of configure.ac
major.minor.micro now comes from libisoburn.h
#include "../version.h"
*/
/* ----------------------- isoburn_toc_entry ---------------------- */
int isoburn_toc_entry_new(struct isoburn_toc_entry **objpt,
struct isoburn_toc_entry *boss, int flag)
{
struct isoburn_toc_entry *o, *s;
*objpt= o= (struct isoburn_toc_entry *)
malloc(sizeof(struct isoburn_toc_entry));
if(o==NULL) {
burn_msgs_submit(0x00060000,
"Cannot allocate memory for isoburn toc entry",
0, "FATAL", NULL);
return(-1);
}
o->session= 0;
o->track_no= 0;
o->start_lba= -1;
o->track_blocks= 0;
o->next= NULL;
if(boss!=NULL) {
for(s= boss; s->next!=NULL; s= s->next);
s->next= o;
}
return(1);
}
/* @param flag bit0= delete all subordinates too
*/
int isoburn_toc_entry_destroy(struct isoburn_toc_entry **o, int flag)
{
if(*o==NULL)
return(0);
if(flag&1)
isoburn_toc_entry_destroy(&((*o)->next), flag);
free((char *) (*o));
*o= NULL;
return(1);
}
/* --------------------- end isoburn_toc_entry -------------------- */
/* -------------------------- 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) {
burn_msgs_submit(0x00060000,
"Cannot allocate memory for isoburn control object",
0, "FATAL", NULL);
return(-1);
}
o->drive= NULL;
o->emulation_mode= 0;
o->fabricated_msc1= -1;
o->zero_nwa= Libisoburn_overwriteable_starT;
o->min_start_byte= o->zero_nwa * 2048;
o->nwa= o->zero_nwa;
o->truncate= 0;
o->iso_source= NULL;
o->fabricated_disc_status= BURN_DISC_UNREADY;
o->toc= NULL;
o->wrote_well= -1;
for(i=0;i<Libisoburn_target_head_sizE;i++)
o->target_iso_head[i]= 0;
o->image= NULL;
o->read_pacifier= NULL;
o->read_pacifier_handle= NULL;
o->prev= NULL;
o->next= NULL;
ret= iso_image_new("ISOIMAGE", &o->image);
if(ret<0) {
isoburn_report_iso_error(ret, "Cannot create image", 0, "FATAL", 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->toc!=NULL)
isoburn_toc_entry_destroy(&(o->toc), 1); /* all */
if(o->iso_source!=NULL)
burn_source_free(o->iso_source);
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_imgen_opts *opts, int new_img)
{
struct burn_source *wsrc;
struct burn_session *session;
struct burn_track *track;
struct isoburn *o;
IsoWriteOpts *wopts= NULL;
enum burn_disc_status state;
int ret, fifo_chunks;
ret= isoburn_find_emulator(&o, d, 0);
if(ret<0 || o==NULL)
{ret= -1; goto ex;}
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 */
burn_msgs_submit(0x00060000, "Unsuitable media state", 0, "FAILURE", NULL);
{ret= -2; goto ex;}
}
fifo_chunks= 32;
if(opts->fifo_size >= 64*1024 && opts->fifo_size <= 1024.0 * 1024.0 * 1024.0){
fifo_chunks= opts->fifo_size/2048;
if(fifo_chunks*2048 < opts->fifo_size)
fifo_chunks++;
}
ret = iso_write_opts_new(&wopts, 0);
if (ret < 0) {
isoburn_report_iso_error(ret, "Cannot create iso_write_opts", 0, "FATAL",0);
goto ex;
}
iso_write_opts_set_iso_level(wopts, opts->level);
iso_write_opts_set_rockridge(wopts, opts->rockridge);
iso_write_opts_set_joliet(wopts, opts->joliet);
iso_write_opts_set_iso1999(wopts, opts->iso1999);
iso_write_opts_set_omit_version_numbers(wopts, opts->omit_version_numbers);
iso_write_opts_set_allow_deep_paths(wopts, opts->allow_deep_paths);
iso_write_opts_set_allow_longer_paths(wopts, opts->allow_longer_paths);
iso_write_opts_set_max_37_char_filenames(wopts, opts->max_37_char_filenames);
iso_write_opts_set_no_force_dots(wopts, opts->no_force_dots);
iso_write_opts_set_allow_lowercase(wopts, opts->allow_lowercase);
iso_write_opts_set_allow_full_ascii(wopts, opts->allow_full_ascii);
iso_write_opts_set_relaxed_vol_atts(wopts, 1);
iso_write_opts_set_joliet_longer_paths(wopts, opts->joliet_longer_paths);
iso_write_opts_set_sort_files(wopts, opts->sort_files);
iso_write_opts_set_replace_mode(wopts, opts->replace_dir_mode,
opts->replace_file_mode, opts->replace_uid, opts->replace_gid);
iso_write_opts_set_default_dir_mode(wopts, opts->dir_mode);
iso_write_opts_set_default_file_mode(wopts, opts->file_mode);
iso_write_opts_set_default_uid(wopts, opts->uid);
iso_write_opts_set_default_gid(wopts, opts->gid);
iso_write_opts_set_output_charset(wopts, opts->output_charset);
iso_write_opts_set_fifo_size(wopts, fifo_chunks);
if (new_img) {
iso_write_opts_set_ms_block(wopts, 0);
opts->effective_lba= 0;
iso_write_opts_set_appendable(wopts, 0);
iso_write_opts_set_overwrite_buf(wopts, NULL);
} else {
int lba, nwa;
ret = isoburn_disc_track_lba_nwa(d, NULL, 0, &lba, &nwa);
if (ret != 1) {
burn_msgs_submit(0x00060000, "Cannot determine next writeable address", 0,
"FAILURE", NULL);
{ret= -3; goto ex;}
}
if (nwa == 0 && state == BURN_DISC_APPENDABLE) {
/* invalid nwa */
burn_msgs_submit(0x00060000,
"Encountered 0 as next writeable address of appendable",
0, "FAILURE", NULL);
{ret= -4; goto ex;}
}
iso_write_opts_set_ms_block(wopts, nwa);
opts->effective_lba= nwa;
iso_write_opts_set_appendable(wopts, 1);
iso_write_opts_set_overwrite_buf(wopts, o->target_iso_head);
}
ret = iso_image_create_burn_source(o->image, wopts, &wsrc);
if (ret < 0) {
isoburn_report_iso_error(ret, "Cannot create burn source", 0, "FAILURE", 0);
{ret= -1; goto ex;}
}
/* TODO check return values for failure. propertly clean-up on error */
o->iso_source= wsrc;
*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->iso_source);
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 */
ret= 1;
ex:
if(wopts!=NULL)
{iso_write_opts_free(wopts); wopts= NULL;}
return ret;
}
int isoburn_prepare_disc(struct burn_drive *d, struct burn_disc **disc,
struct isoburn_imgen_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_imgen_opts *opts,
struct burn_drive *out_drive)
{
int ret;
struct isoburn *in_o, *out_o;
ret= isoburn_prepare_disc_aux(d, disc, opts, 1);
if (ret<=0)
return ret;
/* Hand over source reference for optional fifo status inquiry */
if(out_drive==NULL)
return 1;
ret= isoburn_find_emulator(&out_o, out_drive, 0);
if(ret<0 || out_o==NULL)
return 1;
ret= isoburn_find_emulator(&in_o, d, 0);
if(ret<0 || in_o==NULL)
return 1; /* then without fifo status inquiry */
if(out_o->iso_source!=NULL)
burn_source_free(out_o->iso_source);
out_o->iso_source= in_o->iso_source;
in_o->iso_source= NULL;
return 1;
}
/* API @since 0.1.0
@param flag bit0= this is a regular end, not an abort
give up source reference
*/
int isoburn_cancel_prepared_write(struct burn_drive *d,
struct burn_drive *output_drive, int flag)
{
int ret;
struct isoburn *o= NULL;
if(output_drive!=NULL) {
ret= isoburn_find_emulator(&o, output_drive, 0);
if(ret<0 || o==NULL)
o= NULL;
else if(o->iso_source==NULL)
o= NULL;
}
if(o==NULL) {
ret= isoburn_find_emulator(&o, d, 0);
if(ret<0)
return(-1);
if(o==NULL)
return(0);
if(o->iso_source==NULL)
return(0);
}
if(o->iso_source->read!=NULL)
return(0);
if(o->iso_source->version<1)
return(0);
o->iso_source->cancel(o->iso_source);
burn_source_free(o->iso_source);
o->iso_source= NULL;
return(1);
}
/* API @since 0.1.0 */
int isoburn_sync_after_write(struct burn_drive *d,
struct burn_drive *output_drive, int flag)
{
return isoburn_cancel_prepared_write(d, output_drive, 1);
}
void isoburn_version(int *major, int *minor, int *micro)
{
*major= isoburn_header_version_major;
*minor= isoburn_header_version_minor;
*micro= isoburn_header_version_micro;
/* No more: values from version.h generated from version.h.in and
macro values defined in configure.ac
*major = ISOBURN_MAJOR_VERSION;
*minor = ISOBURN_MINOR_VERSION;
*micro = ISOBURN_MICRO_VERSION;
*/
}
int isoburn_is_compatible(int major, int minor, int micro, int flag)
{
int own_major, own_minor, own_micro;
isoburn_version(&own_major, &own_minor, &own_micro);
return(own_major > major ||
(own_major == major && (own_minor > minor ||
(own_minor == minor && own_micro >= micro))));
}
/* ----------------------------------------------------------------------- */
/*
Options for image reading.
*/
/* ----------------------------------------------------------------------- */
int isoburn_ropt_new(struct isoburn_read_opts **new_o, int flag)
{
struct isoburn_read_opts *o;
o= (*new_o)= calloc(1, sizeof(struct isoburn_read_opts));
if(o==NULL) {
burn_msgs_submit(0x00060000, "Cannot allocate memory for read options",
0, "FATAL", NULL);
return(-1);
}
o->norock= 0;
o->nojoliet= 0;
o->noiso1999= 1;
o->preferjoliet= 0;
o->uid= geteuid();
o->gid= getegid();
o->mode= 0444;
o->dirmode= 0555;
o->input_charset= NULL;
o->hasRR= 0;
o->hasJoliet= 0;
o->hasIso1999= 0;
o->hasElTorito= 0;
o->size= 0;
o->pretend_blank= 1;
return(1);
}
int isoburn_ropt_destroy(struct isoburn_read_opts **o, int flag)
{
if(*o==NULL)
return(0);
free(*o);
*o= NULL;
return(1);
}
int isoburn_ropt_set_extensions(struct isoburn_read_opts *o, int ext)
{
o->norock= !!(ext&1);
o->nojoliet= !!(ext&2);
o->noiso1999= !!(ext&4);
o->preferjoliet= !!(ext&8);
o->pretend_blank= !!(ext&16);
return(1);
}
int isoburn_ropt_get_extensions(struct isoburn_read_opts *o, int *ext)
{
*ext= (!!o->norock) | ((!!o->nojoliet)<<1) | ((!!o->noiso1999)<<2) |
((!!o->preferjoliet)<<3) | ((!!o->pretend_blank)<<4);
return(1);
}
int isoburn_ropt_set_default_perms(struct isoburn_read_opts *o,
uid_t uid, gid_t gid, mode_t mode)
{
mode_t dirmode;
o->uid= uid;
o->gid= gid;
o->mode= mode;
dirmode= mode;
if(dirmode & S_IRUSR)
dirmode|= S_IXUSR;
if(dirmode & S_IRGRP)
dirmode|= S_IXGRP;
if(dirmode & S_IROTH)
dirmode|= S_IXOTH;
o->dirmode= dirmode;
return(1);
}
int isoburn_ropt_get_default_perms(struct isoburn_read_opts *o,
uid_t *uid, gid_t *gid, mode_t *mode)
{
*uid= o->uid;
*gid= o->gid;
*mode= o->mode;
return(1);
}
int isoburn_ropt_set_default_dirperms(struct isoburn_read_opts *o,
mode_t mode)
{
o->dirmode= mode;
return(1);
}
int isoburn_ropt_get_default_dirperms(struct isoburn_read_opts *o,
mode_t *mode)
{
*mode= o->dirmode;
return(1);
}
int isoburn_ropt_set_input_charset(struct isoburn_read_opts *o,
char *input_charset)
{
o->input_charset= input_charset;
return(1);
}
int isoburn_igopt_get_in_charset(struct isoburn_read_opts *o,
char **input_charset)
{
*input_charset= o->input_charset;
return(1);
}
int isoburn_ropt_get_size_what(struct isoburn_read_opts *o,
uint32_t *size, int *has_what)
{
*size= o->size;
*has_what= (!!o->hasRR) | ((!!o->hasJoliet)<<1) |
((!!o->hasIso1999)<<2) | ((!!o->hasElTorito)<<3);
return(1);
}
/* ----------------------------------------------------------------------- */
/*
Options for image generation by libisofs and image transport to libburn.
*/
/* ----------------------------------------------------------------------- */
int isoburn_igopt_new(struct isoburn_imgen_opts **new_o, int flag)
{
struct isoburn_imgen_opts *o;
o= (*new_o)= calloc(1, sizeof(struct isoburn_imgen_opts));
if(o==NULL) {
burn_msgs_submit(0x00060000,
"Cannot allocate memory for image generation options",
0, "FATAL", NULL);
return(-1);
}
o->level= 2;
o->rockridge= 1;
o->joliet= 0;
o->iso1999= 0;
o->omit_version_numbers= 0;
o->allow_deep_paths= 1;
o->allow_longer_paths= 0;
o->max_37_char_filenames= 0;
o->no_force_dots= 0;
o->allow_lowercase= 0;
o->allow_full_ascii= 0;
o->joliet_longer_paths= 0;
o->sort_files= 0;
o->replace_dir_mode= 0;
o->replace_file_mode= 0;
o->replace_uid= 0;
o->replace_gid= 0;
o->dir_mode= 0555;
o->file_mode= 0444;
o->uid= 0;
o->gid= 0;
o->output_charset= 0;
o->fifo_size= 4*1024*1024;
o->effective_lba= -1;
return(1);
}
int isoburn_igopt_destroy(struct isoburn_imgen_opts **o, int flag)
{
if(*o==NULL)
return(0);
free(*o);
*o= NULL;
return(1);
}
int isoburn_igopt_set_level(struct isoburn_imgen_opts *o, int level)
{
o->level= level;
return(1);
}
int isoburn_igopt_get_level(struct isoburn_imgen_opts *o, int *level)
{
*level= o->level;
return(1);
}
int isoburn_igopt_set_extensions(struct isoburn_imgen_opts *o, int ext)
{
o->rockridge= !!(ext&1);
o->joliet= !!(ext&2);
o->iso1999= !!(ext&4);
return(1);
}
int isoburn_igopt_get_extensions(struct isoburn_imgen_opts *o, int *ext)
{
*ext= (!!o->rockridge) | ((!!o->joliet)<<1) | ((!!o->iso1999)<<2);
return(1);
}
int isoburn_igopt_set_relaxed(struct isoburn_imgen_opts *o, int relax)
{
o->omit_version_numbers= !!(relax&1);
o->allow_deep_paths= !!(relax&2);
o->allow_longer_paths= !!(relax&4);
o->max_37_char_filenames= !!(relax&8);
o->no_force_dots= !!(relax&16);
o->allow_lowercase= !!(relax&32);
o->allow_full_ascii= !!(relax&64);
o->joliet_longer_paths= !!(relax&128);
return(1);
}
int isoburn_igopt_get_relaxed(struct isoburn_imgen_opts *o, int *relax)
{
*relax= (!!o->omit_version_numbers) | ((!!o->allow_deep_paths)<<1) |
((!!o->allow_longer_paths)<<2) | ((!!o->max_37_char_filenames)<<3) |
((!!o->no_force_dots)<<4) | ((!!o->allow_lowercase)<<5) |
((!!o->allow_full_ascii)<<6) | ((!!o->joliet_longer_paths)<<7);
return(1);
}
int isoburn_igopt_set_sort_files(struct isoburn_imgen_opts *o, int value)
{
o->sort_files= !!(value&1);
return(1);
}
int isoburn_igopt_get_sort_files(struct isoburn_imgen_opts *o, int *value)
{
*value= !!o->sort_files;
return(1);
}
int isoburn_igopt_set_over_mode(struct isoburn_imgen_opts *o,
int replace_dir_mode, int replace_file_mode,
mode_t dir_mode, mode_t file_mode)
{
o->replace_dir_mode= replace_dir_mode%3;
o->replace_file_mode= replace_file_mode%3;
o->dir_mode= dir_mode;
o->file_mode= file_mode;
return(1);
}
int isoburn_igopt_get_over_mode(struct isoburn_imgen_opts *o,
int *replace_dir_mode, int *replace_file_mode,
mode_t *dir_mode, mode_t *file_mode)
{
*replace_dir_mode= o->replace_dir_mode%3;
*replace_file_mode= o->replace_file_mode%3;
*dir_mode= o->dir_mode;
*file_mode= o->file_mode;
return(1);
}
int isoburn_igopt_set_over_ugid(struct isoburn_imgen_opts *o,
int replace_uid, int replace_gid,
uid_t uid, gid_t gid)
{
o->replace_uid= replace_uid%3;
o->replace_gid= replace_gid%3;
o->uid= uid;
o->gid= gid;
return(1);
}
int isoburn_igopt_get_over_ugid(struct isoburn_imgen_opts *o,
int *replace_uid, int *replace_gid,
uid_t *uid, gid_t *gid)
{
*replace_uid= o->replace_uid%3;
*replace_gid= o->replace_gid%3;
*uid= o->uid;
*gid= o->gid;
return(1);
}
int isoburn_igopt_set_out_charset(struct isoburn_imgen_opts *o,
char *output_charset)
{
o->output_charset= output_charset;
return(1);
}
int isoburn_igopt_get_out_charset(struct isoburn_imgen_opts *o,
char **output_charset)
{
*output_charset= o->output_charset;
return(1);
}
int isoburn_igopt_set_fifo_size(struct isoburn_imgen_opts *o, int fifo_size)
{
o->fifo_size= fifo_size;
return(1);
}
int isoburn_igopt_get_fifo_size(struct isoburn_imgen_opts *o, int *fifo_size)
{
*fifo_size= o->fifo_size;
return(1);
}
int isoburn_igopt_get_effective_lba(struct isoburn_imgen_opts *o, int *lba)
{
*lba= o->effective_lba;
return(1);
}

View File

@ -0,0 +1,422 @@
/*
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>
/* For emulated TOC of overwriteable media.
Provides minimal info for faking a struct burn_toc_entry.
*/
struct isoburn_toc_entry {
int session;
int track_no; /* point */
int start_lba;
int track_blocks;
struct isoburn_toc_entry *next;
};
int isoburn_toc_entry_new(struct isoburn_toc_entry **objpt,
struct isoburn_toc_entry *boss, int flag);
/* @param flag bit0= delete all subordinates too
*/
int isoburn_toc_entry_destroy(struct isoburn_toc_entry **o, int flag);
/* Size of target_iso_head which is to be written during
isoburn_activate_session()
*/
#define Libisoburn_target_head_sizE (32*2048)
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;
/* If >= 0, this address is used as reply for isoburn_disc_get_msc1()
*/
int fabricated_msc1;
/* The nwa to be used for a first session on the present kind of overwriteable
media (usually Libisoburn_overwriteable_starT, but might be forced to 0)
*/
int zero_nwa;
/* 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;
/* Truncate to .nwa an eventual regular file serving as output drive */
int truncate;
/* Eventual freely fabricated isoburn_disc_get_status().
BURN_DISC_UNREADY means that this variable is disabled
and normally emulated status is in effect.
*/
enum burn_disc_status fabricated_disc_status;
/* Eventual emulated table of content read from the chain of ISO headers
on overwriteable media.
*/
struct isoburn_toc_entry *toc;
/* 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;
/* Buffered ISO head from media (should that become part of
ecma119_read_opts ?) */
uint8_t target_iso_head[Libisoburn_target_head_sizE];
/* Libisofs image context */
IsoImage *image;
/* The burn source which transfers data from libisofs to libburn.
It has its own fifo.
*/
struct burn_source *iso_source;
/* For iso_tree_set_report_callback() */
int (*read_pacifier)(IsoImage*, IsoFileSource*);
/* For iso_image_attach_data() */
void *read_pacifier_handle;
};
/* 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 */
/* Submit a libisofs error to the libburn messenger. An application message
reader shall recognize the error code range and attribute it to the
libisofs message channel to which one cannot submit via API.
@param iso_error_code return value <= 0 from a libisofs API call.
@param default_msg_text is to be put out if iso_error_code leads to no
error message
@param os_errno operating system errno, submit 0 if none is known
@param min_severity minimum severity, might be be increased if libisofs
error severity surpasses min_severity.
@param flag Bitfield, submit 0 for now
*/
int isoburn_report_iso_error(int iso_error_code, char default_msg_text[],
int os_errno, char min_severity[], int flag);
/* 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);
/**
* Options for image reading.
(Comments here may be outdated. API getter/setter function descriptions
may override the descriptions here. Any difference is supposed to be a
minor correction only.)
*/
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 noiso1999:1; /*< Do not read ISO 9660:1999 enhanced tree */
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) */
mode_t dirmode; /**< Default mode for directories
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
present, to 0 if not. */
/**
* It will be set to 1 if the image is an ISO 9660:1999, i.e. it has
* a version 2 Enhanced Volume Descriptor.
*/
unsigned int hasIso1999:1;
/** It will be set to 1 if El-Torito boot record is present, to 0 if not.*/
unsigned int hasElTorito:1;
uint32_t size; /**< Will be filled with the size (in 2048 byte block) of
* the image, as reported in the PVM. */
unsigned int pretend_blank:1; /* always create empty image */
};
/**
* Options for image generation by libisofs and image transport to libburn.
(Comments here may be outdated. API getter/setter function descriptions
may override the descriptions here. Any difference is supposed to be a
minor correction only.)
*/
struct isoburn_imgen_opts {
/* Options for image generation */
int level; /**< ISO level to write at. */
/** Which extensions to support. */
unsigned int rockridge :1;
unsigned int joliet :1;
unsigned int iso1999 :1;
/* relaxed constraints */
/*
* Relaxed constraints. Setting any of these to 1 break the specifications,
* but it is supposed to work on most moderns systems. Use with caution.
*/
/**
* Omit the version number (";1") at the end of the ISO-9660 identifiers.
* Version numbers are usually not used.
*/
unsigned int omit_version_numbers :1;
/**
* Allow ISO-9660 directory hierarchy to be deeper than 8 levels.
*/
unsigned int allow_deep_paths :1;
/**
* Allow path in the ISO-9660 tree to have more than 255 characters.
*/
unsigned int allow_longer_paths :1;
/**
* Allow a single file or directory hierarchy to have up to 37 characters.
* This is larger than the 31 characters allowed by ISO level 2, and the
* extra space is taken from the version number, so this also forces
* omit_version_numbers.
*/
unsigned int max_37_char_filenames :1;
/**
* ISO-9660 forces filenames to have a ".", that separates file name from
* extension. libisofs adds it if original filename doesn't has one. Set
* this to 1 to prevent this behavior
*/
unsigned int no_force_dots :1;
/**
* Allow lowercase characters in ISO-9660 filenames. By default, only
* uppercase characters, numbers and a few other characters are allowed.
*/
unsigned int allow_lowercase :1;
/**
* Allow all ASCII characters to be appear on an ISO-9660 filename. Note
* that "/" and "\0" characters are never allowed, even in RR names.
*/
unsigned int allow_full_ascii :1;
/**
* Allow paths in the Joliet tree to have more than 240 characters.
*/
unsigned int joliet_longer_paths :1;
unsigned int sort_files:1;
/**< If files should be sorted based on their weight. */
/**
* The following options set the default values for files and directory
* permissions, gid and uid. All these take one of three values: 0, 1 or 2.
* If 0, the corresponding attribute will be kept as set in the IsoNode.
* Unless you have changed it, it corresponds to the value on disc, so it
* is suitable for backup purposes. If set to 1, the corresponding attrib.
* will be changed by a default suitable value. Finally, if you set it to
* 2, the attrib. will be changed with the value specified in the options
* below. Note that for mode attributes, only the permissions are set, the
* file type remains unchanged.
*/
unsigned int replace_dir_mode :2;
unsigned int replace_file_mode :2;
unsigned int replace_uid :2;
unsigned int replace_gid :2;
mode_t dir_mode; /** Mode to use on dirs when replace_dir_mode == 2. */
mode_t file_mode; /** Mode to use on files when replace_file_mode == 2. */
uid_t uid; /** uid to use when replace_uid == 2. */
gid_t gid; /** gid to use when replace_gid == 2. */
char *output_charset; /**< NULL to use default charset */
/* Options for image transport */
/** The number of bytes to be used for the fifo which decouples libisofs
and libburn for better throughput and for reducing the risk of
interrupting signals hitting the libburn thread which operates the
MMC drive.
The size will be rounded up to the next full 2048.
Minimum is 64kiB, maximum is 1 GiB (but that is too much anyway).
*/
int fifo_size;
/** Output value: Block address of session start as evaluatedfrom media
and other options by libisoburn and libburn.
If <0 : Invalid
If >=0: Valid block number. Block size is always 2 KiB.
*/
int effective_lba;
};
/* Alignment for session starts on overwriteable media.
(Increased from 16 to 32 blocks for aligning to BD-RE clusters.)
*/
#define Libisoburn_nwa_alignemenT 32
/* Alignment for outer session scanning with -ROM drives.
(E.g. my DVD-ROM drive shows any DVD type as 0x10 "DVD-ROM" with
more or less false capacity and TOC.)
*/
#define Libisoburn_toc_scan_alignemenT 16
/* Maximum gap to be bridged during a outer TOC scan. Gaps appear between the
end of a session and the start of the next session.
*/
#define Libisoburn_toc_scan_max_gaP 8192
/* Creating a chain of image headers which form a TOC:
The header of the first session is written after the LBA 0 header.
So it persists and can give the end of its session. By help of
Libisoburn_nwa_alignemenT it should be possible to predict the start
of the next session header.
The LBA 0 header is written by isoburn_activate_session() already
with the first session. So the media is mountable.
A problem arises with DVD-RW in Intermediate State. They cannot be
written by random access before they were written sequentially.
In this case, no copy of the session 1 header is maintained and no TOC
will be possible. Thus writing begins sequentially at LBA 0.
*/
#define Libisoburn_overwriteable_starT \
((off_t) (Libisoburn_target_head_sizE/2048))
/* Wrappers for emulation of TOC on overwriteable media */
struct isoburn_toc_track {
/* Either track or toc_entry are supposed to be NULL */
struct burn_track *track;
struct isoburn_toc_entry *toc_entry;
};
struct isoburn_toc_session {
/* Either session or tracks and toc_entry are supposed to be NULL */
struct burn_session *session;
struct isoburn_toc_track **track_pointers;
int track_count;
struct isoburn_toc_entry *toc_entry;
};
struct isoburn_toc_disc {
/* Either disc or sessions and toc are supposed to be NULL */
struct burn_disc *disc;
struct isoburn_toc_session *sessions; /* storage array */
struct isoburn_toc_session **session_pointers; /* storage array */
struct isoburn_toc_track *tracks; /* storage array */
struct isoburn_toc_track **track_pointers; /* storage array */
int session_count;
int track_count;
struct isoburn_toc_entry *toc;
};
#endif /* Isoburn_includeD */

View File

@ -0,0 +1,402 @@
/*
cc -g -c isofs_wrap.c
*/
/*
libisofs related functions of libisoburn.
Copyright 2007 - 2008 Vreixo Formoso Lopes <metalpain2002@yahoo.es>
Thomas Schmitt <scdbackup@gmx.net>
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#ifndef Xorriso_standalonE
#include <libburn/libburn.h>
#include <libisofs/libisofs.h>
#else /* ! Xorriso_standalonE */
#include "../libisofs/libisofs.h"
#include "../libburn/libburn.h"
#endif /* Xorriso_standalonE */
#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;
}
static void isoburn_idle_free_function(void *ignored)
{
return;
}
/* API function. See libisoburn.h
*/
int isoburn_read_image(struct burn_drive *d,
struct isoburn_read_opts *read_opts,
IsoImage **image)
{
int ret, int_num, dummy;
IsoReadOpts *ropts= NULL;
IsoReadImageFeatures *features= NULL;
uint32_t ms_block;
char msg[160];
enum burn_disc_status status= BURN_DISC_BLANK;
IsoDataSource *ds= NULL;
struct isoburn *o= NULL;
if(read_opts==NULL) {
burn_msgs_submit(0x00060000,
"Program error: isoburn_read_image: read_opts==NULL",
0, "FATAL", NULL);
return(-1);
}
if(d != NULL) {
ret = isoburn_find_emulator(&o, d, 0);
if (ret < 0 || o == NULL)
return 0;
status = isoburn_disc_get_status(d);
}
if (d == NULL || status == BURN_DISC_BLANK || read_opts->pretend_blank) {
create_blank_image:;
/*
* Blank disc, we create a new image without files.
*/
if (d == NULL) {
/* New empty image without relation to a drive */
if (image==NULL) {
burn_msgs_submit(0x00060000,
"Program error: isoburn_read_image: image==NULL",
0, "FATAL", NULL);
return -1;
}
/* create a new image */
ret = iso_image_new("ISOIMAGE", image);
if (ret < 0) {
isoburn_report_iso_error(ret, "Cannot create image", 0, "FATAL", 0);
return ret;
}
} else {
/* Blank new image for the drive */
iso_image_unref(o->image);
ret = iso_image_new("ISOIMAGE", &o->image);
if (ret < 0) {
isoburn_report_iso_error(ret, "Cannot create image", 0, "FATAL", 0);
return ret;
}
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) {
burn_msgs_submit(0x00060000,
"Program error: isoburn_read_image: incorrect disc status",
0, "FATAL", NULL);
return -4;
}
memset((char *) &ropts, 0, sizeof(ropts));
ret = isoburn_disc_get_msc1(d, &int_num);
if (ret <= 0)
return -2;
ms_block= int_num;
ret = isoburn_read_iso_head(d, int_num, &dummy, NULL, 0);
if (ret <= 0) {
sprintf(msg, "No ISO 9660 image at LBA %d. Creating blank image.", int_num);
burn_msgs_submit(0x00060000, msg, 0, "WARNING", NULL);
goto create_blank_image;
}
/* create the data source */
ret = iso_read_opts_new(&ropts, 0);
if (ret < 0) {
isoburn_report_iso_error(ret, "Cannot create write opts", 0, "FATAL", 0);
return ret;
}
/* Important: do not return until iso_read_opts_free() */
iso_read_opts_set_start_block(ropts, ms_block);
iso_read_opts_set_no_rockridge(ropts, read_opts->norock);
iso_read_opts_set_no_joliet(ropts, read_opts->nojoliet);
iso_read_opts_set_no_iso1999(ropts, read_opts->noiso1999);
iso_read_opts_set_preferjoliet(ropts, read_opts->preferjoliet);
iso_read_opts_set_default_permissions(ropts,
read_opts->mode, read_opts->dirmode);
iso_read_opts_set_default_uid(ropts, read_opts->uid);
iso_read_opts_set_default_gid(ropts, read_opts->gid);
iso_read_opts_set_input_charset(ropts, read_opts->input_charset);
/* <<< experimental API call of libisofs
iso_read_opts_set_error_behavior(ropts, 1);
*/
ds = isoburn_data_source_new(d);
iso_image_attach_data(o->image, o->read_pacifier_handle,
isoburn_idle_free_function);
if(o->read_pacifier_handle==NULL)
iso_tree_set_report_callback(o->image, NULL);
else
iso_tree_set_report_callback(o->image, o->read_pacifier);
ret = iso_image_import(o->image, ds, ropts, &features);
iso_tree_set_report_callback(o->image, NULL);
iso_read_opts_free(ropts);
iso_data_source_unref(ds);
if (ret < 0) {
isoburn_report_iso_error(ret, "Cannot import image", 0, "FAILURE", 0);
return ret;
}
/* Important: do not return until free(features) */
if (image!=NULL) {
*image = o->image;
iso_image_ref(*image); /*protects object from premature free*/
}
read_opts->hasRR = iso_read_image_features_has_rockridge(features);
read_opts->hasJoliet = iso_read_image_features_has_joliet(features);
read_opts->hasIso1999 = iso_read_image_features_has_iso1999(features);
read_opts->hasElTorito = iso_read_image_features_has_eltorito(features);
read_opts->size = iso_read_image_features_get_size(features);
iso_read_image_features_destroy(features);
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) {
burn_msgs_submit(0x00060000,
"Program error: isoburn_attach_image: image==NULL",
0, "FATAL", NULL);
return -1;
}
ret = isoburn_find_emulator(&o, d, 0);
if (ret < 0 || o == NULL)
return 0;
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 ||
(o->fabricated_disc_status == BURN_DISC_BLANK &&
o->zero_nwa > 0)))
return 1;
ret = burn_random_access_write(drive, (off_t) 0, (char*)o->target_iso_head,
Libisoburn_target_head_sizE, 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;
if(o==NULL) {
burn_msgs_submit(0x00060000,
"Program error: isoburn_start_emulation: o==NULL",
0, "FATAL", NULL);
return -1;
}
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,
(off_t) Libisoburn_target_head_sizE, &data_count, 2);
/* 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 = Libisoburn_target_head_sizE;
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, o->zero_nwa * 2048, 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);
}
/* API @since 0.1.0 */
int isoburn_set_read_pacifier(struct burn_drive *drive,
int (*read_pacifier)(IsoImage*, IsoFileSource*),
void *read_handle)
{
int ret;
struct isoburn *o;
ret = isoburn_find_emulator(&o, drive, 0);
if(ret < 0 || o == NULL)
return -1;
o->read_pacifier_handle= read_handle;
o->read_pacifier= read_pacifier;
return(1);
}

File diff suppressed because it is too large Load Diff