Enabled writing of EFI El Torito boot image as EFI System Partition outside
the range of the HFS+ partition.
This commit is contained in:
parent
9882d983b9
commit
55e134fb1c
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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_*/
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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:
|
||||
|
@ -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";
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user