Branches 0.1.6 of libisoburn
This commit is contained in:
1524
libisoburn/branches/ZeroOneSix/libisoburn/burn_wrap.c
Normal file
1524
libisoburn/branches/ZeroOneSix/libisoburn/burn_wrap.c
Normal file
File diff suppressed because it is too large
Load Diff
372
libisoburn/branches/ZeroOneSix/libisoburn/data_source.c
Normal file
372
libisoburn/branches/ZeroOneSix/libisoburn/data_source.c
Normal 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 */
|
||||
|
866
libisoburn/branches/ZeroOneSix/libisoburn/isoburn.c
Normal file
866
libisoburn/branches/ZeroOneSix/libisoburn/isoburn.c
Normal 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);
|
||||
}
|
||||
|
||||
|
422
libisoburn/branches/ZeroOneSix/libisoburn/isoburn.h
Normal file
422
libisoburn/branches/ZeroOneSix/libisoburn/isoburn.h
Normal 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 */
|
||||
|
402
libisoburn/branches/ZeroOneSix/libisoburn/isofs_wrap.c
Normal file
402
libisoburn/branches/ZeroOneSix/libisoburn/isofs_wrap.c
Normal 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);
|
||||
}
|
||||
|
1224
libisoburn/branches/ZeroOneSix/libisoburn/libisoburn.h
Normal file
1224
libisoburn/branches/ZeroOneSix/libisoburn/libisoburn.h
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user