Enabled writing of EFI El Torito boot image as EFI System Partition outside

the range of the HFS+ partition.
This commit is contained in:
Thomas Schmitt 2012-06-18 10:06:16 +02:00
parent 9882d983b9
commit 55e134fb1c
9 changed files with 391 additions and 228 deletions

View File

@ -1514,7 +1514,12 @@ void *write_function(void *arg)
if (target->tree_end_block == 1) { if (target->tree_end_block == 1) {
iso_msgs_submit(0, 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); 0, "FATAL", 0);
} }
@ -1893,6 +1898,7 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
return ISO_OUT_OF_MEM; return ISO_OUT_OF_MEM;
} }
target->efi_boot_part_size = 0; target->efi_boot_part_size = 0;
target->efi_boot_part_filesrc = NULL;
for (i = 0; i < ISO_MAX_PARTITIONS; i++) { for (i = 0; i < ISO_MAX_PARTITIONS; i++) {
target->appended_partitions[i] = NULL; target->appended_partitions[i] = NULL;
if (opts->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_max_entries = 0;
target->gpt_is_computed = 0; target->gpt_is_computed = 0;
target->filesrc_start = 0;
target->filesrc_blocks = 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 * If PreP or FAT are desired, it creates MBR partition entries and
* surrounding protecting partition entries. * surrounding protecting partition entries.
* If EFI boot partition is desired, it creates a GPT entry for it. * 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); ret = partprepend_writer_create(target);
if (ret < 0) if (ret < 0)

View File

@ -797,6 +797,11 @@ struct ecma119_image
#ifdef Libisofs_with_libjtE #ifdef Libisofs_with_libjtE
struct libjte_env *libjte_handle; 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 */ #endif /* Libisofs_with_libjtE */
uint32_t tail_blocks; uint32_t tail_blocks;
@ -848,6 +853,7 @@ struct ecma119_image
char *efi_boot_partition; char *efi_boot_partition;
uint32_t efi_boot_part_size; 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 /* Messages from gpt_tail_writer_compute_data_blocks() to
iso_write_system_area(). iso_write_system_area().
@ -869,6 +875,7 @@ struct ecma119_image
This is available before any IsoImageWriter.compute_data_blocks() This is available before any IsoImageWriter.compute_data_blocks()
is called. is called.
*/ */
uint32_t filesrc_start;
uint32_t filesrc_blocks; uint32_t filesrc_blocks;
}; };

View File

@ -1032,7 +1032,7 @@ int el_torito_catalog_file_src_create(Ecma119Image *target, IsoFileSrc **src)
} }
/* fill fields */ /* 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->checksum_index = 0;
file->nsections = 1; file->nsections = 1;
file->sections = calloc(1, sizeof(struct iso_file_section)); 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 eltorito_writer_create(Ecma119Image *target)
{ {
int ret, idx; int ret, idx, outsource_efi = 0;
IsoImageWriter *writer; IsoImageWriter *writer;
IsoFile *bootimg; IsoFile *bootimg;
IsoFileSrc *src; 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++) { for (idx = 0; idx < target->catalog->num_bootimages; idx++) {
bootimg = target->catalog->bootimages[idx]->image; bootimg = target->catalog->bootimages[idx]->image;
ret = iso_file_src_create(target, bootimg, &src); 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 */ /* For patching an image, it needs to be copied always */
if (target->catalog->bootimages[idx]->isolinux_options & 0x01) { 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 */ /* we need the bootable volume descriptor */
target->curblock++; 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; return ISO_SUCCESS;
} }

View File

@ -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 iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
{ {
int ret; int ret, i;
IsoFileSrc *fsrc; IsoFileSrc *fsrc;
unsigned int fs_id; unsigned int fs_id;
dev_t dev_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 */ /* 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) { if (file->from_old_session && img->appendable) {
/* /*
* On multisession discs we keep file sections from old image. * 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); free(fsrc);
return ISO_OUT_OF_MEM; return ISO_OUT_OF_MEM;
} }
for (i = 0; i < fsrc->nsections; i++)
fsrc->sections[i].block = 0;
} }
fsrc->sort_weight = file->sort_weight; fsrc->sort_weight = file->sort_weight;
fsrc->stream = file->stream; fsrc->stream = file->stream;
@ -219,15 +221,15 @@ static int cmp_by_weight(const void *f1, const void *f2)
} }
static static
int is_ms_file(void *arg) int shall_be_written(void *arg)
{ {
IsoFileSrc *f = (IsoFileSrc *)arg; IsoFileSrc *f = (IsoFileSrc *)arg;
return f->prev_img ? 0 : 1; return f->no_write ? 0 : 1;
} }
int filesrc_writer_pre_compute(IsoImageWriter *writer) int filesrc_writer_pre_compute(IsoImageWriter *writer)
{ {
size_t i, size; size_t i, size, is_external;
Ecma119Image *t; Ecma119Image *t;
IsoFileSrc **filelist; IsoFileSrc **filelist;
int (*inc_item)(void *); int (*inc_item)(void *);
@ -247,7 +249,7 @@ int filesrc_writer_pre_compute(IsoImageWriter *writer)
/* on appendable images, ms files shouldn't be included */ /* on appendable images, ms files shouldn't be included */
if (t->appendable) { if (t->appendable) {
inc_item = is_ms_file; inc_item = shall_be_written;
} else { } else {
inc_item = NULL; inc_item = NULL;
} }
@ -267,8 +269,16 @@ int filesrc_writer_pre_compute(IsoImageWriter *writer)
for (i = 0; i < size; ++i) { for (i = 0; i < size; ++i) {
int extent = 0; int extent = 0;
IsoFileSrc *file = filelist[i]; 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) { for (extent = 0; extent < file->nsections - 1; ++extent) {
file->sections[extent].block = t->filesrc_blocks + extent * file->sections[extent].block = t->filesrc_blocks + extent *
(ISO_EXTENT_SIZE / BLOCK_SIZE); (ISO_EXTENT_SIZE / BLOCK_SIZE);
@ -293,6 +303,15 @@ int filesrc_writer_pre_compute(IsoImageWriter *writer)
} }
file->sections[extent].size = (uint32_t)section_size; 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); 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; t = writer->target;
filelist = (IsoFileSrc **) writer->data; filelist = (IsoFileSrc **) writer->data;
t->filesrc_start = t->curblock;
/* Give all extent addresses their final absolute value */ /* Give all extent addresses their final absolute value */
i = 0; i = 0;
while ((file = filelist[i++]) != NULL) { while ((file = filelist[i++]) != NULL) {
/* Skip external partitions */
if (file->no_write)
continue;
for (extent = 0; extent < file->nsections; ++extent) { for (extent = 0; extent < file->nsections; ++extent) {
if (file->sections[extent].block == 0xffffffff) if (file->sections[extent].block == 0xffffffff)
file->sections[extent].block = t->empty_file_block; 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); return iso_stream_make_md5(file->stream, md5, 0);
} }
static /* name must be NULL or offer at least PATH_MAX characters.
int filesrc_writer_write_data(IsoImageWriter *writer) 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; int res, ret, was_error;
size_t i, b; char *name_data = NULL;
Ecma119Image *t = NULL; char *buffer_data = NULL;
IsoFileSrc *file; size_t b;
IsoFileSrc **filelist;
char *name = NULL;
char *buffer = NULL;
off_t file_size; off_t file_size;
uint32_t nblocks; uint32_t nblocks;
void *ctx= NULL; void *ctx= NULL;
char md5[16], pre_md5[16]; char md5[16], pre_md5[16];
int pre_md5_valid = 0; int pre_md5_valid = 0;
IsoStream *stream, *inp; IsoStream *stream, *inp;
#ifdef Libisofs_with_libjtE #ifdef Libisofs_with_libjtE
int jte_begun = 0; int jte_begun = 0;
#endif #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) { if (writer == NULL) {
ret = ISO_ASSERT_FAILURE; goto ex; ret = ISO_ASSERT_FAILURE; goto ex;
} }
@ -416,216 +661,28 @@ int filesrc_writer_write_data(IsoImageWriter *writer)
i = 0; i = 0;
while ((file = filelist[i++]) != NULL) { while ((file = filelist[i++]) != NULL) {
was_error = 0; if (file->no_write) {
file_size = iso_file_src_get_size(file); /* Do not write external partitions */
nblocks = DIV_UP(file_size, BLOCK_SIZE); iso_msg_debug(t->image->id,
pre_md5_valid = 0; "filesrc_writer: Skipping no_write-src [%.f , %.f]",
if (file->checksum_index > 0 && (t->md5_file_checksums & 2)) { (double) file->sections[0].block,
/* Obtain an MD5 of content by a first read pass */ (double) (file->sections[0].block - 1 +
pre_md5_valid = filesrc_make_md5(t, file, pre_md5, 0); (file->sections[0].size + 2047) / BLOCK_SIZE));
continue;
} }
res = filesrc_open(file); ret = iso_filesrc_write_data(t, file, name, buffer, 0);
if (ret < 0)
/* Get file name from end of filter chain */ goto ex;
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_SUCCESS; ret = ISO_SUCCESS;
ex:; 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(buffer);
LIBISO_FREE_MEM(name); LIBISO_FREE_MEM(name);
return ret; return ret;
} }
static static
int filesrc_writer_free_data(IsoImageWriter *writer) int filesrc_writer_free_data(IsoImageWriter *writer)
{ {

View File

@ -22,12 +22,33 @@
#endif #endif
#endif #endif
/* Abstraction of data file content in the emerging image.
*/
struct Iso_File_Src 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; unsigned int checksum_index :31;
/** File Sections of the file in the image */ /** 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; struct iso_file_section *sections;
int nsections; int nsections;
@ -101,5 +122,14 @@ int iso_file_src_writer_create(Ecma119Image *target);
*/ */
int filesrc_writer_pre_compute(IsoImageWriter *writer); 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_*/ #endif /*LIBISO_FILESRC_H_*/

View File

@ -197,6 +197,12 @@ int set_hfsplus_name(Ecma119Image *t, char *name, HFSPlusNode *node)
return ISO_SUCCESS; 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 static
int hfsplus_count_tree(Ecma119Image *t, IsoNode *iso) int hfsplus_count_tree(Ecma119Image *t, IsoNode *iso)
{ {

View File

@ -300,6 +300,11 @@ enum IsoHideNodeFlag {
*/ */
LIBISO_HIDE_ON_HFSPLUS = 1 << 4, 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 /** With IsoNode and IsoBoot: Write data content even if the node is
* not visible in any tree. * not visible in any tree.
* With directory nodes : Write data content of IsoNode and IsoBoot * 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) */ /** Attempt to use an MBR partition entry twice (FAILURE, HIGH, -389) */
#define ISO_BOOT_MBR_COLLISION 0xE830FE7B #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: /* Internal developer note:

View File

@ -488,6 +488,8 @@ const char *iso_error_to_msg(int errcode)
return "Overlapping MBR partition entries requested"; return "Overlapping MBR partition entries requested";
case ISO_BOOT_MBR_COLLISION: case ISO_BOOT_MBR_COLLISION:
return "Attempt to use an MBR partition entry twice"; 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: default:
return "Unknown error"; return "Unknown error";
} }

View File

@ -2017,7 +2017,8 @@ int gpt_tail_writer_create(Ecma119Image *target)
static int partprepend_writer_compute_data_blocks(IsoImageWriter *writer) static int partprepend_writer_compute_data_blocks(IsoImageWriter *writer)
{ {
Ecma119Image *t; 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 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; static uint64_t gpt_flags = (((uint64_t) 1) << 60) | 1;
uint8_t gpt_name[72]; uint8_t gpt_name[72];
@ -2038,10 +2039,23 @@ static int partprepend_writer_compute_data_blocks(IsoImageWriter *writer)
will_have_gpt = 1; will_have_gpt = 1;
if (t->efi_boot_partition != NULL) { if (t->efi_boot_partition != NULL) {
ret = compute_partition_size(t->efi_boot_partition, if (t->efi_boot_part_filesrc != NULL) {
&(t->efi_boot_part_size), 0); /* A file in the emerging ISO image shall store its content
if (ret < 0) as prepended partition.
return ret; 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); memset(gpt_name, 0, 72);
strcpy((char *) gpt_name, "EFI boot partition"); strcpy((char *) gpt_name, "EFI boot partition");
poor_man_s_utf_16le(gpt_name); poor_man_s_utf_16le(gpt_name);
@ -2108,8 +2122,14 @@ static int partprepend_writer_write_data(IsoImageWriter *writer)
t = writer->target; t = writer->target;
if (t->efi_boot_partition != NULL && t->efi_boot_part_size) { 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) if (ret < 0)
return ret; return ret;
} }