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