diff --git a/libisofs/ecma119.c b/libisofs/ecma119.c index e018199..d019532 100644 --- a/libisofs/ecma119.c +++ b/libisofs/ecma119.c @@ -1514,7 +1514,12 @@ void *write_function(void *arg) if (target->tree_end_block == 1) { iso_msgs_submit(0, - "Image is most likely damaged. Calculated/written block address mismatch.", + "Image is most likely damaged. Calculated/written tree end address mismatch.", + 0, "FATAL", 0); + } + if (target->bytes_written != target->total_size) { + iso_msgs_submit(0, +"Image is most likely damaged. Calculated/written image end address mismatch.", 0, "FATAL", 0); } @@ -1893,6 +1898,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img) return ISO_OUT_OF_MEM; } target->efi_boot_part_size = 0; + target->efi_boot_part_filesrc = NULL; for (i = 0; i < ISO_MAX_PARTITIONS; i++) { target->appended_partitions[i] = NULL; if (opts->appended_partitions[i] != NULL) { @@ -1924,6 +1930,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img) target->gpt_max_entries = 0; target->gpt_is_computed = 0; + target->filesrc_start = 0; target->filesrc_blocks = 0; /* @@ -2037,7 +2044,6 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img) * If PreP or FAT are desired, it creates MBR partition entries and * surrounding protecting partition entries. * If EFI boot partition is desired, it creates a GPT entry for it. - * >>> It shall learn to grab Ecma119Node instead of external disk files. */ ret = partprepend_writer_create(target); if (ret < 0) diff --git a/libisofs/ecma119.h b/libisofs/ecma119.h index 12c47c3..ada10ce 100644 --- a/libisofs/ecma119.h +++ b/libisofs/ecma119.h @@ -797,6 +797,11 @@ struct ecma119_image #ifdef Libisofs_with_libjtE struct libjte_env *libjte_handle; + + /* Indicates that libjte_begin_data_file() was called and not finished yet + by libjte_end_data_file(). + */ + int jte_begun; #endif /* Libisofs_with_libjtE */ uint32_t tail_blocks; @@ -848,6 +853,7 @@ struct ecma119_image char *efi_boot_partition; uint32_t efi_boot_part_size; + IsoFileSrc *efi_boot_part_filesrc; /* Just a pointer. Do not free. */ /* Messages from gpt_tail_writer_compute_data_blocks() to iso_write_system_area(). @@ -869,6 +875,7 @@ struct ecma119_image This is available before any IsoImageWriter.compute_data_blocks() is called. */ + uint32_t filesrc_start; uint32_t filesrc_blocks; }; diff --git a/libisofs/eltorito.c b/libisofs/eltorito.c index 4d2a647..36d235b 100644 --- a/libisofs/eltorito.c +++ b/libisofs/eltorito.c @@ -1032,7 +1032,7 @@ int el_torito_catalog_file_src_create(Ecma119Image *target, IsoFileSrc **src) } /* fill fields */ - file->prev_img = 0; /* TODO allow copy of old img catalog???? */ + file->no_write = 0; /* TODO allow copy of old img catalog???? */ file->checksum_index = 0; file->nsections = 1; file->sections = calloc(1, sizeof(struct iso_file_section)); @@ -1221,7 +1221,7 @@ int eltorito_writer_free_data(IsoImageWriter *writer) int eltorito_writer_create(Ecma119Image *target) { - int ret, idx; + int ret, idx, outsource_efi = 0; IsoImageWriter *writer; IsoFile *bootimg; IsoFileSrc *src; @@ -1253,6 +1253,9 @@ int eltorito_writer_create(Ecma119Image *target) } } + if (target->efi_boot_partition != NULL) + if (strcmp(target->efi_boot_partition, "--efi-boot-image") == 0) + outsource_efi = 1; for (idx = 0; idx < target->catalog->num_bootimages; idx++) { bootimg = target->catalog->bootimages[idx]->image; ret = iso_file_src_create(target, bootimg, &src); @@ -1263,12 +1266,35 @@ int eltorito_writer_create(Ecma119Image *target) /* For patching an image, it needs to be copied always */ if (target->catalog->bootimages[idx]->isolinux_options & 0x01) { - src->prev_img = 0; + src->no_write = 0; + } + + /* If desired: Recognize first EFI boot image that will be newly + written, and mark it as claimed for being a partition. + */ + if (outsource_efi && + target->catalog->bootimages[idx]->platform_id == 0xef && + src->no_write == 0) { + target->efi_boot_part_filesrc = src; + src->sections[0].block = 0xfffffffe; + ((IsoNode *) bootimg)->hidden |= + LIBISO_HIDE_ON_HFSPLUS | LIBISO_HIDE_ON_FAT; + outsource_efi = 0; } } /* we need the bootable volume descriptor */ target->curblock++; + + if (outsource_efi) { + /* Disable EFI Boot partition and complain */ + free(target->efi_boot_partition); + target->efi_boot_partition = NULL; + iso_msg_submit(target->image->id, ISO_BOOT_NO_EFI_ELTO, 0, +"No newly added El Torito EFI boot image found for exposure as GPT partition"); + return ISO_BOOT_NO_EFI_ELTO; + } + return ISO_SUCCESS; } diff --git a/libisofs/filesrc.c b/libisofs/filesrc.c index d79e25d..3c8ed65 100644 --- a/libisofs/filesrc.c +++ b/libisofs/filesrc.c @@ -68,7 +68,7 @@ int iso_file_src_cmp(const void *n1, const void *n2) int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src) { - int ret; + int ret, i; IsoFileSrc *fsrc; unsigned int fs_id; dev_t dev_id; @@ -88,7 +88,7 @@ int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src) } /* fill key and other atts */ - fsrc->prev_img = file->from_old_session; + fsrc->no_write = (file->from_old_session && img->appendable); if (file->from_old_session && img->appendable) { /* * On multisession discs we keep file sections from old image. @@ -118,6 +118,8 @@ int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src) free(fsrc); return ISO_OUT_OF_MEM; } + for (i = 0; i < fsrc->nsections; i++) + fsrc->sections[i].block = 0; } fsrc->sort_weight = file->sort_weight; fsrc->stream = file->stream; @@ -219,15 +221,15 @@ static int cmp_by_weight(const void *f1, const void *f2) } static -int is_ms_file(void *arg) +int shall_be_written(void *arg) { IsoFileSrc *f = (IsoFileSrc *)arg; - return f->prev_img ? 0 : 1; + return f->no_write ? 0 : 1; } int filesrc_writer_pre_compute(IsoImageWriter *writer) { - size_t i, size; + size_t i, size, is_external; Ecma119Image *t; IsoFileSrc **filelist; int (*inc_item)(void *); @@ -247,7 +249,7 @@ int filesrc_writer_pre_compute(IsoImageWriter *writer) /* on appendable images, ms files shouldn't be included */ if (t->appendable) { - inc_item = is_ms_file; + inc_item = shall_be_written; } else { inc_item = NULL; } @@ -267,8 +269,16 @@ int filesrc_writer_pre_compute(IsoImageWriter *writer) for (i = 0; i < size; ++i) { int extent = 0; IsoFileSrc *file = filelist[i]; + off_t section_size; - off_t section_size = iso_stream_get_size(file->stream); + /* 0xfffffffe in emerging image means that this is an external + partition. Only assess extent sizes but do not count as part + of filesrc_writer output. + */ + is_external = (file->no_write == 0 && + file->sections[0].block == 0xfffffffe); + + section_size = iso_stream_get_size(file->stream); for (extent = 0; extent < file->nsections - 1; ++extent) { file->sections[extent].block = t->filesrc_blocks + extent * (ISO_EXTENT_SIZE / BLOCK_SIZE); @@ -293,6 +303,15 @@ int filesrc_writer_pre_compute(IsoImageWriter *writer) } file->sections[extent].size = (uint32_t)section_size; + /* 0xfffffffe in emerging image means that this is an external + partition. Others will take care of the content data. + */ + if (is_external) { + file->sections[0].block = 0xfffffffe; + file->no_write = 1; /* Ban for filesrc_writer */ + continue; + } + t->filesrc_blocks += DIV_UP(iso_file_src_get_size(file), BLOCK_SIZE); } @@ -316,9 +335,16 @@ int filesrc_writer_compute_data_blocks(IsoImageWriter *writer) t = writer->target; filelist = (IsoFileSrc **) writer->data; + t->filesrc_start = t->curblock; + /* Give all extent addresses their final absolute value */ i = 0; while ((file = filelist[i++]) != NULL) { + + /* Skip external partitions */ + if (file->no_write) + continue; + for (extent = 0; extent < file->nsections; ++extent) { if (file->sections[extent].block == 0xffffffff) file->sections[extent].block = t->empty_file_block; @@ -373,26 +399,245 @@ int filesrc_make_md5(Ecma119Image *t, IsoFileSrc *file, char md5[16], int flag) return iso_stream_make_md5(file->stream, md5, 0); } -static -int filesrc_writer_write_data(IsoImageWriter *writer) +/* name must be NULL or offer at least PATH_MAX characters. + buffer must be NULL or offer at least BLOCK_SIZE characters. +*/ +int iso_filesrc_write_data(Ecma119Image *t, IsoFileSrc *file, + char *name, char *buffer, int flag) { int res, ret, was_error; - size_t i, b; - Ecma119Image *t = NULL; - IsoFileSrc *file; - IsoFileSrc **filelist; - char *name = NULL; - char *buffer = NULL; + char *name_data = NULL; + char *buffer_data = NULL; + size_t b; off_t file_size; uint32_t nblocks; void *ctx= NULL; char md5[16], pre_md5[16]; int pre_md5_valid = 0; IsoStream *stream, *inp; + #ifdef Libisofs_with_libjtE int jte_begun = 0; #endif + if (name == NULL) { + LIBISO_ALLOC_MEM(name_data, char, PATH_MAX); + name = name_data; + } + if (buffer == NULL) { + LIBISO_ALLOC_MEM(buffer_data, char, BLOCK_SIZE); + buffer = buffer_data; + } + + was_error = 0; + file_size = iso_file_src_get_size(file); + nblocks = DIV_UP(file_size, BLOCK_SIZE); + pre_md5_valid = 0; + if (file->checksum_index > 0 && (t->md5_file_checksums & 2)) { + /* Obtain an MD5 of content by a first read pass */ + pre_md5_valid = filesrc_make_md5(t, file, pre_md5, 0); + } + res = filesrc_open(file); + + /* Get file name from end of filter chain */ + for (stream = file->stream; ; stream = inp) { + inp = iso_stream_get_input_stream(stream, 0); + if (inp == NULL) + break; + } + iso_stream_get_file_name(stream, name); + if (res < 0) { + /* + * UPS, very ugly error, the best we can do is just to write + * 0's to image + */ + iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0); + was_error = 1; + res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res, + "File \"%s\" can't be opened. Filling with 0s.", name); + if (res < 0) { + ret = res; /* aborted due to error severity */ + goto ex; + } + memset(buffer, 0, BLOCK_SIZE); + for (b = 0; b < nblocks; ++b) { + res = iso_write(t, buffer, BLOCK_SIZE); + if (res < 0) { + /* ko, writer error, we need to go out! */ + ret = res; + goto ex; + } + } + ret = ISO_SUCCESS; + goto ex; + } else if (res > 1) { + iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0); + was_error = 1; + res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0, + "Size of file \"%s\" has changed. It will be %s", name, + (res == 2 ? "truncated" : "padded with 0's")); + if (res < 0) { + filesrc_close(file); + ret = res; /* aborted due to error severity */ + goto ex; + } + } +#ifdef LIBISOFS_VERBOSE_DEBUG + else { + iso_msg_debug(t->image->id, "Writing file %s", name); + } +#endif + +#ifdef Libisofs_with_libjtE + if (t->libjte_handle != NULL) { + res = libjte_begin_data_file(t->libjte_handle, name, + BLOCK_SIZE, file_size); + if (res <= 0) { + res = iso_libjte_forward_msgs(t->libjte_handle, t->image->id, + ISO_LIBJTE_FILE_FAILED, 0); + if (res < 0) { + filesrc_close(file); + ret = ISO_LIBJTE_FILE_FAILED; + goto ex; + } + } + jte_begun = 1; + } +#endif /* Libisofs_with_libjtE */ + + if (file->checksum_index > 0) { + /* initialize file checksum */ + res = iso_md5_start(&ctx); + if (res <= 0) + file->checksum_index = 0; + } + /* write file contents to image */ + for (b = 0; b < nblocks; ++b) { + int wres; + res = filesrc_read(file, buffer, BLOCK_SIZE); + if (res < 0) { + /* read error */ + break; + } + wres = iso_write(t, buffer, BLOCK_SIZE); + if (wres < 0) { + /* ko, writer error, we need to go out! */ + filesrc_close(file); + ret = wres; + goto ex; + } + if (file->checksum_index > 0) { + /* Add to file checksum */ + if (file_size - b * BLOCK_SIZE > BLOCK_SIZE) + res = BLOCK_SIZE; + else + res = file_size - b * BLOCK_SIZE; + res = iso_md5_compute(ctx, buffer, res); + if (res <= 0) + file->checksum_index = 0; + } + } + + filesrc_close(file); + + if (b < nblocks) { + /* premature end of file, due to error or eof */ + iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0); + was_error = 1; + if (res < 0) { + /* error */ + res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res, + "Read error in file %s.", name); + } else { + /* eof */ + res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0, + "Premature end of file %s.", name); + } + + if (res < 0) { + ret = res; /* aborted due error severity */ + goto ex; + } + + /* fill with 0s */ + iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0, + "Filling with 0"); + memset(buffer, 0, BLOCK_SIZE); + while (b++ < nblocks) { + res = iso_write(t, buffer, BLOCK_SIZE); + if (res < 0) { + /* ko, writer error, we need to go out! */ + ret = res; + goto ex; + } + if (file->checksum_index > 0) { + /* Add to file checksum */ + if (file_size - b * BLOCK_SIZE > BLOCK_SIZE) + res = BLOCK_SIZE; + else + res = file_size - b * BLOCK_SIZE; + res = iso_md5_compute(ctx, buffer, res); + if (res <= 0) + file->checksum_index = 0; + } + } + } + if (file->checksum_index > 0 && + file->checksum_index <= t->checksum_idx_counter) { + /* Obtain checksum and dispose checksum context */ + res = iso_md5_end(&ctx, md5); + if (res <= 0) + file->checksum_index = 0; + if ((t->md5_file_checksums & 2) && pre_md5_valid > 0 && + !was_error) { + if (! iso_md5_match(md5, pre_md5)) { + /* Issue MISHAP event */ + iso_report_errfile(name, ISO_MD5_STREAM_CHANGE, 0, 0); + was_error = 1; + res = iso_msg_submit(t->image->id, ISO_MD5_STREAM_CHANGE,0, + "Content of file '%s' changed while it was written into the image.", + name); + if (res < 0) { + ret = res; /* aborted due to error severity */ + goto ex; + } + } + } + /* Write md5 into checksum buffer at file->checksum_index */ + memcpy(t->checksum_buffer + 16 * file->checksum_index, md5, 16); + } + + ret = ISO_SUCCESS; +ex:; + if (ctx != NULL) /* avoid any memory leak */ + iso_md5_end(&ctx, md5); + +#ifdef Libisofs_with_libjtE + if (jte_begun) { + res = libjte_end_data_file(t->libjte_handle); + iso_libjte_forward_msgs(t->libjte_handle, t->image->id, + ISO_LIBJTE_END_FAILED, 0); + if (res <= 0 && ret >= 0) + ret = ISO_LIBJTE_FILE_FAILED; + } +#endif /* Libisofs_with_libjtE */ + + LIBISO_FREE_MEM(buffer_data); + LIBISO_FREE_MEM(name_data); + return ret; +} + +static +int filesrc_writer_write_data(IsoImageWriter *writer) +{ + int ret; + size_t i; + Ecma119Image *t = NULL; + IsoFileSrc *file; + IsoFileSrc **filelist; + char *name = NULL; + char *buffer = NULL; + if (writer == NULL) { ret = ISO_ASSERT_FAILURE; goto ex; } @@ -416,216 +661,28 @@ int filesrc_writer_write_data(IsoImageWriter *writer) i = 0; while ((file = filelist[i++]) != NULL) { - was_error = 0; - file_size = iso_file_src_get_size(file); - nblocks = DIV_UP(file_size, BLOCK_SIZE); - pre_md5_valid = 0; - if (file->checksum_index > 0 && (t->md5_file_checksums & 2)) { - /* Obtain an MD5 of content by a first read pass */ - pre_md5_valid = filesrc_make_md5(t, file, pre_md5, 0); + if (file->no_write) { + /* Do not write external partitions */ + iso_msg_debug(t->image->id, + "filesrc_writer: Skipping no_write-src [%.f , %.f]", + (double) file->sections[0].block, + (double) (file->sections[0].block - 1 + + (file->sections[0].size + 2047) / BLOCK_SIZE)); + continue; } - res = filesrc_open(file); - - /* Get file name from end of filter chain */ - for (stream = file->stream; ; stream = inp) { - inp = iso_stream_get_input_stream(stream, 0); - if (inp == NULL) - break; - } - iso_stream_get_file_name(stream, name); - if (res < 0) { - /* - * UPS, very ugly error, the best we can do is just to write - * 0's to image - */ - iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0); - was_error = 1; - res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res, - "File \"%s\" can't be opened. Filling with 0s.", name); - if (res < 0) { - ret = res; /* aborted due to error severity */ - goto ex; - } - memset(buffer, 0, BLOCK_SIZE); - for (b = 0; b < nblocks; ++b) { - res = iso_write(t, buffer, BLOCK_SIZE); - if (res < 0) { - /* ko, writer error, we need to go out! */ - ret = res; - goto ex; - } - } - continue; - } else if (res > 1) { - iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0); - was_error = 1; - res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0, - "Size of file \"%s\" has changed. It will be %s", name, - (res == 2 ? "truncated" : "padded with 0's")); - if (res < 0) { - filesrc_close(file); - ret = res; /* aborted due to error severity */ - goto ex; - } - } -#ifdef LIBISOFS_VERBOSE_DEBUG - else { - iso_msg_debug(t->image->id, "Writing file %s", name); - } -#endif - -#ifdef Libisofs_with_libjtE - if (t->libjte_handle != NULL) { - res = libjte_begin_data_file(t->libjte_handle, name, - BLOCK_SIZE, file_size); - if (res <= 0) { - res = iso_libjte_forward_msgs(t->libjte_handle, t->image->id, - ISO_LIBJTE_FILE_FAILED, 0); - if (res < 0) { - filesrc_close(file); - ret = ISO_LIBJTE_FILE_FAILED; - goto ex; - } - } - jte_begun = 1; - } -#endif /* Libisofs_with_libjtE */ - - if (file->checksum_index > 0) { - /* initialize file checksum */ - res = iso_md5_start(&ctx); - if (res <= 0) - file->checksum_index = 0; - } - /* write file contents to image */ - for (b = 0; b < nblocks; ++b) { - int wres; - res = filesrc_read(file, buffer, BLOCK_SIZE); - if (res < 0) { - /* read error */ - break; - } - wres = iso_write(t, buffer, BLOCK_SIZE); - if (wres < 0) { - /* ko, writer error, we need to go out! */ - filesrc_close(file); - ret = wres; - goto ex; - } - if (file->checksum_index > 0) { - /* Add to file checksum */ - if (file_size - b * BLOCK_SIZE > BLOCK_SIZE) - res = BLOCK_SIZE; - else - res = file_size - b * BLOCK_SIZE; - res = iso_md5_compute(ctx, buffer, res); - if (res <= 0) - file->checksum_index = 0; - } - } - - filesrc_close(file); - - if (b < nblocks) { - /* premature end of file, due to error or eof */ - iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0); - was_error = 1; - if (res < 0) { - /* error */ - res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res, - "Read error in file %s.", name); - } else { - /* eof */ - res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0, - "Premature end of file %s.", name); - } - - if (res < 0) { - ret = res; /* aborted due error severity */ - goto ex; - } - - /* fill with 0s */ - iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0, - "Filling with 0"); - memset(buffer, 0, BLOCK_SIZE); - while (b++ < nblocks) { - res = iso_write(t, buffer, BLOCK_SIZE); - if (res < 0) { - /* ko, writer error, we need to go out! */ - ret = res; - goto ex; - } - if (file->checksum_index > 0) { - /* Add to file checksum */ - if (file_size - b * BLOCK_SIZE > BLOCK_SIZE) - res = BLOCK_SIZE; - else - res = file_size - b * BLOCK_SIZE; - res = iso_md5_compute(ctx, buffer, res); - if (res <= 0) - file->checksum_index = 0; - } - } - } - if (file->checksum_index > 0 && - file->checksum_index <= t->checksum_idx_counter) { - /* Obtain checksum and dispose checksum context */ - res = iso_md5_end(&ctx, md5); - if (res <= 0) - file->checksum_index = 0; - if ((t->md5_file_checksums & 2) && pre_md5_valid > 0 && - !was_error) { - if (! iso_md5_match(md5, pre_md5)) { - /* Issue MISHAP event */ - iso_report_errfile(name, ISO_MD5_STREAM_CHANGE, 0, 0); - was_error = 1; - res = iso_msg_submit(t->image->id, ISO_MD5_STREAM_CHANGE,0, - "Content of file '%s' changed while it was written into the image.", - name); - if (res < 0) { - ret = res; /* aborted due to error severity */ - goto ex; - } - } - } - /* Write md5 into checksum buffer at file->checksum_index */ - memcpy(t->checksum_buffer + 16 * file->checksum_index, md5, 16); - } - -#ifdef Libisofs_with_libjtE - if (t->libjte_handle != NULL) { - res = libjte_end_data_file(t->libjte_handle); - if (res <= 0) { - iso_libjte_forward_msgs(t->libjte_handle, t->image->id, - ISO_LIBJTE_FILE_FAILED, 0); - ret = ISO_LIBJTE_FILE_FAILED; - goto ex; - } - jte_begun = 0; - } -#endif /* Libisofs_with_libjtE */ - + ret = iso_filesrc_write_data(t, file, name, buffer, 0); + if (ret < 0) + goto ex; } ret = ISO_SUCCESS; ex:; - if (ctx != NULL) /* avoid any memory leak */ - iso_md5_end(&ctx, md5); - -#ifdef Libisofs_with_libjtE - if (jte_begun && t != NULL) { - libjte_end_data_file(t->libjte_handle); - iso_libjte_forward_msgs(t->libjte_handle, t->image->id, - ISO_LIBJTE_END_FAILED, 0); - } -#endif /* Libisofs_with_libjtE */ - LIBISO_FREE_MEM(buffer); LIBISO_FREE_MEM(name); return ret; } + static int filesrc_writer_free_data(IsoImageWriter *writer) { diff --git a/libisofs/filesrc.h b/libisofs/filesrc.h index ee4c22a..6e77ab9 100644 --- a/libisofs/filesrc.h +++ b/libisofs/filesrc.h @@ -22,12 +22,33 @@ #endif #endif + +/* Abstraction of data file content in the emerging image. +*/ struct Iso_File_Src { - unsigned int prev_img :1; /**< if the file comes from a previous image */ + /* This marks an IsoFileSrc which shall only expose its extent addresses + and sizes but shall not be counted or written by filesrc_writer. + */ + unsigned int no_write :1; + unsigned int checksum_index :31; /** File Sections of the file in the image */ + /* Special sections[0].block values while they are relative + before filesrc_writer_compute_data_blocks(). + Valid only with .no_write == 0: + 0xfffffffe This Iso_File_Src is claimed as external partition. + Others will take care of the content data. + filesrc_writer shall neither count nor write it. + At write_data time it is already converted to + a fileadress between Ecma119Image.ms_block and + Ecma119Image.filesrc_start - 1. + 0xffffffff This is the block to which empty files shall point. + Normal data files have relative addresses from 0 to 0xffffffdf. + They cannot be higher, because mspad_writer forces the absolute + filesrc addresses to start at least at 0x20. + */ struct iso_file_section *sections; int nsections; @@ -101,5 +122,14 @@ int iso_file_src_writer_create(Ecma119Image *target); */ int filesrc_writer_pre_compute(IsoImageWriter *writer); +/** + * Write the content of file into the output stream of t. + * name must be NULL or offer at least PATH_MAX characters of storage. + * buffer must be NULL or offer at least BLOCK_SIZE characters of storage. + * flag is not used yet, submit 0. + */ +int iso_filesrc_write_data(Ecma119Image *t, IsoFileSrc *file, + char *name, char *buffer, int flag); + #endif /*LIBISO_FILESRC_H_*/ diff --git a/libisofs/hfsplus.c b/libisofs/hfsplus.c index 3dcbca7..45553c2 100644 --- a/libisofs/hfsplus.c +++ b/libisofs/hfsplus.c @@ -197,6 +197,12 @@ int set_hfsplus_name(Ecma119Image *t, char *name, HFSPlusNode *node) return ISO_SUCCESS; } + +/* >>> ts B20617 + This should be HFSPlusNode rather than IsoNode in order to have access + to IsoFileSrc.no_write which indicates that the file content will not + be in written the range of filesrc_writer. +*/ static int hfsplus_count_tree(Ecma119Image *t, IsoNode *iso) { diff --git a/libisofs/libisofs.h b/libisofs/libisofs.h index 8a40603..5c70968 100644 --- a/libisofs/libisofs.h +++ b/libisofs/libisofs.h @@ -300,6 +300,11 @@ enum IsoHideNodeFlag { */ LIBISO_HIDE_ON_HFSPLUS = 1 << 4, + /** Hide the node in the FAT tree, if that format is enabled. + @since 1.2.4 + */ + LIBISO_HIDE_ON_FAT = 1 << 5, + /** With IsoNode and IsoBoot: Write data content even if the node is * not visible in any tree. * With directory nodes : Write data content of IsoNode and IsoBoot @@ -7329,6 +7334,10 @@ int iso_image_hfsplus_get_blessed(IsoImage *img, IsoNode ***blessed_nodes, /** Attempt to use an MBR partition entry twice (FAILURE, HIGH, -389) */ #define ISO_BOOT_MBR_COLLISION 0xE830FE7B +/** No suitable El Torito EFI boot image for exposure as GPT partition + (FAILURE, HIGH, -390) */ +#define ISO_BOOT_NO_EFI_ELTO 0xE830FE7A + /* Internal developer note: diff --git a/libisofs/messages.c b/libisofs/messages.c index 46635e4..bc4cb65 100644 --- a/libisofs/messages.c +++ b/libisofs/messages.c @@ -488,6 +488,8 @@ const char *iso_error_to_msg(int errcode) return "Overlapping MBR partition entries requested"; case ISO_BOOT_MBR_COLLISION: return "Attempt to use an MBR partition entry twice"; + case ISO_BOOT_NO_EFI_ELTO: + return "No suitable El Torito EFI boot image for exposure as GPT partition"; default: return "Unknown error"; } diff --git a/libisofs/system_area.c b/libisofs/system_area.c index d39930b..3ecc882 100644 --- a/libisofs/system_area.c +++ b/libisofs/system_area.c @@ -2017,7 +2017,8 @@ int gpt_tail_writer_create(Ecma119Image *target) static int partprepend_writer_compute_data_blocks(IsoImageWriter *writer) { Ecma119Image *t; - int ret, will_have_gpt = 0, with_chrp = 0; + IsoFileSrc *src; + int ret, will_have_gpt = 0, with_chrp = 0, i; static uint8_t zero_uuid[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static uint64_t gpt_flags = (((uint64_t) 1) << 60) | 1; uint8_t gpt_name[72]; @@ -2038,10 +2039,23 @@ static int partprepend_writer_compute_data_blocks(IsoImageWriter *writer) will_have_gpt = 1; if (t->efi_boot_partition != NULL) { - ret = compute_partition_size(t->efi_boot_partition, - &(t->efi_boot_part_size), 0); - if (ret < 0) - return ret; + if (t->efi_boot_part_filesrc != NULL) { + /* A file in the emerging ISO image shall store its content + as prepended partition. + Install absolute block addresses and determine partition size. + */ + src = t->efi_boot_part_filesrc; + t->efi_boot_part_size = 0; + for (i = 0; i < src->nsections; i++) { + src->sections[i].block = t->curblock + t->efi_boot_part_size; + t->efi_boot_part_size += (src->sections[i].size + 2047) / 2048; + } + } else { + ret = compute_partition_size(t->efi_boot_partition, + &(t->efi_boot_part_size), 0); + if (ret < 0) + return ret; + } memset(gpt_name, 0, 72); strcpy((char *) gpt_name, "EFI boot partition"); poor_man_s_utf_16le(gpt_name); @@ -2108,8 +2122,14 @@ static int partprepend_writer_write_data(IsoImageWriter *writer) t = writer->target; if (t->efi_boot_partition != NULL && t->efi_boot_part_size) { - ret = iso_write_partition_file(t, t->efi_boot_partition, (uint32_t) 0, - t->efi_boot_part_size, 0); + + if (t->efi_boot_part_filesrc != NULL) { + ret = iso_filesrc_write_data(t, t->efi_boot_part_filesrc, + NULL, NULL, 0); + } else { + ret = iso_write_partition_file(t, t->efi_boot_partition, + (uint32_t) 0, t->efi_boot_part_size, 0); + } if (ret < 0) return ret; }