New API function isoburn_prepare_blind_grow() for -as mkisofs -multi
This commit is contained in:
parent
837f60c2e4
commit
88ef7d06f4
@ -625,6 +625,23 @@ int isoburn_disc_track_lba_nwa(struct burn_drive *d,
|
||||
}
|
||||
|
||||
|
||||
int isoburn_get_msc2(struct isoburn *o,
|
||||
struct burn_write_opts *opts, int *msc2, int flag)
|
||||
{
|
||||
int ret, lba, nwa;
|
||||
|
||||
if(o->fabricated_msc2>=0)
|
||||
*msc2= o->fabricated_msc2;
|
||||
else {
|
||||
ret= isoburn_disc_track_lba_nwa(o->drive, opts, 0, &lba, &nwa);
|
||||
if(ret<=0)
|
||||
return(ret);
|
||||
*msc2= nwa;
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
void isoburn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
|
||||
{
|
||||
int ret;
|
||||
|
@ -85,6 +85,19 @@ int ds_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer)
|
||||
|
||||
icd = (struct isoburn_cached_drive *) src->data;
|
||||
d = (struct burn_drive*) icd->drive;
|
||||
|
||||
if(d == NULL) {
|
||||
/* This would happen if libisoburn saw output data in the fifo and
|
||||
performed early drive release and afterwards libisofs still tries
|
||||
to read data.
|
||||
That would constitute a bad conceptual problem in libisoburn.
|
||||
*/
|
||||
isoburn_msgs_submit(NULL, 0x00060000,
|
||||
"Programming error: Drive released while libisofs still attempts to read",
|
||||
0, "FATAL", 0);
|
||||
return ISO_ASSERT_FAILURE;
|
||||
}
|
||||
|
||||
tiles = (struct isoburn_cache_tile *) icd->tiles;
|
||||
|
||||
aligned_lba= lba & ~(Libisoburn_tile_blockS - 1);
|
||||
@ -189,6 +202,19 @@ static void ds_free_data(IsoDataSource *src)
|
||||
src->data= NULL;
|
||||
}
|
||||
|
||||
|
||||
int isoburn_data_source_shutdown(IsoDataSource *src, int flag)
|
||||
{
|
||||
struct isoburn_cached_drive *icd;
|
||||
|
||||
if(src==NULL)
|
||||
return(0);
|
||||
icd= (struct isoburn_cached_drive *) src->data;
|
||||
icd->drive= NULL;
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
IsoDataSource *isoburn_data_source_new(struct burn_drive *d)
|
||||
{
|
||||
IsoDataSource *ret;
|
||||
|
@ -119,6 +119,7 @@ int isoburn_new(struct isoburn **objpt, int flag)
|
||||
o->drive= NULL;
|
||||
o->emulation_mode= 0;
|
||||
o->fabricated_msc1= -1;
|
||||
o->fabricated_msc2= -1;
|
||||
o->zero_nwa= Libisoburn_overwriteable_starT;
|
||||
o->min_start_byte= o->zero_nwa * 2048;
|
||||
o->nwa= o->zero_nwa;
|
||||
@ -130,6 +131,7 @@ int isoburn_new(struct isoburn **objpt, int flag)
|
||||
for(i=0;i<Libisoburn_target_head_sizE;i++)
|
||||
o->target_iso_head[i]= 0;
|
||||
o->image= NULL;
|
||||
o->iso_data_source= NULL;
|
||||
o->read_pacifier= NULL;
|
||||
o->read_pacifier_handle= NULL;
|
||||
o->msgs_submit= NULL;
|
||||
@ -175,7 +177,8 @@ int isoburn_destroy(struct isoburn **objpt, int flag)
|
||||
isoburn_toc_entry_destroy(&(o->toc), 1); /* all */
|
||||
if(o->iso_source!=NULL)
|
||||
burn_source_free(o->iso_source);
|
||||
|
||||
if(o->iso_data_source!=NULL)
|
||||
iso_data_source_unref(o->iso_data_source);
|
||||
free((char *) o);
|
||||
*objpt= NULL;
|
||||
return(1);
|
||||
@ -334,10 +337,14 @@ int isoburn_msgs_submit(struct isoburn *o, int error_code, char msg_text[],
|
||||
}
|
||||
|
||||
|
||||
/* @param flag bit0= modifying rather than growing
|
||||
bit1= prepare for early release of input drive:
|
||||
wait until input and then disable image data source
|
||||
*/
|
||||
static
|
||||
int isoburn_prepare_disc_aux(struct burn_drive *in_d, struct burn_drive *out_d,
|
||||
struct burn_disc **disc,
|
||||
struct isoburn_imgen_opts *opts, int new_img)
|
||||
struct isoburn_imgen_opts *opts, int flag)
|
||||
{
|
||||
struct burn_source *wsrc;
|
||||
struct burn_session *session;
|
||||
@ -345,7 +352,18 @@ int isoburn_prepare_disc_aux(struct burn_drive *in_d, struct burn_drive *out_d,
|
||||
struct isoburn *in_o, *out_o;
|
||||
IsoWriteOpts *wopts= NULL;
|
||||
enum burn_disc_status state;
|
||||
int ret, fifo_chunks, lba, nwa;
|
||||
int ret, fifo_chunks, nwa, i, new_img, early_indev_release;
|
||||
size_t buffer_size= 0, buffer_free= 0;
|
||||
char msg[160];
|
||||
|
||||
new_img= flag&1;
|
||||
early_indev_release= flag&2;
|
||||
if(new_img && early_indev_release) {
|
||||
isoburn_msgs_submit(in_o, 0x00060000,
|
||||
"Programming error: Wrong session setup: new_img && early_indev_release",
|
||||
0, "FATAL", 0);
|
||||
{ret= -4; goto ex;}
|
||||
}
|
||||
|
||||
ret= isoburn_find_emulator(&in_o, in_d, 0);
|
||||
if(ret<0 || in_o==NULL)
|
||||
@ -405,19 +423,12 @@ int isoburn_prepare_disc_aux(struct burn_drive *in_d, struct burn_drive *out_d,
|
||||
iso_write_opts_set_output_charset(wopts, opts->output_charset);
|
||||
iso_write_opts_set_fifo_size(wopts, fifo_chunks);
|
||||
|
||||
|
||||
ret = isoburn_disc_track_lba_nwa(out_d, NULL, 0, &lba, &nwa);
|
||||
ret= isoburn_get_msc2(out_o, NULL, &nwa, 0);
|
||||
if (ret != 1) {
|
||||
isoburn_msgs_submit(out_o, 0x00060000,
|
||||
"Cannot determine next writeable address", 0, "FAILURE", 0);
|
||||
{ret= -3; goto ex;}
|
||||
}
|
||||
if (nwa == 0 && state == BURN_DISC_APPENDABLE) {
|
||||
isoburn_msgs_submit(out_o, 0x00060000,
|
||||
"Encountered 0 as next writeable address of appendable",
|
||||
0, "FAILURE", 0);
|
||||
{ret= -4; goto ex;}
|
||||
}
|
||||
iso_write_opts_set_ms_block(wopts, nwa);
|
||||
opts->effective_lba= nwa;
|
||||
iso_write_opts_set_appendable(wopts, !new_img);
|
||||
@ -429,6 +440,30 @@ int isoburn_prepare_disc_aux(struct burn_drive *in_d, struct burn_drive *out_d,
|
||||
isoburn_report_iso_error(ret, "Cannot create burn source", 0, "FAILURE", 0);
|
||||
{ret= -1; goto ex;}
|
||||
}
|
||||
if (early_indev_release) {
|
||||
for(i= 0; i<300; i++) {
|
||||
|
||||
/* <<< ??? */
|
||||
if((i%30) == 0) {
|
||||
sprintf(msg, "Waiting for data in fifo since %d seconds", i/30);
|
||||
isoburn_msgs_submit(in_o, 0x00060000, msg, 0, "DEBUG", 0);
|
||||
}
|
||||
|
||||
usleep(100000);
|
||||
ret= iso_ring_buffer_get_status(wsrc, &buffer_size, &buffer_free);
|
||||
if(ret >0 && buffer_size != buffer_free)
|
||||
break;
|
||||
}
|
||||
|
||||
/* <<< ??? */
|
||||
sprintf(msg,
|
||||
"After %.1f seconds: %d bytes of output available (fifo state=%d)",
|
||||
((double) i+1) / 10.0, (int) (buffer_size - buffer_free), ret);
|
||||
isoburn_msgs_submit(in_o, 0x00060000, msg, 0, "DEBUG", 0);
|
||||
|
||||
if(in_o->iso_data_source!=NULL)
|
||||
isoburn_data_source_shutdown(in_o->iso_data_source, 0);
|
||||
}
|
||||
|
||||
/* TODO check return values for failure. propertly clean-up on error */
|
||||
|
||||
@ -474,6 +509,27 @@ int isoburn_prepare_new_image(struct burn_drive *d, struct burn_disc **disc,
|
||||
}
|
||||
|
||||
|
||||
/* API since 0.2.2 */
|
||||
int isoburn_prepare_blind_grow(struct burn_drive *d, struct burn_disc **disc,
|
||||
struct isoburn_imgen_opts *opts,
|
||||
struct burn_drive *out_drive, int nwa)
|
||||
{
|
||||
int ret;
|
||||
struct isoburn *o= NULL;
|
||||
|
||||
if(nwa >= 0) {
|
||||
ret= isoburn_find_emulator(&o, out_drive, 0);
|
||||
if(ret<0 || o==NULL)
|
||||
return(-1);
|
||||
o->fabricated_msc2= nwa;
|
||||
}
|
||||
ret= isoburn_prepare_disc_aux(d, out_drive, disc, opts, 2);
|
||||
if (ret<=0)
|
||||
return ret;
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
/* API @since 0.1.0
|
||||
@param flag bit0= this is a regular end, not an abort
|
||||
give up source reference
|
||||
|
@ -60,9 +60,17 @@ struct isoburn {
|
||||
*/
|
||||
int fabricated_msc1;
|
||||
|
||||
/* If >= 0, this address is used in isoburn_disc_track_lba_nwa()
|
||||
as reply parameter nwa.
|
||||
(The other nwa parameters below apply only to the effective write address
|
||||
on random access media. msc2 is handed to libisofs but not to libburn.)
|
||||
*/
|
||||
int fabricated_msc2;
|
||||
|
||||
|
||||
/* 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) */
|
||||
@ -71,6 +79,7 @@ struct isoburn {
|
||||
/* 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;
|
||||
|
||||
@ -99,6 +108,10 @@ struct isoburn {
|
||||
/* Libisofs image context */
|
||||
IsoImage *image;
|
||||
|
||||
/* The block data source from which the existing image is read.
|
||||
*/
|
||||
IsoDataSource *iso_data_source;
|
||||
|
||||
/* The burn source which transfers data from libisofs to libburn.
|
||||
It has its own fifo.
|
||||
*/
|
||||
@ -190,6 +203,19 @@ int isoburn_msgs_submit(struct isoburn *o, int error_code, char msg_text[],
|
||||
*/
|
||||
int isoburn_set_start_byte(struct isoburn *o, off_t value, int flag);
|
||||
|
||||
/** Obtains the image address offset to be used with image generation.
|
||||
This is either the (emulated) drive nwa or a value set by
|
||||
isoburn_prepare_blind_grow().
|
||||
In any case this is the address to tell to iso_write_opts_set_ms_block().
|
||||
@param o The isoburn object to be inquired
|
||||
@param opts If not NULL: write parameters to be set on drive before query
|
||||
@param msc2 The value to be used with iso_write_opts_set_ms_block()
|
||||
@param flag unused yet
|
||||
@return <=0 is failure , >0 success
|
||||
*/
|
||||
int isoburn_get_msc2(struct isoburn *o,
|
||||
struct burn_write_opts *opts, int *msc2, 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.
|
||||
@ -200,6 +226,19 @@ int isoburn_set_start_byte(struct isoburn *o, off_t value, int flag);
|
||||
IsoDataSource *
|
||||
isoburn_data_source_new(struct burn_drive *d);
|
||||
|
||||
/** Disable read capabilities of a data source which was originally created
|
||||
by isoburn_data_source_new(). After this any attempt to read will yield
|
||||
a FATAL programming error event.
|
||||
This is usually done to allow libburn to release the drive while libisofs
|
||||
still holds a reference to the data source object. libisofs is not supposed
|
||||
to use this object for reading any more, nevertheless. The disabled state
|
||||
of the data source is a safety fence around this daring situation.
|
||||
@param src The data source to be disabled
|
||||
@param flag unused yet
|
||||
@return <=0 is failure , >0 success
|
||||
*/
|
||||
int isoburn_data_source_shutdown(IsoDataSource *src, int flag);
|
||||
|
||||
|
||||
/**
|
||||
* Options for image reading.
|
||||
|
@ -212,6 +212,9 @@ create_blank_image:;
|
||||
*/
|
||||
|
||||
ds = isoburn_data_source_new(d);
|
||||
if(o->iso_data_source!=NULL)
|
||||
iso_data_source_unref(o->iso_data_source);
|
||||
o->iso_data_source= ds;
|
||||
iso_image_attach_data(o->image, o->read_pacifier_handle,
|
||||
isoburn_idle_free_function);
|
||||
if(o->read_pacifier_handle==NULL)
|
||||
@ -221,7 +224,7 @@ create_blank_image:;
|
||||
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;
|
||||
@ -277,6 +280,8 @@ int isoburn_activate_session(struct burn_drive *drive)
|
||||
|
||||
if (o->emulation_mode != 1)
|
||||
return 1; /* don't need to activate session */
|
||||
if (o->fabricated_msc2 >= 0)
|
||||
return 1; /* blind growing: do not alter anything outside the session */
|
||||
|
||||
if (!(o->fabricated_disc_status == BURN_DISC_APPENDABLE ||
|
||||
(o->fabricated_disc_status == BURN_DISC_BLANK &&
|
||||
|
@ -75,10 +75,10 @@ job parameters. It rather states its desires which libisoburn tries to
|
||||
fulfill, or else will refuse to start the write run.
|
||||
|
||||
|
||||
Setup for Growing or Modifying
|
||||
Setup for Growing, Modifying or Blind Growing
|
||||
|
||||
The connector function family offers two alternative API calls for performing
|
||||
the setup for two alternative image generation strategies.
|
||||
the setup for several alternative image generation strategies.
|
||||
|
||||
Growing:
|
||||
If input and output drive is the same, then isoburn_prepare_disc() is to
|
||||
@ -93,6 +93,16 @@ generation run, use isoburn_prepare_new_image(). The run will copy file data
|
||||
from an eventual input drive with valid image, add any newly introduced data
|
||||
from the local filesystem, and produce a first session on output media.
|
||||
|
||||
Blind Growing:
|
||||
This method reads the old image from one drive and writes the add-on session
|
||||
to a different drive. That output drive is nevertheless supposed to
|
||||
finally lead to the same media from where the session was loaded. Usually it
|
||||
will be stdio:/dev/fd/1 (i.e. stdout) being piped into some burn program
|
||||
like with this classic gesture:
|
||||
mkisofs -M $dev -C $msc1,$nwa | cdrecord -waiti dev=$dev
|
||||
Blind growing is prepared by the call isoburn_prepare_blind_grow().
|
||||
The input drive should be released immediately after this call.
|
||||
|
||||
After either of these setups, some peripheral libburn drive parameter settings
|
||||
like burn_write_opts_set_simulate(), burn_write_opts_set_multi(),
|
||||
burn_drive_set_speed(), burn_write_opts_set_underrun_proof() should be made.
|
||||
@ -1068,7 +1078,8 @@ int isoburn_get_min_start_byte(struct burn_drive *d, off_t *start_byte,
|
||||
int flag);
|
||||
|
||||
|
||||
/** Create a disc object for writing the new session from the created or loaded
|
||||
/** To choose the expansion method of Growing:
|
||||
Create a disc object for writing the new session from the created or loaded
|
||||
iso_volset which has been manipulated via libisofs, to the same media from
|
||||
where the image was eventually loaded. This struct burn_disc is ready for
|
||||
use by a subsequent call to isoburn_disc_write().
|
||||
@ -1085,9 +1096,10 @@ int isoburn_prepare_disc(struct burn_drive *drive, struct burn_disc **disc,
|
||||
struct isoburn_imgen_opts *opts);
|
||||
|
||||
|
||||
/** Create a disc object for producing a new image from a previous image
|
||||
/** To choose the expansion method of Modifying:
|
||||
Create a disc object for producing a new image from a previous image
|
||||
plus the changes made by user. The generated burn_disc is suitable
|
||||
to be written to any grabbed libburn drive with blank writeable media.
|
||||
to be written to a grabbed drive with blank writeable media.
|
||||
But you must not use the same drive for input and output, because data
|
||||
will be read from the source drive while at the same time the target
|
||||
drive is already writing.
|
||||
@ -1095,15 +1107,11 @@ int isoburn_prepare_disc(struct burn_drive *drive, struct burn_disc **disc,
|
||||
is done and the drive is BURN_DRIVE_IDLE again after asynchronous
|
||||
burn_disc_write().
|
||||
@since 0.1.0
|
||||
@param in_drive The input drive,grabbed with isoburn_drive_scan_and_grab().
|
||||
@param in_drive The input drive, grabbed with isoburn_drive_aquire() or
|
||||
one of its alternatives.
|
||||
@param disc Returns the newly created burn_disc object.
|
||||
@param opts Options for image generation and data transport to media.
|
||||
@param out_drive The libburn drive which shall be write target.
|
||||
If the drive was grabbed via libisoburn then it can later
|
||||
access the libisofs source fifo via
|
||||
isoburn_get_fifo_status().
|
||||
Mere libburn drives cannot obtain this info.
|
||||
In that case out_drive may be NULL, as well.
|
||||
@param out_drive The output drive, from isoburn_drive_aquire() et.al..
|
||||
@return <=0 error , 1 = success
|
||||
*/
|
||||
int isoburn_prepare_new_image(struct burn_drive *in_drive,
|
||||
@ -1111,7 +1119,52 @@ int isoburn_prepare_new_image(struct burn_drive *in_drive,
|
||||
struct isoburn_imgen_opts *opts,
|
||||
struct burn_drive *out_drive);
|
||||
|
||||
/** @since 0.1.0
|
||||
|
||||
/** To choose the expansion method of Blind Growing:
|
||||
Create a disc object for writing an add-on session from the created or
|
||||
loaded IsoImage which has been manipulated via libisofs, to a different
|
||||
drive than the one from where it was loaded.
|
||||
Usually output will be stdio:/dev/fd/1 (i.e. stdout) being piped
|
||||
into some burn program like with this classic gesture:
|
||||
mkisofs -M $dev -C $msc1,$nwa | cdrecord -waiti dev=$dev
|
||||
Parameter translation into libisoburn:
|
||||
$dev is the address by which parameter in_drive of this call was aquired
|
||||
$msc1 was set by isoburn_set_msc1() before image reading
|
||||
or was detected from the in_drive media
|
||||
$nwa is a parameter of this call
|
||||
or can be used as detected from the in_drive media
|
||||
|
||||
This call waits for libisofs output to become available and then detaches
|
||||
the input drive object from the data source object by which libisofs was
|
||||
reading from the input drive.
|
||||
So, as far as libisofs is concerned, that drive may be released immediately
|
||||
after this call in order to allow the consumer to access the drive for
|
||||
writing.
|
||||
The consumer should wait for input to become available and only then open
|
||||
its burn drive. With cdrecord this is caused by option -waiti.
|
||||
|
||||
The resulting burn_disc object has to be disposed when all its writing
|
||||
is done and the drive is BURN_DRIVE_IDLE again after asynchronous
|
||||
burn_disc_write().
|
||||
@since 0.2.2
|
||||
@param in_drive The input drive,grabbed with isoburn_drive_scan_and_grab().
|
||||
@param disc Returns the newly created burn_disc object.
|
||||
@param opts Options for image generation and data transport to media.
|
||||
@param out_drive The output drive, from isoburn_drive_aquire() et.al..
|
||||
typically stdio:/dev/fd/1 .
|
||||
@param nwa The address (2048 byte block count) where the add-on
|
||||
session will be finally stored on a mountable media
|
||||
or in a mountable file.
|
||||
If nwa is -1 then the address is used as determined from
|
||||
the in_drive media.
|
||||
@return <=0 error , 1 = success
|
||||
*/
|
||||
int isoburn_prepare_blind_grow(struct burn_drive *d, struct burn_disc **disc,
|
||||
struct isoburn_imgen_opts *opts,
|
||||
struct burn_drive *out_drive, int nwa);
|
||||
|
||||
|
||||
/**
|
||||
Revoke isoburn_prepare_new_image() or isoburn_prepare_disc() instead of
|
||||
running isoburn_disc_write().
|
||||
libisofs reserves resources and maybe already starts generating the
|
||||
@ -1193,8 +1246,7 @@ int isoburn_drive_wrote_well(struct burn_drive *d);
|
||||
int isoburn_activate_session(struct burn_drive *drive);
|
||||
|
||||
|
||||
/** @since 0.1.0
|
||||
Wait after normal end of operations until libisofs ended all write
|
||||
/** Wait after normal end of operations until libisofs ended all write
|
||||
threads and freed resource reservations.
|
||||
This call is not mandatory. But without it, messages from the ending
|
||||
threads might appear after the application ended its write procedure.
|
||||
@ -1210,21 +1262,6 @@ int isoburn_sync_after_write(struct burn_drive *input_drive,
|
||||
struct burn_drive *output_drive, int flag);
|
||||
|
||||
|
||||
#if 0
|
||||
/* >>> NOT YET IMPLEMENTED <<< */
|
||||
/** Write a new session to a disc.
|
||||
This is a synchronous call equivalent to isoburn_prepare_disc +
|
||||
isoburn_disc_write + isoburn_activate_session
|
||||
@param pacifier_func If not NULL: a function to produce appeasing messages.
|
||||
See burn_abort_pacifier() in libburn.h for an example.
|
||||
*/
|
||||
/* TODO implement this */
|
||||
int isoburn_perform_write(struct burn_write_opts *o,
|
||||
int (*pacifier_func)(void *handle, int patience,
|
||||
int elapsed));
|
||||
#endif /* 0 */
|
||||
|
||||
|
||||
/** Release an aquired drive.
|
||||
Wrapper for: burn_drive_release()
|
||||
@since 0.1.0
|
||||
|
@ -1 +1 @@
|
||||
#define Xorriso_timestamP "2008.07.04.070001"
|
||||
#define Xorriso_timestamP "2008.07.05.132528"
|
||||
|
Loading…
Reference in New Issue
Block a user