New API call iso_write_opts_set_tail_blocks() for tail padding inside ISO image

This commit is contained in:
Thomas Schmitt 2010-10-02 22:57:09 +02:00
parent a387a8b06a
commit 69a25c9734
5 changed files with 163 additions and 20 deletions

View File

@ -922,7 +922,7 @@ int ecma119_writer_create(Ecma119Image *target)
/** compute how many padding bytes are needed */
static
int pad_writer_compute_data_blocks(IsoImageWriter *writer)
int mspad_writer_compute_data_blocks(IsoImageWriter *writer)
{
Ecma119Image *target;
uint32_t min_size;
@ -933,24 +933,25 @@ int pad_writer_compute_data_blocks(IsoImageWriter *writer)
target = writer->target;
min_size = 32 + target->partition_offset;
if (target->curblock < min_size) {
target->pad_blocks = min_size - target->curblock;
target->mspad_blocks = min_size - target->curblock;
target->curblock = min_size;
}
return ISO_SUCCESS;
}
static
int pad_writer_write_vol_desc(IsoImageWriter *writer)
int mspad_writer_write_vol_desc(IsoImageWriter *writer)
{
/* nothing to do */
return ISO_SUCCESS;
}
static
int pad_writer_write_data(IsoImageWriter *writer)
int mspad_writer_write_data(IsoImageWriter *writer)
{
int ret;
Ecma119Image *t;
uint32_t pad[BLOCK_SIZE];
uint8_t pad[BLOCK_SIZE];
size_t i;
if (writer == NULL) {
@ -958,12 +959,12 @@ int pad_writer_write_data(IsoImageWriter *writer)
}
t = writer->target;
if (t->pad_blocks == 0) {
if (t->mspad_blocks == 0) {
return ISO_SUCCESS;
}
memset(pad, 0, BLOCK_SIZE);
for (i = 0; i < t->pad_blocks; ++i) {
for (i = 0; i < t->mspad_blocks; ++i) {
ret = iso_write(t, pad, BLOCK_SIZE);
if (ret < 0) {
return ret;
@ -974,14 +975,14 @@ int pad_writer_write_data(IsoImageWriter *writer)
}
static
int pad_writer_free_data(IsoImageWriter *writer)
int mspad_writer_free_data(IsoImageWriter *writer)
{
/* nothing to do */
return ISO_SUCCESS;
}
static
int pad_writer_create(Ecma119Image *target)
int mspad_writer_create(Ecma119Image *target)
{
IsoImageWriter *writer;
@ -990,10 +991,10 @@ int pad_writer_create(Ecma119Image *target)
return ISO_OUT_OF_MEM;
}
writer->compute_data_blocks = pad_writer_compute_data_blocks;
writer->write_vol_desc = pad_writer_write_vol_desc;
writer->write_data = pad_writer_write_data;
writer->free_data = pad_writer_free_data;
writer->compute_data_blocks = mspad_writer_compute_data_blocks;
writer->write_vol_desc = mspad_writer_write_vol_desc;
writer->write_data = mspad_writer_write_data;
writer->free_data = mspad_writer_free_data;
writer->data = NULL;
writer->target = target;
@ -1002,6 +1003,100 @@ int pad_writer_create(Ecma119Image *target)
return ISO_SUCCESS;
}
/** ----- Zero padding writer ----- */
struct iso_zero_writer_data_struct {
uint32_t num_blocks;
};
static
int zero_writer_compute_data_blocks(IsoImageWriter *writer)
{
Ecma119Image *target;
struct iso_zero_writer_data_struct *data;
if (writer == NULL)
return ISO_ASSERT_FAILURE;
target = writer->target;
data = (struct iso_zero_writer_data_struct *) writer->data;
target->curblock += data->num_blocks;
return ISO_SUCCESS;
}
static
int zero_writer_write_vol_desc(IsoImageWriter *writer)
{
/* nothing to do */
return ISO_SUCCESS;
}
static
int zero_writer_write_data(IsoImageWriter *writer)
{
int ret;
Ecma119Image *t;
struct iso_zero_writer_data_struct *data;
uint8_t pad[BLOCK_SIZE];
size_t i;
if (writer == NULL)
return ISO_ASSERT_FAILURE;
t = writer->target;
data = (struct iso_zero_writer_data_struct *) writer->data;
if (data->num_blocks == 0)
return ISO_SUCCESS;
memset(pad, 0, BLOCK_SIZE);
for (i = 0; i < data->num_blocks; ++i) {
ret = iso_write(t, pad, BLOCK_SIZE);
if (ret < 0)
return ret;
}
return ISO_SUCCESS;
}
static
int zero_writer_free_data(IsoImageWriter *writer)
{
if (writer == NULL)
return ISO_SUCCESS;
if (writer->data == NULL)
return ISO_SUCCESS;
free(writer->data);
writer->data = NULL;
return ISO_SUCCESS;
}
static
int zero_writer_create(Ecma119Image *target, uint32_t num_blocks)
{
IsoImageWriter *writer;
struct iso_zero_writer_data_struct *data;
writer = malloc(sizeof(IsoImageWriter));
if (writer == NULL) {
return ISO_OUT_OF_MEM;
}
data = calloc(1, sizeof(struct iso_zero_writer_data_struct));
if (data == NULL) {
free(writer);
return ISO_OUT_OF_MEM;
}
data->num_blocks = num_blocks;
writer->compute_data_blocks = zero_writer_compute_data_blocks;
writer->write_vol_desc = zero_writer_write_vol_desc;
writer->write_data = zero_writer_write_data;
writer->free_data = zero_writer_free_data;
writer->data = data;
writer->target = target;
/* add this writer to image */
target->writers[target->nwriters++] = writer;
return ISO_SUCCESS;
}
static
int transplant_checksum_buffer(Ecma119Image *target, int flag)
{
@ -1095,7 +1190,7 @@ int write_head_part2(Ecma119Image *target, int *write_count, int flag)
if (target->partition_offset <= 0)
return ISO_SUCCESS;
/* Write padding up to target->partition_offset + 16 */
/* Write multi-session padding up to target->partition_offset + 16 */
memset(buf, 0, 2048);
for(; *write_count < target->partition_offset + 16; (*write_count)++) {
res = iso_write(target, buf, BLOCK_SIZE);
@ -1513,6 +1608,8 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
#endif /* Libisofs_with_libjtE */
target->tail_blocks = opts->tail_blocks;
/*
* 2. Based on those options, create needed writers: iso, joliet...
* Each writer inits its structures and stores needed info into
@ -1531,7 +1628,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
}
/* the number of writers is dependent of the extensions */
nwriters = 1 + 1 + 1; /* ECMA-119 + padding + files */
nwriters = 1 + 1 + 1; /* ECMA-119 + multi-session padding + files */
if (target->eltorito) {
nwriters++;
@ -1542,7 +1639,8 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
if (target->iso1999) {
nwriters++;
}
if (target->tail_blocks > 0)
nwriters++;
if ((target->md5_file_checksums & 1) || target->md5_session_checksum) {
nwriters++;
image_checksums_mad = 1; /* from here on the loaded checksums are
@ -1605,7 +1703,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
* Create the writer for possible padding to ensure that in case of image
* growing we can safely overwrite the first 64 KiB of image.
*/
ret = pad_writer_create(target);
ret = mspad_writer_create(target);
if (ret < 0) {
goto target_cleanup;
}
@ -1616,6 +1714,15 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
goto target_cleanup;
}
file_src_writer_index = target->nwriters - 1;
/* IMPORTANT: This must be the last writer before the checksum writer */
if (target->tail_blocks > 0) {
ret = zero_writer_create(target, target->tail_blocks);
if (ret < 0)
goto target_cleanup;
}
if ((target->md5_file_checksums & 1) || target->md5_session_checksum) {
ret = checksum_writer_create(target);
if (ret < 0)
@ -2063,6 +2170,8 @@ int iso_write_opts_new(IsoWriteOpts **opts, int profile)
wopts->libjte_handle = NULL;
#endif /* Libisofs_with_libjtE */
wopts->tail_blocks = 0;
*opts = wopts;
return ISO_SUCCESS;
}
@ -2532,4 +2641,9 @@ int iso_write_opts_detach_jte(IsoWriteOpts *opts, void **libjte_handle)
#endif /* Libisofs_with_libjtE */
}
int iso_write_opts_set_tail_blocks(IsoWriteOpts *opts, uint32_t num_blocks)
{
opts->tail_blocks = num_blocks;
return ISO_SUCCESS;
}

View File

@ -330,6 +330,10 @@ struct iso_write_opts {
struct libjte_env *libjte_handle;
#endif /* Libisofs_with_libjtE */
/* A trailing padding of zero bytes which belongs to the image
*/
uint32_t tail_blocks;
};
typedef struct ecma119_image Ecma119Image;
@ -499,7 +503,7 @@ struct ecma119_image
* file data is written in the first 64 KiB, that are the bytes we usually
* overwrite.
*/
uint32_t pad_blocks;
uint32_t mspad_blocks;
size_t nwriters;
IsoImageWriter **writers;
@ -577,6 +581,7 @@ struct ecma119_image
struct libjte_env *libjte_handle;
#endif /* Libisofs_with_libjtE */
uint32_t tail_blocks;
};
#define BP(a,b) [(b) - (a) + 1]

View File

@ -1887,6 +1887,29 @@ int iso_write_opts_attach_jte(IsoWriteOpts *opts, void *libjte_handle);
int iso_write_opts_detach_jte(IsoWriteOpts *opts, void **libjte_handle);
/**
* Cause a number of blocks with zero bytes to be written after the payload
* data, but before the eventual checksum data. Unlike libburn tail padding,
* these blocks are counted as part of the image and covered by eventual
* image checksums.
* A reason for such padding can be the wish to prevent the Linux read-ahead
* bug by sacrificial data which still belong to image and Jigdo template.
* Normally such padding would be the job of the burn program which should know
* that it is needed with CD write type TAO if Linux read(2) shall be able
* to read all payload blocks.
* 150 blocks = 300 kB is the traditional sacrifice to the Linux kernel.
* @param opts
* The option set to be manipulated.
* @param num_blocks
* Number of extra 2 kB blocks to be written.
* @return
* ISO_SUCCESS or error
*
* @since 0.6.38
*/
int iso_write_opts_set_tail_blocks(IsoWriteOpts *opts, uint32_t num_blocks);
/**
* Inquire the start address of the file data blocks after having used
* IsoWriteOpts with iso_image_create_burn_source().

View File

@ -286,6 +286,7 @@ iso_write_opts_set_rrip_version_1_10;
iso_write_opts_set_scdbackup_tag;
iso_write_opts_set_sort_files;
iso_write_opts_set_system_area;
iso_write_opts_set_tail_blocks;
iso_zisofs_get_params;
iso_zisofs_get_refcounts;
iso_zisofs_set_params;

View File

@ -299,7 +299,7 @@ const char *iso_error_to_msg(int errcode)
case ISO_LIBJTE_END_FAILED:
return "Failed to finish Jigdo Template Extraction";
case ISO_LIBJTE_FILE_FAILED:
return "Failed process file for Jigdo Template Extraction";
return "Failed to process file for Jigdo Template Extraction";
default:
return "Unknown error";
}