Browse Source

New API call iso_image_report_system_area()

release-1.5.4.branch
Thomas Schmitt 7 years ago
parent
commit
dd27f579eb
  1. 2
      doc/boot_sectors.txt
  2. 4
      libisofs/ecma119.h
  3. 4
      libisofs/eltorito.c
  4. 6
      libisofs/eltorito.h
  5. 1475
      libisofs/fs_image.c
  6. 3
      libisofs/hfsplus.c
  7. 93
      libisofs/image.c
  8. 124
      libisofs/image.h
  9. 249
      libisofs/libisofs.h
  10. 1
      libisofs/libisofs.ver
  11. 15
      libisofs/make_isohybrid_mbr.c
  12. 2
      libisofs/messages.c
  13. 160
      libisofs/system_area.c
  14. 60
      libisofs/system_area.h
  15. 49
      libisofs/tree.c
  16. 5
      libisofs/tree.h
  17. 31
      libisofs/util.c
  18. 9
      libisofs/util.h

2
doc/boot_sectors.txt

@ -580,7 +580,7 @@ Basic data partition: a2 a0 d0 eb , e5 b9 , 33 44 , 87 c0 68 b6 b7 26 99 c7
HFS+ partition : 00 53 46 48 , 00 00 , aa 11 , aa 11 00 30 65 43 ec ac
EFI System partition: 28 73 2a c1 , 1f f8 , d2 11 , ba 4b 00 a0 c9 3e c9 3b
Note that the wikipedia list shows the first 32-bit word and the next two
16-bit words in little-endia interpretation.
16-bit words in little-endian interpretation.
The partition table is an array of entries. Each has a size of 128 bytes.
A partition table entry looks like:

4
libisofs/ecma119.h

@ -768,8 +768,8 @@ struct ecma119_image
/* Allocation block size of HFS+
May be defined to 512 or 2048 before hfsplus_writer_create().
*/
int hfsp_cat_node_size; /* 2 * apm_block_size */
int hfsp_iso_block_fac; /* 2048 / apm_block_size */
int hfsp_cat_node_size; /* 2 * hfsp_block_size */
int hfsp_iso_block_fac; /* 2048 / hfsp_block_size */
/* Apple Partition Map description. To be composed during IsoImageWriter
method ->compute_data_blocks() by calling iso_register_apm_entry().

4
libisofs/eltorito.c

@ -1,6 +1,6 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2010 - 2013 Thomas Schmitt
* Copyright (c) 2010 - 2014 Thomas Schmitt
*
* This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
@ -440,6 +440,8 @@ int create_image(IsoImage *image, const char *image_path,
iso_node_ref(imgfile); /* get our ref */
boot->bootable = 1;
boot->seems_boot_info_table = 0;
boot->seems_grub2_boot_info = 0;
boot->seems_isohybrid_capable = 0;
boot->isolinux_options = 0;
boot->type = boot_media_type;
boot->partition_type = partition_type;

6
libisofs/eltorito.h

@ -1,6 +1,6 @@
/*
* Copyright (c) 2007 Vreixo Formoso
* Copyright (c) 2010 Thomas Schmitt
* Copyright (c) 2010 - 2014 Thomas Schmitt
*
* This file is part of the libisofs project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
@ -59,6 +59,10 @@ struct el_torito_boot_image {
*/
unsigned int seems_boot_info_table:1;
unsigned int seems_grub2_boot_info:1;
/**
* Whether the boot image seems to be capable of isohybrid
*/
unsigned int seems_isohybrid_capable:1;
/**
* isolinux options
* bit 0 -> whether to patch image

1475
libisofs/fs_image.c
File diff suppressed because it is too large
View File

3
libisofs/hfsplus.c

@ -475,7 +475,8 @@ int hfsplus_tail_writer_compute_data_blocks(IsoImageWriter *writer)
t->hfsp_total_blocks = hfsp_curblock - t->hfsp_part_start;
return iso_quick_apm_entry(t, t->hfsp_part_start / block_fac,
return iso_quick_apm_entry(t->apm_req, &(t->apm_req_count),
t->hfsp_part_start / block_fac,
t->hfsp_total_blocks / block_fac +
!!(t->hfsp_total_blocks % block_fac),
"HFSPLUS_Hybrid", "Apple_HFS");

93
libisofs/image.c

@ -22,6 +22,97 @@
#include <string.h>
#include <stdio.h>
int iso_imported_sa_new(struct iso_imported_sys_area **boots, int flag)
{
struct iso_imported_sys_area *b;
*boots = NULL;
b = calloc(1, sizeof(struct iso_imported_sys_area));
if (b == NULL)
return ISO_OUT_OF_MEM;
b->mbr_req = NULL;
b->apm_req = NULL;
b->gpt_req = NULL;
b->gpt_backup_comments = NULL;
b->mips_boot_file_paths = NULL;
b->mips_vd_entries = NULL;
b->sparc_disc_label = NULL;
b->sparc_core_node = NULL;
b->sparc_entries = NULL;
b->hppa_cmdline = NULL;
b->hppa_bootloader = NULL;
b->hppa_kernel_32 = NULL;
b->hppa_kernel_64 = NULL;
b->hppa_ramdisk = NULL;
*boots = b;
return 1;
}
int iso_imported_sa_unref(struct iso_imported_sys_area **boots, int flag)
{
int i;
struct iso_imported_sys_area *b;
b = *boots;
if (b == NULL)
return 2;
if (b->refcount > 0)
b->refcount--;
if (b->refcount > 0)
return 2;
if (b->mbr_req != NULL) {
for (i = 0; i < b->mbr_req_count; i++)
LIBISO_FREE_MEM(b->mbr_req[i]);
LIBISO_FREE_MEM(b->mbr_req);
}
if (b->apm_req != NULL) {
for (i = 0; i < b->apm_req_count; i++)
LIBISO_FREE_MEM(b->apm_req[i]);
LIBISO_FREE_MEM(b->apm_req);
}
if (b->gpt_req != NULL) {
for (i = 0; i < b->gpt_req_count; i++)
LIBISO_FREE_MEM(b->gpt_req[i]);
LIBISO_FREE_MEM(b->gpt_req);
}
LIBISO_FREE_MEM(b->gpt_backup_comments);
if (b->mips_boot_file_paths != NULL) {
for (i = 0; i < b->num_mips_boot_files; i++)
LIBISO_FREE_MEM(b->mips_boot_file_paths[i]);
LIBISO_FREE_MEM(b->mips_boot_file_paths);
}
if (b->mips_vd_entries != NULL) {
for (i = 0; i < b->num_mips_boot_files; i++)
LIBISO_FREE_MEM(b->mips_vd_entries[i]);
LIBISO_FREE_MEM(b->mips_vd_entries);
}
LIBISO_FREE_MEM(b->mipsel_boot_file_path);
LIBISO_FREE_MEM(b->sparc_disc_label);
if (b->sparc_core_node != NULL)
iso_node_unref((IsoNode *) b->sparc_core_node);
LIBISO_FREE_MEM(b->sparc_entries);
LIBISO_FREE_MEM(b->hppa_cmdline);
LIBISO_FREE_MEM(b->hppa_bootloader);
LIBISO_FREE_MEM(b->hppa_kernel_32);
LIBISO_FREE_MEM(b->hppa_kernel_64);
LIBISO_FREE_MEM(b->hppa_ramdisk);
LIBISO_FREE_MEM(b);
*boots = NULL;
return 1;
}
/**
* Create a new image, empty.
*
@ -103,6 +194,7 @@ int iso_image_new(const char *name, IsoImage **image)
for (i = 0; i < ISO_HFSPLUS_BLESS_MAX; i++)
img->hfsplus_blessed[i] = NULL;
img->collision_warnings = 0;
img->imported_sa_info = NULL;
*image = img;
return ISO_SUCCESS;
@ -165,6 +257,7 @@ void iso_image_unref(IsoImage *image)
if (image->system_area_data != NULL)
free(image->system_area_data);
iso_image_free_checksums(image, 0);
iso_imported_sa_unref(&(image->imported_sa_info), 0);
free(image);
}
}

124
libisofs/image.h

@ -212,6 +212,9 @@ struct Iso_Image
/* Counts the name collisions while iso_image_import() */
size_t collision_warnings;
/* Contains the assessment of boot aspects of the loaded image */
struct iso_imported_sys_area *imported_sa_info;
};
@ -263,4 +266,125 @@ int iso_image_set_pvd_times(IsoImage *image,
char *creation_time, char *modification_time,
char *expiration_time, char *effective_time);
/* Collects boot block information obtained from the system area of
imported images
*/
struct iso_imported_sys_area {
int refcount;
/* Whether there was some System Area data at all */
int is_not_zero;
/* Giving the error number if the assessment ended by an error */
int overall_return;
/* Size of the imported ISO image */
uint32_t image_size;
/* see libisofs.h : iso_write_opts_set_system_area() */
int system_area_options;
/* The perceived MBR partitions */
struct iso_mbr_partition_request **mbr_req;
int mbr_req_count;
/* see ecma119.h : struct ecma119_image , struct iso_write_opts */
/* Effective partition table parameter: 1 to 63, 0= disabled/default */
int partition_secs_per_head;
/* 1 to 255, 0= disabled/default */
int partition_heads_per_cyl;
/* see ecma119.h : struct iso_write_opts */
uint32_t partition_offset;
/* 2048-byte start LBA and block count of PreP partition */
uint32_t prep_part_start;
uint32_t prep_part_size;
/* see ecma119.h : struct ecma119_image */
struct iso_apm_partition_request **apm_req;
int apm_req_count;
int apm_req_flags;
/* Number of found "GapNN", "ISO9660_data" partitions in APM */
int apm_gap_count;
/* see ecma119.h : struct iso_write_opts */
int apm_block_size;
/* >>> see ecma119.h : struct iso_write_opts */
int hfsp_block_size;
/* see ecma119.h : struct ecma119_image */
struct iso_gpt_partition_request **gpt_req;
int gpt_req_count;
int gpt_req_flags;
/* see ecma119.h : struct ecma119_image */
uint8_t gpt_disk_guid[16];
/* Start of GPT entries in System Area, block size 512 */
uint64_t gpt_part_start;
uint32_t gpt_max_entries;
uint64_t gpt_first_lba;
uint64_t gpt_last_lba;
uint64_t gpt_backup_lba;
char *gpt_backup_comments;
uint32_t gpt_head_crc_found;
uint32_t gpt_head_crc_should;
uint32_t gpt_array_crc_found;
uint32_t gpt_array_crc_should;
/* see image.h : struct Iso_Image */
int num_mips_boot_files;
char **mips_boot_file_paths; /* ISO 9660 Rock Ridge Paths */
struct iso_mips_voldir_entry **mips_vd_entries;
/* see ecma119.h : struct ecma119_image */
/* Memorized ELF parameters from MIPS Little Endian boot file */
uint32_t mipsel_e_entry;
uint32_t mipsel_p_offset;
uint32_t mipsel_p_vaddr;
uint32_t mipsel_p_filesz;
uint32_t mipsel_seg_start;
char *mipsel_boot_file_path;
/* see image.h : struct Iso_Image */
char *sparc_disc_label;
int sparc_secs_per_head;
int sparc_heads_per_cyl;
struct iso_sun_disk_label_entry *sparc_entries;
int sparc_entry_count;
/* grub2-sparc-core : a node in the ISO image
published at bytes 0x228 to 0x233
*/
uint64_t sparc_grub2_core_adr;
uint32_t sparc_grub2_core_size;
IsoFile *sparc_core_node;
/* see image.h : struct Iso_Image */
int hppa_hdrversion;
char *hppa_cmdline;
uint32_t hppa_kern32_adr;
uint32_t hppa_kern32_len;
uint32_t hppa_kern64_adr;
uint32_t hppa_kern64_len;
uint32_t hppa_ramdisk_adr;
uint32_t hppa_ramdisk_len;
uint32_t hppa_bootloader_adr;
uint32_t hppa_bootloader_len;
uint32_t hppa_ipl_entry;
char *hppa_kernel_32;
char *hppa_kernel_64;
char *hppa_ramdisk;
char *hppa_bootloader;
};
int iso_imported_sa_new(struct iso_imported_sys_area **sa_info, int flag);
int iso_imported_sa_unref(struct iso_imported_sys_area **sa_info, int flag);
#endif /*LIBISO_IMAGE_H_*/

249
libisofs/libisofs.h

@ -2164,14 +2164,15 @@ int iso_write_opts_set_fifo_size(IsoWriteOpts *opts, size_t fifo_size);
* that one partition is defined which begins at the second
* 512-byte block of the image and ends where the image ends.
* This works with and without system_area_data.
* Modern GRUB2 system areas get also treated by bit14. See below.
* bit1= Only with System area type 0 = MBR
* Apply isohybrid MBR patching to the system area.
* This works only with system area data from SYSLINUX plus an
* ISOLINUX boot image (see iso_image_set_boot_image()) and
* only if not bit0 is set.
* ISOLINUX boot image as first submitted boot image
* (see iso_image_set_boot_image()) and only if not bit0 is set.
* bit2-7= System area type
* 0= with bit0 or bit1: MBR
* else: unspecified type which will be used unaltered.
* else: type depends on bits bit10-13: System area sub type
* 1= MIPS Big Endian Volume Header
* @since 0.6.38
* Submit up to 15 MIPS Big Endian boot files by
@ -2216,15 +2217,17 @@ int iso_write_opts_set_fifo_size(IsoWriteOpts *opts, size_t fifo_size);
* @since 1.2.4
* With type 0 = MBR:
* Gets overridden by bit0 and bit1.
* 0 = no particular sub type
* 0 = no particular sub type, use unaltered
* 1 = CHRP: A single MBR partition of type 0x96 covers the
* ISO image. Not compatible with any other feature
* which needs to have own MBR partition entries.
* 2 = generic MBR @since 1.3.8
* bit14= Only with System area type 0 = MBR
* GRUB2 boot provisions:
* @since 1.3.0
* Patch system area at byte 92 to 99 with 512-block address + 1
* of the first boot image file. Little-endian 8-byte.
* Patch system area at byte 0x1b0 to 0x1b7 with
* (512-block address + 4) of the first boot image file.
* Little-endian 8-byte.
* Should be combined with options bit0.
* Will not be in effect if options bit1 is set.
* @param flag
@ -3665,6 +3668,219 @@ void el_torito_patch_isolinux_image(ElToritoBootImage *bootimg);
int iso_image_get_system_area(IsoImage *img, char data[32768],
int *options, int flag);
/**
* The maximum length of a single line in the output of function
* iso_image_report_system_area(). This number includes the trailing 0.
* @since 1.3.8
*/
#define ISO_MAX_SYSAREA_LINE_LENGTH 4096
/**
* Text which describes the output format of iso_image_report_system_area().
* It is publicly defined here only as part of the API description.
* Do not use it as macro in your application but rather call
* iso_image_report_system_area() with flag bit0.
*/
#define ISO_SYSAREA_REPORT_DOC \
"Report format for recognized System Area data:", \
"", \
"No text will be reported if no System Area was loaded or if it was", \
"entirely filled with 0-bytes.", \
"Else there will be at least these two lines:", \
" System area options: hex", \
" see libisofs.h, parameter of iso_write_opts_set_system_area().", \
" System area summary: word ... word", \
" human readable interpretation of system area options and other info", \
" The words are from the set:", \
" { MBR, protective-msdos-label, isohybrid, CHRP, grub2-mbr,", \
" cyl-align-{auto,on,off,all}, PReP, MIPS-Big-Endian,", \
" MIPS-Little-Endian, SUN-SPARC-Disk-Label, HP-PA-PALO,", \
" not-recognized,", \
" GPT, APM }", \
"", \
"If an MBR is detected, with at least one partition entry of non-zero size,", \
"then there may be:", \
" Partition offset : decimal", \
" if not 0 then a second ISO 9660 superblock was found to which MBR", \
" partition 1 is pointing.", \
" ISO image size/512 : decimal", \
" size of ISO image in MBR block units of 512 bytes.", \
" MBR heads per cyl : decimal", \
" conversion factor between MBR C/H/S address and LBA. 0=inconsistent.", \
" MBR secs per head : decimal", \
" conversion factor between MBR C/H/S address and LBA. 0=inconsistent.", \
" MBR partition table: N Status Type Start Blocks", \
" headline for MBR partition table.", \
" MBR partition : X hex hex decimal decimal", \
" gives partition number, status byte, type byte, start block,", \
" and number of blocks. 512 bytes per block.", \
" MBR partition path : X path", \
" the path of a file in the ISO image which begins at the partition", \
" start block of partition X.", \
" PReP boot partition: decimal decimal", \
" gives start block and size of a PReP boot partition in ISO 9660", \
" block units of 2048 bytes.", \
"", \
"GUID Partition Table can coexist with MBR:", \
" GPT : N Info", \
" headline for GPT partition table. The fields are too wide for a", \
" neat table. So they are listed with a partition number and a text.", \
" GPT CRC should be : <hex> to match first 92 GPT header block bytes", \
" GPT CRC found : <hex> matches all 512 bytes of GPT header block", \
" libisofs-1.2.4 to 1.2.8 had a bug with the GPT header CRC. So", \
" libisofs is willing to recognize GPT with the buggy CRC. These", \
" two lines inform that most partition editors will not accept it.", \
" GPT array CRC wrong: should be <hex>, found <hex>", \
" GPT entry arrays are accepted even if their CRC does not match.", \
" In this case, both CRCs are reported by this line.", \
" GPT backup problems: text", \
" reports about inconsistencies between main GPT and backup GPT.", \
" The statements are comma separated:", \
" Implausible header LBA <decimal>", \
" Cannot read header block at 2k LBA <decimal>", \
" Not a GPT 1.0 header of 92 bytes for 128 bytes per entry", \
" Head CRC <hex> wrong. Should be <hex>", \
" Head CRC <hex> wrong. Should be <hex>. Matches all 512 block bytes", \
" Disk GUID differs (<hex_digits>)", \
" Cannot read array block at 2k LBA <decimal>", \
" Array CRC <hex> wrong. Should be <hex>", \
" Entries differ for partitions <decimal> [... <decimal>]", \
" GPT disk GUID : hex_digits", \
" 32 hex digits giving the byte string of the disk's GUID", \
" GPT entry array : decimal decimal word", \
" start block of partition entry array and number of entries. 512 bytes", \
" per block. The word may be \"separated\" if partitions are disjoint,", \
" \"overlapping\" if they are not. In future there may be \"nested\"", \
" as special case where all overlapping partitions are superset and", \
" subset, and \"covering\" as special case of disjoint partitions", \
" covering the whole GPT block range for partitions.", \
" GPT lba range : decimal decimal decimal", \
" addresses of first payload block, last payload block, and of the", \
" GPT backup header block. 512 bytes per block.", \
" GPT partition name : X hex_digits", \
" up to 144 hex digits giving the UTF-16LE name byte string of", \
" partition X. Trailing 16 bit 0-characters are omitted.", \
" GPT partname local : X text", \
" the name of partition X converted to the local character set.", \
" This line may be missing if the name cannot be converted, or is", \
" empty.", \
" GPT partition GUID : X hex_digits", \
" 32 hex digits giving the byte string of the GUID of partition X.", \
" GPT type GUID : X hex_digits", \
" 32 hex digits giving the byte string of the type GUID of partition X.", \
" GPT partition flags: X hex", \
" 64 flag bits of partition X in hex representation.", \
" Known bit meanings are:", \
" bit0 = \"System Partition\" Do not alter.", \
" bit2 = Legacy BIOS bootable (MBR partition type 0x80)", \
" bit60= read-only", \
" GPT start and size : X decimal decimal", \
" start block and number of blocks of partition X. 512 bytes per block.", \
" GPT partition path : X path", \
" the path of a file in the ISO image which begins at the partition", \
" start block of partition X.", \
"", \
"Apple partition map can coexist with MBR:", \
" APM : N Info", \
" headline for human readers.", \
" APM block size : decimal", \
" block size of Apple Partition Map. 512 or 2048. This applies to", \
" start address and size of all partitions in the APM.", \
" APM gap fillers : decimal", \
" tells the number of partitions with name \"Gap[0-9[0-9]]\" and type", \
" \"ISO9660_data\".", \
" APM partition name : X text", \
" the name of partition X. Up to 32 characters.", \
" APM partition type : X text", \
" the type string of partition X. Up to 32 characters.", \
" APM start and size : X decimal decimal", \
" start block and number of blocks of partition X.", \
" APM partition path : X path", \
" the path of a file in the ISO image which begins at the partition", \
" start block of partition X.", \
"", \
"If a MIPS Big Endian Volume Header is detected, there may be:", \
" MIPS-BE volume dir : N Name Block Bytes", \
" headline for human readers.", \
" MIPS-BE boot entry : X upto8chr decimal decimal", \
" tells name, 512-byte block address, and byte count of boot entry X.", \
" MIPS-BE boot path : X path", \
" tells the path to the boot image file in the ISO image which belongs", \
" to the block address given by boot entry X.", \
"", \
"If a DEC Boot Block for MIPS Little Endian is detected, there may be:", \
" MIPS-LE boot map : LoadAddr ExecAddr SegmentSize SegmentStart", \
" headline for human readers.", \
" MIPS-LE boot params: decimal decimal decimal decimal", \
" tells four numbers which are originally derived from the ELF header", \
" of the boot file. The first two are counted in bytes, the other two", \
" are counted in blocks of 512 bytes.", \
" MIPS-LE boot path : path", \
" tells the path to the boot file in the ISO image which belongs to the", \
" address given by SegmentStart.", \
" MIPS-LE elf offset : decimal", \
" tells the relative 512-byte block offset inside the boot file:", \
" SegmentStart - FileStartBlock", \
"", \
"If a SUN SPARC Disk Label is present:", \
" SUN SPARC disklabel: text", \
" tells the disk label text.", \
" SUN SPARC secs/head: decimal", \
" tells the number of sectors per head.", \
" SUN SPARC heads/cyl: decimal", \
" tells the number of heads per cylinder.", \
" SPARC GRUB2 core : decimal decimal", \
" tells byte address and byte count of the GRUB2 SPARC core file.", \
" SPARC GRUB2 path : path", \
" tells the path to the data file in the ISO image which belongs to the", \
" address given by core.", \
"", \
"If a HP-PA PALO boot sector version 4 or 5 is present:", \
" PALO header version: decimal", \
" tells the PALO header version: 4 or 5.", \
" HP-PA cmdline : text", \
" tells the command line for the kernels.", \
" HP-PA boot files : ByteAddr ByteSize Path", \
" headline for human readers.", \
" HP-PA 32-bit kernel: decimal decimal path", \
" tells start byte, byte count, and file path of the 32-bit kernel.", \
" HP-PA 64-bit kernel: decimal decimal path", \
" tells the same for the 64-bit kernel.", \
" HP-PA ramdisk : decimal decimal path", \
" tells the same for the ramdisk file.", \
" HP-PA bootloader : decimal decimal path", \
" tells the same for the bootloader file.", \
"@END_OF_DOC@"
/**
* Obtain a text describing the detected properties of the eventually loaded
* System Area.
* The text will be NULL if no System Area was loaded. It will be empty but
* non-NULL if the System Area was loaded and contains only 0-bytes.
* Else it will consist of lines as descibed in ISO_SYSAREA_REPORT_DOC above.
*
* File paths and other long texts are reported as "(too long to show here)"
* if their length plus preceeding text plus trailing 0-byte exceeds the
* line length limit of ISO_MAX_SYSAREA_LINE_LENGTH bytes.
*
* @param image
* The image to be inquired.
* @param reply
* Will return the allocated result text or NULL. Dispose a non-NULL
* reply by free() when no longer needed.
* Be prepared for a long text with up to ISO_MAX_SYSAREA_LINE_LENGTH
* characters per line.
* @param flag
* Bitfield for control purposes
* bit0= do not report system area but rather reply a copy of
* above text ISO_SYSAREA_REPORT_DOC.
* With this bit it is permissible to submit image as NULL.
* @return
* 1 on success, 0 if no System Area was loaded, < 0 error.
* @since 1.3.8
*/
int iso_image_report_system_area(IsoImage *image, char **reply, int flag);
/**
* Add a MIPS boot file path to the image.
* Up to 15 such files can be written into a MIPS Big Endian Volume Header
@ -4736,8 +4952,8 @@ int iso_file_get_old_image_lba(IsoFile *file, uint32_t *lba, int flag);
* @since 0.6.8
*/
int iso_file_get_old_image_sections(IsoFile *file, int *section_count,
struct iso_file_section **sections,
int flag);
struct iso_file_section **sections,
int flag);
/*
* Like iso_file_get_old_image_lba(), but take an IsoNode.
@ -5361,7 +5577,7 @@ int iso_ring_buffer_get_status(struct burn_source *b, size_t *size,
*
* @param queue_severity Gives the minimum limit for messages to be queued.
* Default: "NEVER". If you queue messages then you
* must consume them by iso_msgs_obtain().
* must consume them by iso_obtain_msgs().
* @param print_severity Does the same for messages to be printed directly
* to stderr.
* @param print_id A text prefix to be printed before the message.
@ -7209,13 +7425,14 @@ int iso_image_hfsplus_get_blessed(IsoImage *img, IsoNode ***blessed_nodes,
* @param flag
* Bitfield for control purposes.
* bit0-bit7= Name space
* 0= generic (to_charset is valid,
* 0= generic (output charset is used,
* no reserved characters, no length limits)
* 1= Rock Ridge (to_charset is valid)
* 2= Joliet (to_charset gets overridden by UCS-2 or UTF-16)
* 3= ECMA-119 (to_charset gets overridden by the
* 1= Rock Ridge (output charset is used)
* 2= Joliet (output charset gets overridden by UCS-2 or
* UTF-16)
* 3= ECMA-119 (output charset gets overridden by the
* dull ISO 9660 subset of ASCII)
* 4= HFS+ (to_charset gets overridden by UTF-16BE)
* 4= HFS+ (output charset gets overridden by UTF-16BE)
* bit8= Treat input text as directory name
* (matters for Joliet and ECMA-119)
* bit9= Do not issue error messages
@ -7694,6 +7911,10 @@ int iso_conv_name_chars(IsoWriteOpts *opts, char *name, size_t name_len,
/** HP-PA PALO command line too long (FAILURE, HIGH, -402) */
#define ISO_HPPA_PALO_CMDLEN 0xE830FE6E
/** Problems encountered during inspection of System Area (WARN, HIG, -403) */
#define ISO_SYSAREA_PROBLEMS 0xD030FE6D
/* Internal developer note:
Place new error codes directly above this comment.

1
libisofs/libisofs.ver

@ -116,6 +116,7 @@ iso_image_import;
iso_image_new;
iso_image_ref;
iso_image_remove_boot_image;
iso_image_report_system_area;
iso_image_set_abstract_file_id;
iso_image_set_app_use;
iso_image_set_application_id;

15
libisofs/make_isohybrid_mbr.c

@ -50,7 +50,7 @@ license from above stem licenses, typically from LGPL.
In case its generosity is needed, here is the 2-clause BSD license:
make_isohybrid_mbr.c is copyright 2002-2008 H. Peter Anvin
and 2008-2012 Thomas Schmitt
and 2008-2014 Thomas Schmitt
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
@ -435,9 +435,10 @@ int assess_isohybrid_gpt_apm(Ecma119Image *t, int *gpt_count, int gpt_idx[128],
for (j = 0; j < t->bootsrc[i]->nsections; j++)
block_count += t->bootsrc[i]->sections[j].size / 2048;
ret = iso_quick_gpt_entry(
t, t->bootsrc[i]->sections[0].block,
block_count, uuid, zero_uuid, gpt_flags,
(uint8_t *) gpt_name);
t->gpt_req, &(t->gpt_req_count),
((uint64_t) t->bootsrc[i]->sections[0].block) * 4,
((uint64_t) block_count) * 4,
uuid, zero_uuid, gpt_flags, (uint8_t *) gpt_name);
if (ret < 0)
return ret;
}
@ -449,7 +450,8 @@ int assess_isohybrid_gpt_apm(Ecma119Image *t, int *gpt_count, int gpt_idx[128],
block_count = 0;
for (j = 0; j < t->bootsrc[i]->nsections; j++)
block_count += t->bootsrc[i]->sections[j].size / 2048;
ret = iso_quick_apm_entry(t, t->bootsrc[i]->sections[0].block,
ret = iso_quick_apm_entry(t->apm_req, &(t->apm_req_count),
t->bootsrc[i]->sections[0].block,
block_count, "EFI", "Apple_HFS");
if (ret < 0)
return ret;
@ -466,7 +468,8 @@ int assess_isohybrid_gpt_apm(Ecma119Image *t, int *gpt_count, int gpt_idx[128],
iso_ascii_utf_16le(gpt_name);
/* Let it be open ended. iso_write_gpt() will truncate it as needed. */
block_count = 0xffffffff;
ret = iso_quick_gpt_entry(t, (uint32_t) 0, block_count,
ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count),
(uint64_t) 0, ((uint64_t) block_count) * 4,
basic_data_uuid, zero_uuid, gpt_flags,
(uint8_t *) gpt_name);
if (ret < 0)

2
libisofs/messages.c

@ -515,6 +515,8 @@ const char *iso_error_to_msg(int errcode)
return "HP-PA PALO file is not a data file";
case ISO_HPPA_PALO_CMDLEN:
return "HP-PA PALO command line too long";
case ISO_SYSAREA_PROBLEMS:
return "Problems encountered during inspection of System Area";
default:
return "Unknown error";
}

160
libisofs/system_area.c

@ -902,8 +902,10 @@ static int make_hppa_palo_sector(Ecma119Image *t, uint8_t *buf, int hdrversion,
/* Convenience frontend for iso_register_apm_entry().
name and type are 0-terminated strings.
*/
int iso_quick_apm_entry(Ecma119Image *t,
uint32_t start_block, uint32_t block_count, char *name, char *type)
int iso_quick_apm_entry(struct iso_apm_partition_request **req_array,
int *apm_req_count,
uint32_t start_block, uint32_t block_count,
char *name, char *type)
{
int ret;
struct iso_apm_partition_request *entry;
@ -915,7 +917,7 @@ int iso_quick_apm_entry(Ecma119Image *t,
entry->block_count = block_count;
strncpy((char *) entry->name, name, 32);
strncpy((char *) entry->type, type, 32);
ret = iso_register_apm_entry(t, entry, 0);
ret = iso_register_apm_entry(req_array, apm_req_count, entry, 0);
free(entry);
return ret;
}
@ -924,8 +926,9 @@ int iso_quick_apm_entry(Ecma119Image *t,
/* Convenience frontend for iso_register_gpt_entry().
name has to be already encoded as UTF-16LE.
*/
int iso_quick_gpt_entry(Ecma119Image *t,
uint32_t start_block, uint32_t block_count,
int iso_quick_gpt_entry(struct iso_gpt_partition_request **req_array,
int *gpt_req_count,
uint64_t start_block, uint64_t block_count,
uint8_t type_guid[16], uint8_t partition_guid[16],
uint64_t flags, uint8_t name[72])
{
@ -941,13 +944,14 @@ int iso_quick_gpt_entry(Ecma119Image *t,
memcpy(entry->partition_guid, partition_guid, 16);
entry->flags = flags;
memcpy(entry->name, name, 72);
ret = iso_register_gpt_entry(t, entry, 0);
ret = iso_register_gpt_entry(req_array, gpt_req_count, entry, 0);
free(entry);
return ret;
}
int iso_quick_mbr_entry(Ecma119Image *t,
int iso_quick_mbr_entry(struct iso_mbr_partition_request **req_array,
int *mbr_req_count,
uint64_t start_block, uint64_t block_count,
uint8_t type_byte, uint8_t status_byte,
int desired_slot)
@ -955,7 +959,7 @@ int iso_quick_mbr_entry(Ecma119Image *t,
int ret;
struct iso_mbr_partition_request *entry;
ret = iso_mbr_entry_slot_is_free(t, desired_slot);
ret = iso_mbr_entry_slot_is_free(req_array, *mbr_req_count, desired_slot);
if (ret < 0)
desired_slot = 0;
else if (ret == 0)
@ -969,13 +973,14 @@ int iso_quick_mbr_entry(Ecma119Image *t,
entry->type_byte = type_byte;
entry->status_byte = status_byte;
entry->desired_slot = desired_slot;
ret = iso_register_mbr_entry(t, entry, 0);
ret = iso_register_mbr_entry(req_array, mbr_req_count, entry, 0);
free(entry);
return ret;
}
int iso_mbr_entry_slot_is_free(Ecma119Image *t, int slot)
int iso_mbr_entry_slot_is_free(struct iso_mbr_partition_request **req_array,
int mbr_req_count, int slot)
{
int i;
@ -983,8 +988,8 @@ int iso_mbr_entry_slot_is_free(Ecma119Image *t, int slot)
return -1;
if (slot == 0)
return 1;
for (i = 0; i < t->mbr_req_count; i++)
if (t->mbr_req[i]->desired_slot == slot)
for (i = 0; i < mbr_req_count; i++)
if (req_array[i]->desired_slot == slot)
return 0;
return 1;
}
@ -997,8 +1002,8 @@ static
int cmp_partition_request(const void *f1, const void *f2)
{
struct iso_partition_request {
uint32_t start_block;
uint32_t block_count;
uint64_t start_block;
uint64_t block_count;
} *r1, *r2;
r1 = *((struct iso_partition_request **) f1);
@ -1046,10 +1051,10 @@ static int iso_write_apm_entry(Ecma119Image *t, int apm_block_size,
iso_msb(wpt, (uint32_t) map_entries, 4);
wpt += 4;
/* Physical block start of partition */
iso_msb(wpt, req->start_block * block_fac, 4);
iso_msb(wpt, (uint32_t) (req->start_block * block_fac), 4);
wpt += 4;
/* Physical block count of partition */
iso_msb(wpt, req->block_count * block_fac, 4);
iso_msb(wpt, (uint32_t) (req->block_count * block_fac), 4);
wpt += 4;
/* Partition name */
memcpy(wpt, req->name, 32);
@ -1058,10 +1063,10 @@ static int iso_write_apm_entry(Ecma119Image *t, int apm_block_size,
memcpy(wpt, req->type, 32);
wpt += 32;
/* Logical block start */
iso_msb(wpt, 0, 4);
iso_msb(wpt, (uint32_t) 0, 4);
wpt += 4;
/* Logical block count */
iso_msb(wpt, req->block_count * block_fac, 4);
iso_msb(wpt, (uint32_t) (req->block_count * block_fac), 4);
wpt += 4;
/* Status flags : bit0= entry is valid , bit1= entry is allocated
bit4= partition is readable , bit5= partition is writable
@ -1103,7 +1108,8 @@ static int fill_apm_gaps(Ecma119Image *t, uint32_t img_blocks)
break;
}
if (i >= t->apm_req_count) {
ret = iso_quick_apm_entry(t, 1, 0, "Apple", "Apple_partition_map");
ret = iso_quick_apm_entry(t->apm_req, &(t->apm_req_count),
1, 0, "Apple", "Apple_partition_map");
if (ret < 0)
return ret;
}
@ -1115,7 +1121,7 @@ static int fill_apm_gaps(Ecma119Image *t, uint32_t img_blocks)
up_to = t->apm_req_count + 1;
for (i = 1; i < up_to; i++) {
if (i < up_to - 1)
goal = t->apm_req[i]->start_block;
goal = (uint32_t) t->apm_req[i]->start_block;
else
goal = img_blocks * block_fac;
if (i == 1) {
@ -1141,7 +1147,8 @@ static int fill_apm_gaps(Ecma119Image *t, uint32_t img_blocks)
if (part_end < goal || i == up_to - 1) { /* Always add a final entry */
sprintf(gap_name, "Gap%d", gap_counter);
gap_counter++;
ret = iso_quick_apm_entry(t, part_end, goal - part_end,
ret = iso_quick_apm_entry(t->apm_req, &(t->apm_req_count),
part_end, goal - part_end,
gap_name, "ISO9660_data");
if (ret < 0)
return ret;
@ -1167,15 +1174,18 @@ static int rectify_apm(Ecma119Image *t)
/* <<< ts B20526 : Dummy mock-up */
if (t->apm_req_count <= 0) {
/*
ret = iso_quick_apm_entry(t, 16, 20, "Test1_name_16_20", "Test1_type");
ret = iso_quick_apm_entry(t->apm_req, &(t->apm_req_count),
16, 20, "Test1_name_16_20", "Test1_type");
/ * >>> Caution: Size 90 causes intentional partition overlap error * /
ret = iso_quick_apm_entry(t, 30, 90, "BAD_30_90_BAD", "Test1_type");
ret = iso_quick_apm_entry(t->apm_req, &(t->apm_req_count),
30, 90, "BAD_30_90_BAD", "Test1_type");
*/
ret = iso_quick_apm_entry(t, 30, 20, "Test1_name_30_20", "Test1_type");
ret = iso_quick_apm_entry(t->apm_req, &(t->apm_req_count),
30, 20, "Test1_name_30_20", "Test1_type");
if (ret < 0)
return ret;
ret = iso_quick_apm_entry(t, 100, 400, "Test2_name_100_400",
"Test2_type");
ret = iso_quick_apm_entry(t->apm_req, &(t->apm_req_count),
100, 400, "Test2_name_100_400", "Test2_type");
if (ret < 0)
return ret;
}
@ -1280,10 +1290,12 @@ static int iso_write_mbr(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
/* <<< Dummy mock-up */
if (t->mbr_req_count <= 0) {
ret = iso_quick_mbr_entry(t, (uint64_t) 0, (uint64_t) 0, 0xee, 0, 0);
ret = iso_quick_mbr_entry(t->mbr_req, &(t->mbr_req_count),
(uint64_t) 0, (uint64_t) 0, 0xee, 0, 0);
if (ret < 0)
return ret;
ret = iso_quick_mbr_entry(t, ((uint64_t) 100) * 4, (uint64_t) 0,
ret = iso_quick_mbr_entry(t->mbr_req, &(t->mbr_req_count),
((uint64_t) 100) * 4, (uint64_t) 0,
0x0c, 0x80, 1);
if (ret < 0)
return ret;
@ -1491,8 +1503,8 @@ static int iso_write_gpt(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7
};
uint32_t p_arr_crc = 0, part_end, goal, next_end;
uint64_t start_lba, end_lba;
uint32_t p_arr_crc = 0;
uint64_t start_lba, end_lba, goal, part_end, next_end, backup_end_lba;
int ret, i, gap_counter = 0, up_to;
struct iso_gpt_partition_request *req;
uint8_t gpt_name[72];
@ -1513,12 +1525,12 @@ static int iso_write_gpt(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
if (i < up_to - 1) {
goal = t->gpt_req[i]->start_block;
} else {
goal = img_blocks;
goal = ((uint64_t) img_blocks) * 4;
}
if (i == 0) {
if (goal <= 16)
if (goal <= 16 * 4)
continue;
next_end = 16;
next_end = 16 * 4;
} else {
next_end = t->gpt_req[i - 1]->start_block +
t->gpt_req[i - 1]->block_count;
@ -1528,8 +1540,8 @@ static int iso_write_gpt(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
if (part_end > goal) {
if (!(t->gpt_req_flags & 1)) {
iso_msg_submit(t->image->id, ISO_BOOT_GPT_OVERLAP, 0,
"Program error: GPT partitions %d and %d overlap by %lu blocks",
i - 1, i, part_end - goal);
"Program error: GPT partitions %d and %d overlap by %.f blocks",
i - 1, i, (double) (part_end - goal));
return ISO_BOOT_GPT_OVERLAP;
}
} else if (part_end < goal) {
@ -1537,7 +1549,8 @@ static int iso_write_gpt(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
sprintf((char *) gpt_name, "Gap%d", gap_counter);
iso_ascii_utf_16le(gpt_name);
gap_counter++;
ret = iso_quick_gpt_entry(t, part_end, goal - part_end,
ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count),
part_end, goal - part_end,
basic_data_uuid, zero_uuid,
gpt_flags, gpt_name);
if (ret < 0)
@ -1554,11 +1567,13 @@ static int iso_write_gpt(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
/* Write the GPT entries to buf */
for (i = 0; i < t->gpt_req_count; i++) {
req = t->gpt_req[i];
start_lba = ((uint64_t) req->start_block) * 4;
end_lba = ((uint64_t) req->start_block) + req->block_count;
if (end_lba > t->gpt_backup_end - t->gpt_backup_size)
end_lba = t->gpt_backup_end - t->gpt_backup_size;
end_lba = end_lba * 4 - 1;
start_lba = req->start_block;
end_lba = req->start_block + req->block_count;
backup_end_lba = ((uint64_t) t->gpt_backup_end - t->gpt_backup_size) *
4;
if (end_lba > backup_end_lba)
end_lba = backup_end_lba;
end_lba = end_lba - 1;
iso_write_gpt_entry(t, buf + 512 * t->gpt_part_start + 128 * i,
req->type_guid, req->partition_guid,
start_lba, end_lba, req->flags, req->name);
@ -1929,56 +1944,58 @@ ex:;
}
int iso_register_apm_entry(Ecma119Image *t,
int iso_register_apm_entry(struct iso_apm_partition_request **req_array,
int *apm_req_count,
struct iso_apm_partition_request *req, int flag)
{
struct iso_apm_partition_request *entry;
if (t->apm_req_count >= ISO_APM_ENTRIES_MAX)
if (*apm_req_count >= ISO_APM_ENTRIES_MAX)
return ISO_BOOT_TOO_MANY_APM;
entry = calloc(1, sizeof(struct iso_apm_partition_request));
if (entry == NULL)
return ISO_OUT_OF_MEM;
memcpy(entry, req, sizeof(struct iso_apm_partition_request));
t->apm_req[t->apm_req_count] = entry;
t->apm_req_count++;
req_array[*apm_req_count] = entry;
(*apm_req_count)++;
return ISO_SUCCESS;
}
int iso_register_mbr_entry(Ecma119Image *t,
int iso_register_mbr_entry(struct iso_mbr_partition_request **req_array,
int *mbr_req_count,
struct iso_mbr_partition_request *req, int flag)
{
struct iso_mbr_partition_request *entry;
if (t->mbr_req_count >= ISO_MBR_ENTRIES_MAX)
if (*mbr_req_count >= ISO_MBR_ENTRIES_MAX)
return ISO_BOOT_TOO_MANY_MBR;
entry = calloc(1, sizeof(struct iso_mbr_partition_request));
if (entry == NULL)
return ISO_OUT_OF_MEM;
memcpy(entry, req, sizeof(struct iso_mbr_partition_request));
t->mbr_req[t->mbr_req_count] = entry;
t->mbr_req_count++;
req_array[*mbr_req_count] = entry;
(*mbr_req_count)++;
return ISO_SUCCESS;
}
int iso_register_gpt_entry(Ecma119Image *t,
int iso_register_gpt_entry(struct iso_gpt_partition_request **req_array,
int *gpt_req_count,
struct iso_gpt_partition_request *req, int flag)
{
struct iso_gpt_partition_request *entry;
if (t->gpt_req_count >= ISO_GPT_ENTRIES_MAX)
if (*gpt_req_count >= ISO_GPT_ENTRIES_MAX)
return ISO_BOOT_TOO_MANY_GPT;
entry = calloc(1, sizeof(struct iso_gpt_partition_request));
if (entry == NULL)
return ISO_OUT_OF_MEM;
memcpy(entry, req, sizeof(struct iso_gpt_partition_request));
t->gpt_req[t->gpt_req_count] = entry;
t->gpt_req_count++;
req_array[*gpt_req_count] = entry;
(*gpt_req_count)++;
return ISO_SUCCESS;
}
@ -2185,19 +2202,26 @@ static int precompute_gpt(Ecma119Image *t)
strcpy((char *) gpt_name, "GPT Test 1");
iso_ascii_utf_16le(gpt_name);
/*
ret = iso_quick_gpt_entry(t, 16, 20, hfs_uuid, zero_uuid,
gpt_flags, gpt_name);
ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count),
(uint64_t) (16 * 4), (uint64_t) (20 * 4),
hfs_uuid, zero_uuid, gpt_flags, gpt_name);
/ * Caution: Size 90 causes intentional partition overlap error * /
ret = iso_quick_gpt_entry(t, 30, 90, hfs_uuid, zero_uuid,
ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count),
(uint64_t) (30 * 4), (uint64_t) (90 * 4),
hfs_uuid, zero_uuid,
gpt_flags, gpt_name);
*/
ret = iso_quick_gpt_entry(t, 30, 40, hfs_uuid, zero_uuid,
ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count),
(uint64_t) (30 * 4), (uint64_t) (40 * 4),
hfs_uuid, zero_uuid,
gpt_flags, gpt_name);
if (ret < 0)
return ret;
strcpy((char *) gpt_name, "GPT Test 2");
iso_ascii_utf_16le(gpt_name);
ret = iso_quick_gpt_entry(t, 110, 60, basic_data_uuid, zero_uuid,
ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count),
(uint64_t) (110 * 4), (uint64_t) (60 * 4),
basic_data_uuid, zero_uuid,
gpt_flags, gpt_name);
if (ret < 0)
return ret;
@ -2406,7 +2430,9 @@ static int partprepend_writer_compute_data_blocks(IsoImageWriter *writer)
memset(gpt_name, 0, 72);
strcpy((char *) gpt_name, "EFI boot partition");
iso_ascii_utf_16le(gpt_name);
ret = iso_quick_gpt_entry(t, t->curblock, t->efi_boot_part_size,
ret = iso_quick_gpt_entry(t->gpt_req, &(t->gpt_req_count),
((uint64_t) t->curblock) * 4,
((uint64_t) t->efi_boot_part_size) * 4,
efi_sys_uuid, zero_uuid, gpt_flags, gpt_name);
if (ret < 0)
return ret;
@ -2418,8 +2444,8 @@ static int partprepend_writer_compute_data_blocks(IsoImageWriter *writer)
if (t->opts->prep_partition != NULL || t->opts->fat || will_have_gpt ||
t->mbr_req_count > 0)
return ISO_BOOT_MBR_OVERLAP;
ret = iso_quick_mbr_entry(t, (uint64_t) 0, (uint64_t) 0,
0x96, 0x80, 0);
ret = iso_quick_mbr_entry(t->mbr_req, &(t->mbr_req_count),
(uint64_t) 0, (uint64_t) 0, 0x96, 0x80, 0);
if (ret < 0)
return ret;
return ISO_SUCCESS;
@ -2433,7 +2459,8 @@ static int partprepend_writer_compute_data_blocks(IsoImageWriter *writer)
}
if (t->prep_part_size > 0 || t->opts->fat || will_have_gpt) {
/* Protecting MBR entry for ISO start or whole ISO */
ret = iso_quick_mbr_entry(t, will_have_gpt ? (uint64_t) 1 :
ret = iso_quick_mbr_entry(t->mbr_req, &(t->mbr_req_count),
will_have_gpt ? (uint64_t) 1 :
((uint64_t) t->opts->partition_offset) * 4,
(uint64_t) 0,
will_have_gpt ? 0xee : 0xcd, 0, 0);
@ -2441,7 +2468,8 @@ static int partprepend_writer_compute_data_blocks(IsoImageWriter *writer)
return ret;
}
if (t->prep_part_size > 0) {
ret = iso_quick_mbr_entry(t, ((uint64_t) t->curblock) * 4,
ret = iso_quick_mbr_entry(t->mbr_req, &(t->mbr_req_count),
((uint64_t) t->curblock) * 4,
((uint64_t) t->prep_part_size) * 4,
0x41, 0, 0);
if (ret < 0)
@ -2450,8 +2478,8 @@ static int partprepend_writer_compute_data_blocks(IsoImageWriter *writer)
}
if (t->prep_part_size > 0 || t->opts->fat) {
/* FAT partition or protecting MBR entry for ISO end */
ret = iso_quick_mbr_entry(t, ((uint64_t) t->curblock) * 4,
(uint64_t) 0,
ret = iso_quick_mbr_entry(t->mbr_req, &(t->mbr_req_count),
((uint64_t) t->curblock) * 4, (uint64_t) 0,
t->opts->fat ? 0x0c : 0xcd, 0, 0);
if (ret < 0)
return ret;

60
libisofs/system_area.h

@ -108,13 +108,15 @@ struct iso_mbr_partition_request {
I.e. after the call the submitted storage of req can be disposed or re-used.
Submit 0 as value flag.
*/
int iso_register_mbr_entry(Ecma119Image *t,
int iso_register_mbr_entry(struct iso_mbr_partition_request **req_array,
int *mbr_req_count,
struct iso_mbr_partition_request *req, int flag);
/* Convenience frontend for iso_register_mbr_entry().
name and type are 0-terminated strings, which may get silently truncated.
*/
int iso_quick_mbr_entry(Ecma119Image *t,
int iso_quick_mbr_entry(struct iso_mbr_partition_request **req_array,
int *mbr_req_count,
uint64_t start_block, uint64_t block_count,
uint8_t type_byte, uint8_t status_byte,
int desired_slot);
@ -125,12 +127,13 @@ int iso_quick_mbr_entry(Ecma119Image *t,
Return value is 0 if occupied, 1 if free, and -1 if the slot number is
out of range.
*/
int iso_mbr_entry_slot_is_free(Ecma119Image *t, int slot);
int iso_mbr_entry_slot_is_free(struct iso_mbr_partition_request **req_array,
int mbr_req_count, int slot);
/* The parameter struct for production of a single Apple Partition Map entry.
See also the partial APM description in doc/boot_sectors.txt.
The list of entries is stored in Ecma119Image.apm_req.
The list of entries is stored e.g. in Ecma119Image.apm_req, .apm_req_count.
The size of a block can be chosen by setting Ecma119Image.apm_block_size.
If an entry has start_block <=1, then its block_count will be adjusted
to the final size of the partition map.
@ -144,8 +147,8 @@ struct iso_apm_partition_request {
/* Given in blocks of 2 KiB unless (Ecma119Image.apm_req_flags & 4).
Written to the ISO image according to Ecma119Image.apm_block_size.
*/
uint32_t start_block;
uint32_t block_count;
uint64_t start_block;
uint64_t block_count;
/* All 32 bytes get copied to the system area.
Take care to pad up short strings by 0.
@ -158,14 +161,17 @@ struct iso_apm_partition_request {
I.e. after the call the submitted storage of req can be disposed or re-used.
Submit 0 as value flag.
*/
int iso_register_apm_entry(Ecma119Image *t,
int iso_register_apm_entry(struct iso_apm_partition_request **req_array,
int *apm_req_count,
struct iso_apm_partition_request *req, int flag);
/* Convenience frontend for iso_register_apm_entry().
name and type are 0-terminated strings, which may get silently truncated.
*/
int iso_quick_apm_entry(Ecma119Image *t,
uint32_t start_block, uint32_t block_count, char *name, char *type);
int iso_quick_apm_entry(struct iso_apm_partition_request **req_array,
int *apm_req_count,
uint32_t start_block, uint32_t block_count,
char *name, char *type);
/* CRC-32 as of GPT and Ethernet.
@ -206,11 +212,10 @@ void iso_random_uuid(Ecma119Image *t, uint8_t uuid[16]);
*/
struct iso_gpt_partition_request {
/* Always given in blocks of 2 KiB.
Written to the ISO image in blocks of 512.
/* Always given in blocks of 512 bytes.
*/
uint32_t start_block;
uint32_t block_count;
uint64_t start_block;
uint64_t block_count;
/* The registered GUID which defines the partition type */
uint8_t type_guid[16];
@ -231,20 +236,26 @@ struct iso_gpt_partition_request {
Take care to pad up short strings by 0.
*/
uint8_t name[72];
/* Only if read from imported image: Table index of partition (first = 1)
*/
uint32_t idx;
};
/* Copies the content of req and registers it in t.gpt_req[].
I.e. after the call the submitted storage of req can be disposed or re-used.
Submit 0 as value flag.
*/
int iso_register_gpt_entry(Ecma119Image *t,
int iso_register_gpt_entry(struct iso_gpt_partition_request **req_array,
int *gpt_req_count,
struct iso_gpt_partition_request *req, int flag);
/* Convenience frontend for iso_register_gpt_entry().
name has to be already encoded as UTF-16LE.
*/
int iso_quick_gpt_entry(Ecma119Image *t,
uint32_t start_block, uint32_t block_count,
int iso_quick_gpt_entry(struct iso_gpt_partition_request **req_array,
int *gpt_req_count,
uint64_t start_block, uint64_t block_count,
uint8_t type_guid[16], uint8_t partition_guid[16],
uint64_t flags, uint8_t name[72]);
@ -255,6 +266,23 @@ int iso_write_gpt_header_block(Ecma119Image *t, uint32_t img_blocks,
uint8_t *buf, uint32_t max_entries,
uint32_t part_start, uint32_t p_arr_crc);
/* The description of a loaded MIPS Big Endian Volume Directory Entry
*/
struct iso_mips_voldir_entry {
char name[9];
uint32_t boot_block;
uint32_t boot_bytes;
};
/* The description of a loaded SUN Disk Label partition */
struct iso_sun_disk_label_entry {
int idx;
uint16_t id_tag;
uint16_t permissions;
uint32_t start_cyl;
uint32_t num_blocks;
};
/* Creates the Partition Prepend writer.
*/
int partprepend_writer_create(Ecma119Image *target);

49
libisofs/tree.c

@ -1187,6 +1187,55 @@ ex:;
return path;
}
/* Note: No reference is taken to the found node.
@param flag bit0= recursion
*/
int iso_tree_get_node_of_block(IsoImage *image, IsoDir *dir, uint32_t block,
IsoNode **found, int flag)
{
int ret, section_count, i;
IsoDirIter *iter = NULL;
IsoNode *node;
IsoDir *subdir;
IsoFile *file;
struct iso_file_section *sections = NULL;
if (dir == NULL)
dir = image->root;
ret = iso_dir_get_children(dir, &iter);
while (iso_dir_iter_next(iter, &node) == 1 ) {
if (ISO_NODE_IS_FILE(node)) {
file = (IsoFile *) node;
ret = iso_file_get_old_image_sections(file, &section_count,
&sections, 0);
if (ret <= 0)
continue;
for (i = 0; i < section_count; i++) {
if (sections[i].block <= block &&
block - sections[i].block <
(((off_t) sections[i].size) + 2047) / 2048) {
*found = node;
ret = 1; goto ex;
}
}
free(sections); sections = NULL;
} else if (ISO_NODE_IS_DIR(node)) {
subdir = (IsoDir *) node;
ret = iso_tree_get_node_of_block(image, subdir, block, found, 1);
if (ret != 0)
goto ex;
}
}
ret = 0;
ex:
if (sections != NULL)
free(sections);
return ret;
}
/* ------------------------- tree cloning ------------------------------ */
static

5
libisofs/tree.h

@ -19,4 +19,9 @@
*/
int iso_add_dir_src_rec(IsoImage *image, IsoDir *parent, IsoFileSource *dir);
int iso_tree_get_node_of_block(IsoImage *image, IsoDir *dir, uint32_t block,
IsoNode **found, int flag);
#endif /*LIBISO_IMAGE_TREE_H_*/

31
libisofs/util.c

@ -1534,6 +1534,26 @@ uint32_t iso_read_bb(const uint8_t *buf, int bytes, int *error)
return v1;
}
uint64_t iso_read_lsb64(const uint8_t *buf)
{
int i;
uint64_t ret = 0;
for (i=0; i < 8; i++)
ret += ((uint64_t) buf[i]) << (i * 8);
return ret;
}