Enabled multi-session with partition offset
This commit is contained in:
parent
5af8ad46f4
commit
d54efd4bc2
@ -1192,7 +1192,7 @@ int isoburn_emulate_toc(struct burn_drive *d, int flag)
|
||||
ret= isoburn_read_iso_head(d, lba, &image_size, NULL, 0);
|
||||
if(ret<=0)
|
||||
{ret= 0; goto failure;}
|
||||
lba= Libisoburn_overwriteable_starT;
|
||||
lba= o->target_iso_head_size / 2048;
|
||||
with_enclosure= 1;
|
||||
if((flag & 16) && o->emulation_mode == 1) {
|
||||
ret= 1;
|
||||
@ -1219,7 +1219,7 @@ int isoburn_emulate_toc(struct burn_drive *d, int flag)
|
||||
/* growisofs aligns to 16 rather than 32. Overwriteable TOC emulation
|
||||
relies on not accidentially seeing inter-session trash data.
|
||||
But one can safely access 16 blocks earlier because a xorriso header
|
||||
would have overwritten with the unused 16 blocks at its start.
|
||||
would have been overwritten with the unused 16 blocks at its start.
|
||||
If libisoburn alignment would increase, then this would not be
|
||||
possible any more.
|
||||
*/
|
||||
|
@ -115,7 +115,7 @@ struct isoburn *isoburn_list_start= NULL;
|
||||
int isoburn_new(struct isoburn **objpt, int flag)
|
||||
{
|
||||
struct isoburn *o;
|
||||
int i, ret;
|
||||
int ret;
|
||||
|
||||
*objpt= o= (struct isoburn *) malloc(sizeof(struct isoburn));
|
||||
if(o==NULL) {
|
||||
@ -137,8 +137,9 @@ int isoburn_new(struct isoburn **objpt, int flag)
|
||||
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->loaded_partition_offset= 0;
|
||||
o->target_iso_head_size= Libisoburn_target_head_sizE;
|
||||
o->target_iso_head= NULL;
|
||||
o->image= NULL;
|
||||
o->iso_data_source= NULL;
|
||||
o->read_pacifier= NULL;
|
||||
@ -148,9 +149,15 @@ int isoburn_new(struct isoburn **objpt, int flag)
|
||||
o->msgs_submit_flag= 0;
|
||||
o->prev= NULL;
|
||||
o->next= NULL;
|
||||
o->target_iso_head= calloc(1, o->target_iso_head_size);
|
||||
if(o->target_iso_head == NULL) {
|
||||
isoburn_report_iso_error(ISO_OUT_OF_MEM, "Cannot allocate overwrite buffer",
|
||||
0, "FATAL", 0);
|
||||
goto failed;
|
||||
}
|
||||
ret= iso_image_new("ISOIMAGE", &o->image);
|
||||
if(ret<0) {
|
||||
isoburn_report_iso_error(ret, "Cannot create image", 0, "FATAL", 0);
|
||||
isoburn_report_iso_error(ret, "Cannot create image object", 0, "FATAL", 0);
|
||||
goto failed;
|
||||
}
|
||||
isoburn_link(o, isoburn_list_start, 1);
|
||||
@ -188,6 +195,8 @@ int isoburn_destroy(struct isoburn **objpt, int flag)
|
||||
burn_source_free(o->iso_source);
|
||||
if(o->iso_data_source!=NULL)
|
||||
iso_data_source_unref(o->iso_data_source);
|
||||
if(o->target_iso_head != NULL)
|
||||
free(o->target_iso_head);
|
||||
free((char *) o);
|
||||
*objpt= NULL;
|
||||
return(1);
|
||||
@ -346,6 +355,37 @@ int isoburn_msgs_submit(struct isoburn *o, int error_code, char msg_text[],
|
||||
}
|
||||
|
||||
|
||||
/* TWINTREE:
|
||||
Check whether size of target_iso_head matches partition offset.
|
||||
Eventually adjust size.
|
||||
*/
|
||||
int isoburn_adjust_target_iso_head(struct isoburn *o,
|
||||
uint32_t offst, int flag)
|
||||
{
|
||||
uint8_t *new_buf;
|
||||
uint32_t new_size;
|
||||
|
||||
if(o->target_iso_head_size == Libisoburn_target_head_sizE + 2048 * offst)
|
||||
return(1);
|
||||
new_size= Libisoburn_target_head_sizE + 2048 * offst;
|
||||
new_buf= calloc(1, new_size);
|
||||
if(new_buf == NULL) {
|
||||
isoburn_msgs_submit(o, 0x00060000,
|
||||
"Cannot re-allocate overwrite buffer", 0, "FATAL", 0);
|
||||
return(-1);
|
||||
}
|
||||
memcpy(new_buf, o->target_iso_head,
|
||||
o->target_iso_head_size < new_size ? o->target_iso_head_size : new_size);
|
||||
free(o->target_iso_head);
|
||||
o->target_iso_head= new_buf;
|
||||
o->target_iso_head_size= new_size;
|
||||
if(o->nwa == o->zero_nwa)
|
||||
o->nwa= Libisoburn_overwriteable_starT + offst;
|
||||
o->zero_nwa= Libisoburn_overwriteable_starT + offst;
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
/* @param flag bit0= modifying rather than growing
|
||||
bit1= prepare for early release of input drive:
|
||||
wait until input and then disable image data source
|
||||
@ -458,10 +498,17 @@ int isoburn_prepare_disc_aux(struct burn_drive *in_d, struct burn_drive *out_d,
|
||||
opts->vol_expiration_time, opts->vol_effective_time,
|
||||
opts->vol_uuid);
|
||||
|
||||
ret= isoburn_adjust_target_iso_head(out_o, opts->partition_offset, 0);
|
||||
if(ret <= 0)
|
||||
{ret= -1; goto ex;}
|
||||
iso_write_opts_set_overwrite_buf(wopts,
|
||||
nwa>0 ? out_o->target_iso_head : NULL);
|
||||
|
||||
if(opts->no_emul_toc) {
|
||||
if(out_o->nwa == out_o->zero_nwa &&
|
||||
out_o->zero_nwa == Libisoburn_overwriteable_starT &&
|
||||
out_o->emulation_mode == 1) {
|
||||
out_o->zero_nwa == Libisoburn_overwriteable_starT
|
||||
+ opts->partition_offset
|
||||
&& out_o->emulation_mode == 1) {
|
||||
out_o->nwa= 0;
|
||||
out_o->zero_nwa= 0;
|
||||
out_o->min_start_byte= 0;
|
||||
@ -477,41 +524,9 @@ int isoburn_prepare_disc_aux(struct burn_drive *in_d, struct burn_drive *out_d,
|
||||
}
|
||||
iso_write_opts_set_ms_block(wopts, nwa);
|
||||
iso_write_opts_set_appendable(wopts, !new_img);
|
||||
iso_write_opts_set_overwrite_buf(wopts,
|
||||
nwa>0 ? out_o->target_iso_head : NULL);
|
||||
|
||||
if (opts->partition_offset > 0) {
|
||||
|
||||
if (nwa > 0) {
|
||||
/* >>> refuse because for now this works only for single session with
|
||||
no_emul_toc
|
||||
<<< to be removed when multi session stuff is fully ready
|
||||
*/
|
||||
isoburn_msgs_submit(in_o, 0x00060000,
|
||||
"Programming error: non-zero NWA combined with partition offset",
|
||||
0, "FATAL", 0);
|
||||
{ret= -4; goto ex;}
|
||||
}
|
||||
|
||||
iso_write_opts_set_part_offset(wopts, opts->partition_offset,
|
||||
opts->partition_secs_per_head,
|
||||
opts->partition_heads_per_cyl);
|
||||
}
|
||||
#ifdef Libisoburn_partition_offseT
|
||||
#if Libisoburn_partition_offseT >= 16
|
||||
|
||||
else {
|
||||
/* <<< For preliminary testing of emulated TOC and partition offset.
|
||||
Problem is that only this macro can prepare the overwrite buffer
|
||||
for partition offset yet. Emulated TOC does not work yet.
|
||||
*/
|
||||
iso_write_opts_set_part_offset(wopts,
|
||||
(uint32_t) Libisoburn_partition_offseT,
|
||||
0, 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
iso_write_opts_set_part_offset(wopts, opts->partition_offset,
|
||||
opts->partition_secs_per_head,
|
||||
opts->partition_heads_per_cyl);
|
||||
|
||||
ret = iso_image_create_burn_source(in_o->image, wopts, &wsrc);
|
||||
if (ret < 0) {
|
||||
|
@ -36,20 +36,15 @@ int isoburn_toc_entry_new(struct isoburn_toc_entry **objpt,
|
||||
int isoburn_toc_entry_destroy(struct isoburn_toc_entry **o, int flag);
|
||||
|
||||
|
||||
/* >>> TWINTREE : provisory test of partition offset with emulated TOC.
|
||||
.target_iso_head must become dynamically allocated
|
||||
#define Libisoburn_partition_offseT 16
|
||||
/* Minimal size of target_iso_head which is to be written during
|
||||
isoburn_activate_session().
|
||||
TWINTREE:
|
||||
Within this size there is everything that is needed for image access with
|
||||
no partition offset. The actual target_iso_head buffer must be larger by
|
||||
the evential partition offset.
|
||||
*/
|
||||
|
||||
|
||||
/* Size of target_iso_head which is to be written during
|
||||
isoburn_activate_session()
|
||||
*/
|
||||
#ifdef Libisoburn_partition_offseT
|
||||
#define Libisoburn_target_head_sizE (32*2048 +Libisoburn_partition_offseT*2048)
|
||||
#else
|
||||
#define Libisoburn_target_head_sizE (32*2048)
|
||||
#endif
|
||||
|
||||
|
||||
struct isoburn {
|
||||
|
||||
@ -114,9 +109,14 @@ struct isoburn {
|
||||
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];
|
||||
/* ISO head buffer to be filled by write run */
|
||||
int target_iso_head_size;
|
||||
uint8_t *target_iso_head;
|
||||
|
||||
/* The 2k offset which was read from a loaded image.
|
||||
*/
|
||||
uint32_t loaded_partition_offset;
|
||||
|
||||
|
||||
/* Libisofs image context */
|
||||
IsoImage *image;
|
||||
@ -253,6 +253,13 @@ isoburn_data_source_new(struct burn_drive *d);
|
||||
int isoburn_data_source_shutdown(IsoDataSource *src, int flag);
|
||||
|
||||
|
||||
/** TWINTREE:
|
||||
Check whether size of target_iso_head matches offset.
|
||||
Eventually adjust size.
|
||||
*/
|
||||
int isoburn_adjust_target_iso_head(struct isoburn *o,
|
||||
uint32_t offst, int flag);
|
||||
|
||||
/**
|
||||
* Options for image reading.
|
||||
(Comments here may be outdated. API getter/setter function descriptions
|
||||
@ -576,6 +583,10 @@ struct isoburn_imgen_opts {
|
||||
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.
|
||||
|
||||
TWINTREE:
|
||||
This macro gives the minimal size of an image header. It has to be
|
||||
enlarged by the eventual partition offset.
|
||||
*/
|
||||
#define Libisoburn_overwriteable_starT \
|
||||
((off_t) (Libisoburn_target_head_sizE/2048))
|
||||
|
@ -32,8 +32,8 @@
|
||||
|
||||
#endif /* Xorriso_standalonE */
|
||||
|
||||
#include "isoburn.h"
|
||||
#include "libisoburn.h"
|
||||
#include "isoburn.h"
|
||||
|
||||
#define BP(a,b) [(b) - (a) + 1]
|
||||
|
||||
@ -299,12 +299,111 @@ int isoburn_activate_session(struct burn_drive *drive)
|
||||
return 1;
|
||||
|
||||
ret = burn_random_access_write(drive, (off_t) 0, (char*)o->target_iso_head,
|
||||
Libisoburn_target_head_sizE, 1);
|
||||
o->target_iso_head_size, 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** TWINTREE:
|
||||
API @since 0.6.2
|
||||
*/
|
||||
int isoburn_get_img_partition_offset(struct burn_drive *drive,
|
||||
uint32_t *block_offset_2k)
|
||||
{
|
||||
int ret;
|
||||
struct isoburn *o;
|
||||
|
||||
ret = isoburn_find_emulator(&o, drive, 0);
|
||||
if(ret < 0 || o == NULL)
|
||||
return -1;
|
||||
*block_offset_2k= o->loaded_partition_offset;
|
||||
if(o->loaded_partition_offset == 0)
|
||||
return(0);
|
||||
if(o->target_iso_head_size == (off_t) Libisoburn_target_head_sizE
|
||||
+ (off_t) 2048 * (off_t) o->loaded_partition_offset)
|
||||
return(1);
|
||||
return(2);
|
||||
}
|
||||
|
||||
|
||||
/* TWINTREE:
|
||||
Check for MBR signature and a first partition that starts at a 2k block
|
||||
and ends where the image ends.
|
||||
If not too large or too small, accept its start as partition offset.
|
||||
*/
|
||||
static int isoburn_inspect_partition(struct isoburn *o, uint32_t img_size,
|
||||
int flag)
|
||||
{
|
||||
uint8_t *mbr, *part, buf[2048];
|
||||
uint32_t offst, numsec;
|
||||
struct ecma119_pri_vol_desc *pvm;
|
||||
off_t data_count;
|
||||
int ret;
|
||||
char msg[160];
|
||||
static int max_offst= 512 - 32;
|
||||
|
||||
mbr= o->target_iso_head;
|
||||
part= mbr + 446;
|
||||
if(mbr[510] != 0x55 || mbr[511] != 0xAA)
|
||||
return(2); /* not an MBR */
|
||||
|
||||
/* Does the first partition entry look credible ? */
|
||||
if(part[0] != 0x80 && part[0] != 0x00)
|
||||
return(2); /* Invalid partition status */
|
||||
if(part[1] == 0 && part[2] == 0 && part[3] == 0)
|
||||
return(2); /* Zero C/H/S start address */
|
||||
|
||||
/* Does it match the normal ISO image ? */
|
||||
offst= iso_read_lsb(part + 8, 4);
|
||||
numsec= iso_read_lsb(part + 12, 4);
|
||||
if(offst < 64)
|
||||
return(2); /* Zero or unusably small partition start */
|
||||
if((offst % 4) || (numsec % 4))
|
||||
return(2); /* Not aligned to 2k */
|
||||
if(numsec < 72)
|
||||
return(2); /* No room for volume descriptors */
|
||||
offst/= 4;
|
||||
numsec/= 4;
|
||||
if(offst + numsec != img_size)
|
||||
return(2); /* Partition end does not match image end */
|
||||
|
||||
/* Is there a PVD at the partition start ? */
|
||||
ret = burn_read_data(o->drive, (off_t) (offst + 16) * (off_t) 2048,
|
||||
(char*) buf, 2048, &data_count, 2);
|
||||
if(ret <= 0)
|
||||
return(2);
|
||||
pvm = (struct ecma119_pri_vol_desc *) buf;
|
||||
if (strncmp((char*) pvm->std_identifier, "CD001", 5) != 0)
|
||||
return(2); /* not a PVD */
|
||||
if (pvm->vol_desc_type[0] != 1 || pvm->vol_desc_version[0] != 1
|
||||
|| pvm->file_structure_version[0] != 1 )
|
||||
return(2); /* failed sanity check */
|
||||
|
||||
if(iso_read_lsb(pvm->vol_space_size, 4) + offst != img_size)
|
||||
return(2); /* Image ends do not match */
|
||||
|
||||
/* Now it is credible. Not yet clear is whether it is acceptable. */
|
||||
o->loaded_partition_offset= offst;
|
||||
|
||||
/* If the partition start is too large: Report but do not accept. */
|
||||
if(offst > max_offst) { /* Not more than 1 MB of .target_iso_head */
|
||||
sprintf(msg,
|
||||
"Detected partition offset of %.f blocks. Maximum for load buffer is %d",
|
||||
(double) offst, max_offst);
|
||||
isoburn_msgs_submit(NULL, 0x00060000, msg, 0, "WARNING", 0);
|
||||
return(3);
|
||||
}
|
||||
|
||||
/* Accept partition start and adjust buffer size */
|
||||
ret= isoburn_adjust_target_iso_head(o, offst, 0);
|
||||
if(ret <= 0)
|
||||
return(ret);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
/** 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
|
||||
@ -337,8 +436,8 @@ int isoburn_start_emulation(struct isoburn *o, int flag)
|
||||
if (capacity > 0 || role == 2) {
|
||||
/* Might be a block device on a system where libburn cannot determine its
|
||||
size. Try to read anyway. */
|
||||
memset(o->target_iso_head, 0, Libisoburn_target_head_sizE);
|
||||
to_read = Libisoburn_target_head_sizE;
|
||||
to_read = o->target_iso_head_size;
|
||||
memset(o->target_iso_head, 0, to_read);
|
||||
if(capacity > 0 && (off_t) capacity * (off_t) 2048 < to_read)
|
||||
to_read = (off_t) capacity * (off_t) 2048;
|
||||
ret = burn_read_data(drive, (off_t) 0, (char*)o->target_iso_head,
|
||||
@ -370,7 +469,7 @@ int isoburn_start_emulation(struct isoburn *o, int flag)
|
||||
|
||||
pvm = (struct ecma119_pri_vol_desc *)(o->target_iso_head + 16 * 2048);
|
||||
|
||||
if (!strncmp((char*)pvm->std_identifier, "CD001", 5)) {
|
||||
if (strncmp((char*)pvm->std_identifier, "CD001", 5) == 0) {
|
||||
off_t size;
|
||||
|
||||
/* sanity check */
|
||||
@ -383,6 +482,9 @@ int isoburn_start_emulation(struct isoburn *o, int flag)
|
||||
|
||||
/* ok, PVM found, set size */
|
||||
size = (off_t) iso_read_lsb(pvm->vol_space_size, 4);
|
||||
ret= isoburn_inspect_partition(o, (uint32_t) size, 0);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
size *= (off_t) 2048; /* block size in bytes */
|
||||
isoburn_set_start_byte(o, size, 0);
|
||||
o->fabricated_disc_status= BURN_DISC_APPENDABLE;
|
||||
@ -395,6 +497,7 @@ int isoburn_start_emulation(struct isoburn *o, int flag)
|
||||
/* treat any disc in an unknown format as full */
|
||||
o->fabricated_disc_status= BURN_DISC_FULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1361,6 +1361,24 @@ int isoburn_set_read_pacifier(struct burn_drive *drive,
|
||||
int (*read_pacifier)(IsoImage*, IsoFileSource*),
|
||||
void *app_handle);
|
||||
|
||||
/** TWINTREE:
|
||||
Inquire the partition offset of the loaded image. The first 512 bytes of
|
||||
the image get examined whether they bear an MBR signature and a first
|
||||
partition table entry which matches the size of the image. In this case
|
||||
the start address is recorded as partition offset and internal buffers
|
||||
get adjusted.
|
||||
See also isoburn_igopt_set_part_offset().
|
||||
@since 0.6.2
|
||||
@param drive The drive with the loaded image
|
||||
@param block_offset_2k returns the recognized partition offset
|
||||
@return <0 = error
|
||||
0 = no partition offset recognized
|
||||
1 = acceptable non-zero offset, buffers are adjusted
|
||||
2 = offset is credible but not acceptable for buffer size
|
||||
*/
|
||||
int isoburn_get_img_partition_offset(struct burn_drive *drive,
|
||||
uint32_t *block_offset_2k);
|
||||
|
||||
|
||||
/** Set the IsoImage to be used with a drive. This eventually releases
|
||||
the reference to the old IsoImage attached to the drive.
|
||||
@ -1659,3 +1677,7 @@ void isoburn_finish(void);
|
||||
int isoburn_needs_emulation(struct burn_drive *d);
|
||||
|
||||
|
||||
/* ---------------------------- Test area ----------------------------- */
|
||||
|
||||
/* no tests active, currently */
|
||||
|
||||
|
@ -1 +1 @@
|
||||
#define Xorriso_timestamP "2010.09.06.103347"
|
||||
#define Xorriso_timestamP "2010.09.10.170925"
|
||||
|
Loading…
Reference in New Issue
Block a user