From 69a25c97349498b1da60c229abc979ed5b0fbf8e Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Sat, 2 Oct 2010 22:57:09 +0200 Subject: [PATCH] New API call iso_write_opts_set_tail_blocks() for tail padding inside ISO image --- libisofs/ecma119.c | 150 +++++++++++++++++++++++++++++++++++++----- libisofs/ecma119.h | 7 +- libisofs/libisofs.h | 23 +++++++ libisofs/libisofs.ver | 1 + libisofs/messages.c | 2 +- 5 files changed, 163 insertions(+), 20 deletions(-) diff --git a/libisofs/ecma119.c b/libisofs/ecma119.c index 8260dac..b0c9423 100644 --- a/libisofs/ecma119.c +++ b/libisofs/ecma119.c @@ -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; +} + diff --git a/libisofs/ecma119.h b/libisofs/ecma119.h index ffabb52..d2e9a68 100644 --- a/libisofs/ecma119.h +++ b/libisofs/ecma119.h @@ -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] diff --git a/libisofs/libisofs.h b/libisofs/libisofs.h index 70016d9..a994ab5 100644 --- a/libisofs/libisofs.h +++ b/libisofs/libisofs.h @@ -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(). diff --git a/libisofs/libisofs.ver b/libisofs/libisofs.ver index 4c8aaa6..cd96837 100644 --- a/libisofs/libisofs.ver +++ b/libisofs/libisofs.ver @@ -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; diff --git a/libisofs/messages.c b/libisofs/messages.c index e3102f1..9df3290 100644 --- a/libisofs/messages.c +++ b/libisofs/messages.c @@ -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"; }