From f3c27e681f4086b734599e0a76841a599d889fef Mon Sep 17 00:00:00 2001 From: Vreixo Formoso Date: Sat, 5 Jan 2008 03:16:33 +0100 Subject: [PATCH] Improve growing by padding the image, if needed. The padding ensures first 64 KiB can be overwritten without data lost if we grow the image. --- src/ecma119.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++-- src/ecma119.h | 15 ++++++++ 2 files changed, 108 insertions(+), 2 deletions(-) diff --git a/src/ecma119.c b/src/ecma119.c index fcdfd93..27e6739 100644 --- a/src/ecma119.c +++ b/src/ecma119.c @@ -647,6 +647,87 @@ int ecma119_writer_create(Ecma119Image *target) return ISO_SUCCESS; } +/** compute how many padding bytes are needed */ +static +int pad_writer_compute_data_blocks(IsoImageWriter *writer) +{ + Ecma119Image *target; + + if (writer == NULL) { + return ISO_MEM_ERROR; + } + + target = writer->target; + if (target->curblock < 32) { + target->pad_blocks = 32 - target->curblock; + target->curblock = 32; + } + return ISO_SUCCESS; +} + +static +int pad_writer_write_vol_desc(IsoImageWriter *writer) +{ + /* nothing to do */ + return ISO_SUCCESS; +} +static +int pad_writer_write_data(IsoImageWriter *writer) +{ + int ret; + Ecma119Image *t; + uint32_t pad[BLOCK_SIZE]; + size_t i; + + if (writer == NULL) { + return ISO_MEM_ERROR; + } + t = writer->target; + + if (t->pad_blocks == 0) { + return ISO_SUCCESS; + } + + memset(pad, 0, BLOCK_SIZE); + for (i = 0; i < t->pad_blocks; ++i) { + ret = iso_write(t, pad, BLOCK_SIZE); + if (ret < 0) { + return ret; + } + } + + return ISO_SUCCESS; +} + +static +int pad_writer_free_data(IsoImageWriter *writer) +{ + /* nothing to do */ + return ISO_SUCCESS; +} + +static +int pad_writer_create(Ecma119Image *target) +{ + IsoImageWriter *writer; + + writer = malloc(sizeof(IsoImageWriter)); + if (writer == NULL) { + return ISO_MEM_ERROR; + } + + 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->data = NULL; + writer->target = target; + + /* add this writer to image */ + target->writers[target->nwriters++] = writer; + return ISO_SUCCESS; +} + static void *write_function(void *arg) { @@ -717,7 +798,7 @@ void *write_function(void *arg) static int ecma119_image_new(IsoImage *src, Ecma119WriteOpts *opts, Ecma119Image **img) { - int ret, i, voldesc_size; + int ret, i, voldesc_size, nwriters; Ecma119Image *target; /* 1. Allocate target and copy opts there */ @@ -788,7 +869,8 @@ int ecma119_image_new(IsoImage *src, Ecma119WriteOpts *opts, Ecma119Image **img) target->curblock = target->ms_block + 16; /* the number of writers is dependent of the extensions */ - target->writers = malloc(2 * sizeof(void*)); + nwriters = 1 + 1 + 1; /* ECMA-119 + padding + files */ + target->writers = malloc(nwriters * sizeof(void*)); if (target->writers == NULL) { iso_image_unref(src); free(target); @@ -806,6 +888,15 @@ int ecma119_image_new(IsoImage *src, Ecma119WriteOpts *opts, Ecma119Image **img) /* Volume Descriptor Set Terminator */ target->curblock++; + /* + * Create the writer for possible padding to ensure that in case of image + * growing we can safety overwrite the first 64 KiB of image. + */ + ret = pad_writer_create(target); + if (ret < 0) { + goto target_cleanup; + } + /* create writer for file contents */ ret = iso_file_src_writer_create(target); if (ret < 0) { diff --git a/src/ecma119.h b/src/ecma119.h index d0bb207..ca7f995 100644 --- a/src/ecma119.h +++ b/src/ecma119.h @@ -93,6 +93,21 @@ struct ecma119_image uint32_t l_path_table_pos; uint32_t m_path_table_pos; + /* + * Number of pad blocks that we need to write. Padding blocks are blocks + * filled by 0s that we put between the directory structures and the file + * data. These padding blocks are added by libisofs to improve the handling + * of image growing. The idea is that the first blocks in the image are + * overwritten with the volume descriptors of the new image. These first + * blocks usually correspond to the volume descriptors and directory + * structure of the old image, and can be safety overwritten. However, + * with very small images they might correspond to valid data. To ensure + * this never happens, what we do is to add padding bytes, to ensure no + * file data is written in the first 64 KiB, that are the bytes we usually + * overwrite. + */ + uint32_t pad_blocks; + size_t nwriters; IsoImageWriter **writers;