New API call iso_write_opts_set_gpt_with_gaps

This commit is contained in:
Thomas Schmitt 2024-12-16 18:12:29 +01:00
parent b7c1e03ff7
commit 59d10562b1
5 changed files with 109 additions and 7 deletions

View File

@ -4416,6 +4416,16 @@ int iso_write_opts_set_iso_type_guid(IsoWriteOpts *opts, uint8_t guid[16],
return ISO_SUCCESS;
}
int iso_write_opts_set_gpt_with_gaps(IsoWriteOpts *opts, int with_gaps,
int with_gaps_no_sort, int with_gaps_no_iso)
{
opts->iso_gpt_flag &= ~(2 | 4 | 8);
opts->iso_gpt_flag |= (!!with_gaps) << 1;
opts->iso_gpt_flag |= (!!with_gaps_no_sort) << 2;
opts->iso_gpt_flag |= (!!with_gaps_no_iso) << 3;
return ISO_SUCCESS;
}
int iso_write_opts_set_disc_label(IsoWriteOpts *opts, char *label)
{
strncpy(opts->ascii_disc_label, label, ISO_DISC_LABEL_SIZE - 1);

View File

@ -515,6 +515,9 @@ struct iso_write_opts {
*/
uint8_t iso_gpt_type_guid[16];
/* bit0= iso_gpt_type_guid is valid
bit1= gaps in the image coverage are allowed
bit2= with bit1: do not sort GPT partition array by start block
bit3= with bit1: do not create partition 1 for ISO filesystem
*/
int iso_gpt_flag;

View File

@ -2845,6 +2845,41 @@ int iso_write_opts_set_appended_as_gpt(IsoWriteOpts *opts, int gpt);
int iso_write_opts_set_part_type_guid(IsoWriteOpts *opts, int partition_number,
uint8_t guid[16], int valid);
/**
* Control whether the GPT partition table is allowed to leave some parts of
* the emerging ISO image uncovered, whether the partition entries in the
* GPT get sorted by their start block addresses, and whether partition 1
* gets created to represent the ISO 9660 filesystem.
* Default is that the partition entries get sorted and all gaps get filled
* by additional GPT partition entries. Partition 1 is by default created for
* the ISO filesystem if partition offset is 16, no partition 1 was created for
* other reasons, and no other partition overlaps with the range from LBA 16 to
* the end of the ISO 9660 filesystem.
*
* Note that GPT for ISOLINUX isohybrid does not get gaps filled, anyways.
*
* @param opts
* The option set to be manipulated.
* @param with_gaps
* If 0, fill gaps.
* If 1, do not fill gaps.
* @param with_gaps_no_sort
* In case that with_gaps is 1:
* If 0, sort partitions by start block addresses.
* If 1, do not sort partitions.
* @param with_gaps_no_iso
* In case that with_gaps is 1:
* If 0, create partition 1 for the ISO filesystem if possible.
* If 1, do not create partition for the ISO filesystem if not already
* created for other reasons.
* @return
* ISO_SUCCESS or error
*
* @since 1.5.8
*/
int iso_write_opts_set_gpt_with_gaps(IsoWriteOpts *opts, int with_gaps,
int with_gaps_no_sort, int with_gaps_no_iso);
/**
* Control whether partitions created by iso_write_opts_set_partition_img()
* are to be represented in Apple Partition Map.

View File

@ -398,5 +398,6 @@ iso_util_decode_lfa_flags;
iso_util_encode_lfa_flags;
iso_util_get_effective_lfa_mask;
iso_util_get_lfa_masks;
iso_write_opts_set_gpt_with_gaps;
} LIBISOFS6;

View File

@ -1758,15 +1758,66 @@ static int iso_write_gpt(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
if (ret <= 0)
return ret;
if (t->opts->partition_offset == 16 && (t->opts->iso_gpt_flag & 2) &&
!(t->opts->iso_gpt_flag & 8)) {
/* If there is no appended partition number 1, the space between
t->opts->partition_offset and t->vol_space_size is uncovered,
and t->opts->partition_offset == 16:
Create ISO9660 partitition (see below)
*/
for (i = 0; i < t->gpt_req_count; i++) {
if (t->gpt_req[i]->desired_slot == 1)
break;
if (t->gpt_req[i]->start_block < t->vol_space_size * (uint64_t) 4
&&
t->gpt_req[i]->start_block + t->gpt_req[i - 1]->block_count >
t->opts->partition_offset * (uint64_t) 4)
break;
}
if (i >= t->gpt_req_count) {
/* Create ISO 9660 partition */
memset(gpt_name, 0, 72);
type_guid = basic_data_uuid;
eff_gpt_flags= gpt_flags;
sprintf((char *) gpt_name, "ISO9660");
type_guid = basic_data_uuid;
if (t->opts->iso_gpt_flag & 1)
type_guid = t->opts->iso_gpt_type_guid;
if (t->system_area_options & (1 << 16))
eff_gpt_flags|= 4; /* Legacy BIOS bootable */
if (t->system_area_options & (1 << 17))
eff_gpt_flags&= ~(((uint64_t) 1) << 60);/* Not read-only */
iso_ascii_utf_16le(gpt_name);
ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count),
t->opts->partition_offset * (uint64_t) 4,
(t->vol_space_size -
t->opts->partition_offset) * (uint64_t) 4,
type_guid, zero_uuid,
eff_gpt_flags, gpt_name);
if (ret < 0)
return ret;
t->gpt_req[t->gpt_req_count - 1]->desired_slot = 1;
/* Make new partition the first one */
req= t->gpt_req[t->gpt_req_count - 1];
for (i = t->gpt_req_count - 2; i >= 0; i--)
t->gpt_req[i + 1]= t->gpt_req[i];
t->gpt_req[0]= req;
}
}
/* Sort and fill gaps */
/* Sort if not gap filling is disabled or not sorting is disabled */
if (!((t->opts->iso_gpt_flag & 2) && (t->opts->iso_gpt_flag & 4))) {
qsort(t->gpt_req, t->gpt_req_count,
sizeof(struct iso_gpt_partition_request *), cmp_partition_request);
}
/* t->gpt_req_count will grow during the loop */
up_to = t->gpt_req_count + 1;
goal = 0;
part_end = 0;
if (t->opts->part_like_isohybrid)
if (t->opts->part_like_isohybrid || t->opts->iso_gpt_flag & 2)
up_to = 0; /* No gap filling */
for (i = 0; i < up_to; i++) {
@ -1822,9 +1873,11 @@ static int iso_write_gpt(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
t->gpt_req[t->gpt_req_count - 1]->req_status |= 1;
}
}
if (!((t->opts->iso_gpt_flag & 2) && (t->opts->iso_gpt_flag & 4))) {
/* Merge list of gap partitions with list of already sorted entries */
qsort(t->gpt_req, t->gpt_req_count,
sizeof(struct iso_gpt_partition_request *), cmp_partition_request);
}
if ((int) t->gpt_max_entries < t->gpt_req_count)
return ISO_BOOT_TOO_MANY_GPT;