New API call iso_write_opts_set_hfsp_block_size().

release-1.5.4.branch
Thomas Schmitt 10 years ago
parent 7e49fb553b
commit 2d441cca5d
  1. 28
      libisofs/ecma119.c
  2. 31
      libisofs/ecma119.h
  3. 302
      libisofs/hfsplus.c
  4. 26
      libisofs/libisofs.h
  5. 1
      libisofs/libisofs.ver
  6. 4
      libisofs/messages.c
  7. 73
      libisofs/system_area.c
  8. 2
      libisofs/system_area.h

@ -1920,7 +1920,10 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
if (target->hfsplus_blessed[i] != NULL)
iso_node_ref(target->hfsplus_blessed[i]);
}
target->apm_block_size = 512;
target->apm_block_size = opts->apm_block_size;
target->hfsp_block_size = opts->hfsp_block_size;
target->hfsp_cat_node_size = 0;
target->hfsp_iso_block_fac = 0;
target->apm_req_count = 0;
target->apm_req_flags = 0;
for (i = 0; i < ISO_APM_ENTRIES_MAX; i++)
@ -2356,6 +2359,13 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
iso_image_free_checksums(target->image, 0);
image_checksums_mad = 0;
if (target->apm_block_size == 0) {
if (target->gpt_req_count)
target->apm_block_size = 2048; /* Combinable with GPT */
else
target->apm_block_size = 512; /* Mountable on Linux */
}
/* ensure the thread is created joinable */
pthread_attr_init(&(target->th_attr));
pthread_attr_setdetachstate(&(target->th_attr), PTHREAD_CREATE_JOINABLE);
@ -2739,6 +2749,8 @@ int iso_write_opts_new(IsoWriteOpts **opts, int profile)
wopts->untranslated_name_len = 0;
for (i = 0; i < 8; i++)
wopts->hfsp_serial_number[i] = 0;
wopts->apm_block_size = 0;
wopts->hfsp_block_size = 0;
*opts = wopts;
return ISO_SUCCESS;
@ -3403,4 +3415,18 @@ int iso_write_opts_set_hfsp_serial_number(IsoWriteOpts *opts,
memcpy(opts->hfsp_serial_number, serial_number, 8);
return ISO_SUCCESS;
}
int iso_write_opts_set_hfsp_block_size(IsoWriteOpts *opts,
int hfsp_block_size, int apm_block_size)
{
if (hfsp_block_size != 0 && hfsp_block_size != 512 &&
hfsp_block_size != 2048)
return ISO_BOOT_HFSP_BAD_BSIZE;
opts->hfsp_block_size = hfsp_block_size;
if (apm_block_size != 0 && apm_block_size != 512 && apm_block_size != 2048)
return ISO_BOOT_HFSP_BAD_BSIZE;
opts->apm_block_size = apm_block_size;
return ISO_SUCCESS;
}

@ -477,6 +477,14 @@ struct iso_write_opts {
*/
uint8_t hfsp_serial_number[8];
/* Allocation block size of HFS+ : 0= auto , 512, or 2048
*/
int hfsp_block_size;
/* Block size of and in APM : 0= auto , 512, or 2048
*/
int apm_block_size;
};
typedef struct ecma119_image Ecma119Image;
@ -819,6 +827,22 @@ struct ecma119_image
/* See IsoImage and libisofs.h */
IsoNode *hfsplus_blessed[ISO_HFSPLUS_BLESS_MAX];
/* Block sizes come from write options.
Only change a block size if it is 0. Set only to 512 or 2048.
If it stays 0 then it will become 512 or 2048 in time.
*/
/* Blocksize of Apple Partition Map
May be defined to 512 or 2048 before writer thread starts.
*/
int apm_block_size;
/* Allocation block size of HFS+
May be defined to 512 or 2048 before hfsplus_writer_create().
*/
int hfsp_block_size;
int hfsp_cat_node_size; /* 2 * apm_block_size */
int hfsp_iso_block_fac; /* 2048 / apm_block_size */
/* Apple Partition Map description. To be composed during IsoImageWriter
method ->compute_data_blocks() by calling iso_register_apm_entry().
Make sure that the composing writers get registered before the
@ -826,9 +850,10 @@ struct ecma119_image
*/
struct iso_apm_partition_request *apm_req[ISO_APM_ENTRIES_MAX];
int apm_req_count;
/* 512 by default. May be changed to 2048 before writer thread starts. */
int apm_block_size;
/* bit1= Do not fill gaps in Apple Partition Map */
/* bit1= Do not fill gaps in Apple Partition Map
bit2= apm_req entries use apm_block_size in start_block and block_count.
Normally these two parameters are counted in 2 KiB blocks.
*/
int apm_req_flags;
/* MBR partition table description. To be composed during IsoImageWriter

@ -20,6 +20,16 @@
#define Libisofs_ts_debuG yes
/* Do not fill gaps in APM.
<<< provisory , rather not
# define Libisofs_hfsplus_no_gap_filL yes
*/
/* Avoid ISO block padding in hfsplus_tail_writer
<<< provisory , rather not
# define Libisofs_apm_flags_bit2 yes
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
@ -41,10 +51,16 @@
#include <stdio.h>
#include <string.h>
#define HFSPLUS_BLOCK_SIZE 2048
#define HFSPLUS_CAT_NODE_SIZE (2 * HFSPLUS_BLOCK_SIZE)
/* To be used if Ecma119.hfsplus_block_size == 0 in hfsplus_writer_create().
It cannot be larger than 2048 because filesrc_writer aligns data file
content start to 2048.
*/
#define HFSPLUS_DEFAULT_BLOCK_SIZE 2048
/* To be used with storage allocation.
*/
#define HFSPLUS_MAX_BLOCK_SIZE 2048
#define HFSPLUS_ISO_BLOCK_FAC (2048 / HFSPLUS_BLOCK_SIZE)
#include <arpa/inet.h>
/* For these prototypes:
@ -311,8 +327,8 @@ int create_tree(Ecma119Image *t, IsoNode *iso, uint32_t parent_id)
if (t->hfsplus_blessed[i] == iso) {
#ifdef Libisofs_ts_debuG
iso_msg_debug(t->image->id, "hfsplus bless %d to cat_id %u ('%s')",
i, cat_id, iso->name);
iso_msg_debug(t->image->id, "hfsplus bless %d to cat_id %u ('%s')",
i, cat_id, iso->name);
#endif /* Libisofs_ts_debuG */
t->hfsp_bless_id[i] = cat_id;
@ -417,100 +433,141 @@ cmp_node(const void *f1, const void *f2)
return ucscmp(a, b);
}
static
int hfsplus_tail_writer_compute_data_blocks(IsoImageWriter *writer)
{
Ecma119Image *t;
uint32_t hfsp_size;
uint32_t hfsp_size, hfsp_curblock, block_fac, block_size;
if (writer == NULL) {
return ISO_OUT_OF_MEM;
}
t = writer->target;
block_size = t->hfsp_block_size;
block_fac = t->hfsp_iso_block_fac;
#ifdef Libisofs_ts_debuG
iso_msg_debug(t->image->id, "hfsplus tail writer start = %.f",
((double) t->curblock) * 2048.0);
iso_msg_debug(t->image->id, "hfsplus tail writer start = %.f",
((double) t->curblock) * 2048.0);
#endif
hfsp_size = t->curblock * HFSPLUS_ISO_BLOCK_FAC - t->hfsp_part_start + 1;
hfsp_curblock = t->curblock * block_fac;
hfsp_size = hfsp_curblock - t->hfsp_part_start + 1;
/* We need one bit for every block. */
/* So if we allocate x blocks we have to satisfy:
8 * HFSPLUS_BLOCK_SIZE * x >= total_size + x
(8 * HFSPLUS_BLOCK_SIZE - 1) * x >= total_size
8 * block_size * x >= total_size + x
(8 * block_size - 1) * x >= total_size
*/
t->hfsp_allocation_blocks = hfsp_size
/ (8 * HFSPLUS_BLOCK_SIZE - 1) + 1;
t->hfsp_allocation_file_start = t->curblock * HFSPLUS_ISO_BLOCK_FAC;
t->curblock += t->hfsp_allocation_blocks / HFSPLUS_ISO_BLOCK_FAC;
if (t->hfsp_allocation_blocks % HFSPLUS_ISO_BLOCK_FAC)
t->hfsp_allocation_blocks = hfsp_size / (8 * block_size - 1) + 1;
t->hfsp_allocation_file_start = hfsp_curblock;
hfsp_curblock += t->hfsp_allocation_blocks;
#ifdef Libisofs_apm_flags_bit2
/* Superblock always occupies 2K */
hfsp_curblock += block_fac;
/* write_data() will need to pad up ISO block after superblock copy */
t->curblock = hfsp_curblock / block_fac;
if (hfsp_curblock % block_fac)
t->curblock++;
#else /* Libisofs_apm_flags_bit2 */
/* write_data() will need to pad up ISO block before superblock copy */
t->curblock = hfsp_curblock / block_fac;
if (hfsp_curblock % block_fac)
t->curblock++;
hfsp_curblock = t->curblock * block_fac;
/* Superblock always occupies 2K */
hfsp_curblock += block_fac;
t->curblock++;
#endif /* ! Libisofs_apm_flags_bit4 */
#ifdef Libisofs_ts_debuG
iso_msg_debug(t->image->id, "hfsplus tail writer end = %.f",
((double) t->curblock) * 2048.0);
iso_msg_debug(t->image->id, "hfsplus tail writer end = %.f",
((double) hfsp_curblock) * block_size);
#endif
t->hfsp_total_blocks = t->curblock * HFSPLUS_ISO_BLOCK_FAC
- t->hfsp_part_start;
t->apm_block_size = HFSPLUS_BLOCK_SIZE;
return iso_quick_apm_entry(t, t->hfsp_part_start / HFSPLUS_ISO_BLOCK_FAC,
t->hfsp_total_blocks / HFSPLUS_ISO_BLOCK_FAC +
!!(t->hfsp_total_blocks % HFSPLUS_ISO_BLOCK_FAC),
t->hfsp_total_blocks = hfsp_curblock - t->hfsp_part_start;
#ifdef Libisofs_hfsplus_no_gap_filL
/* <<< test B20625 : leave out gap filling */
t->apm_req_flags |= 2;
#endif /* Libisofs_hfsplus_no_gap_filL */
#ifdef Libisofs_apm_flags_bit2
t->apm_req_flags |= 4;
return iso_quick_apm_entry(t, t->hfsp_part_start,
t->hfsp_total_blocks,
"HFSPLUS_Hybrid", "Apple_HFS");
#else /* Libisofs_apm_flags_bit2 */
return iso_quick_apm_entry(t, t->hfsp_part_start / block_fac,
t->hfsp_total_blocks / block_fac +
!!(t->hfsp_total_blocks % block_fac),
"HFSPLUS_Hybrid", "Apple_HFS");
#endif /* ! Libisofs_apm_flags_bit2 */
}
static
int hfsplus_writer_compute_data_blocks(IsoImageWriter *writer)
{
Ecma119Image *t;
uint32_t i, link_blocks;
uint32_t i, link_blocks, hfsp_curblock;
uint32_t block_fac, cat_node_size, block_size;
if (writer == NULL) {
return ISO_OUT_OF_MEM;
}
t = writer->target;
block_size = t->hfsp_block_size;
block_fac = t->hfsp_iso_block_fac;
cat_node_size = t->hfsp_cat_node_size;
iso_msg_debug(t->image->id, "(b) curblock=%d, nodes =%d", t->curblock, t->hfsp_nnodes);
t->hfsp_part_start = t->curblock * HFSPLUS_ISO_BLOCK_FAC;
t->hfsp_part_start = t->curblock * block_fac;
hfsp_curblock = t->curblock * block_fac;
t->curblock++;
/* Superblock always occupies 2K */
hfsp_curblock += block_fac;
t->hfsp_catalog_file_start = t->curblock * HFSPLUS_ISO_BLOCK_FAC;
t->hfsp_catalog_file_start = hfsp_curblock;
/* ts B20623 was:
t->curblock += 2 * t->hfsp_nnodes;
/*
hfsp_curblock += (t->hfsp_nnodes * cat_node_size + block_size - 1) / block_size;
*/
t->curblock += (t->hfsp_nnodes * HFSPLUS_CAT_NODE_SIZE + 2047) / 2048;
hfsp_curblock += 2 * t->hfsp_nnodes;
t->hfsp_extent_file_start = t->curblock * HFSPLUS_ISO_BLOCK_FAC;
t->curblock++;
t->hfsp_extent_file_start = hfsp_curblock;
hfsp_curblock++;
iso_msg_debug(t->image->id, "(d) curblock=%d, nodes =%d", t->curblock, t->hfsp_nnodes);
iso_msg_debug(t->image->id, "(d) hfsp_curblock=%d, nodes =%d", hfsp_curblock, t->hfsp_nnodes);
link_blocks = 0;
for (i = 0; i < t->hfsp_nleafs; i++)
if (t->hfsp_leafs[i].unix_type == UNIX_SYMLINK)
{
/* ts B20623 : was:
t->hfsp_leafs[i].symlink_block = t->curblock;
t->curblock += (t->hfsp_leafs[i].symlink_size + HFSPLUS_BLOCK_SIZE - 1) / HFSPLUS_BLOCK_SIZE;
*/
t->hfsp_leafs[i].symlink_block = hfsp_curblock;
hfsp_curblock += (t->hfsp_leafs[i].symlink_size + block_size - 1) / block_size;
t->hfsp_leafs[i].symlink_block =
t->curblock * HFSPLUS_ISO_BLOCK_FAC + link_blocks;
link_blocks += (t->hfsp_leafs[i].symlink_size +
HFSPLUS_BLOCK_SIZE - 1) / HFSPLUS_BLOCK_SIZE;
}
/* ts B20623 */
t->curblock += link_blocks / HFSPLUS_ISO_BLOCK_FAC;
if (link_blocks % HFSPLUS_ISO_BLOCK_FAC)
t->curblock = hfsp_curblock / block_fac;
if (hfsp_curblock % block_fac)
t->curblock++;
iso_msg_debug(t->image->id, "(a) curblock=%d, nodes =%d", t->curblock, t->hfsp_nnodes);
@ -518,6 +575,7 @@ int hfsplus_writer_compute_data_blocks(IsoImageWriter *writer)
return ISO_SUCCESS;
}
static void set_time (uint32_t *tm, uint32_t t)
{
iso_msb ((uint8_t *) tm, t + 2082844800, 4);
@ -570,9 +628,12 @@ write_sb (Ecma119Image *t)
static char buffer[1024];
int ret;
int i;
uint32_t block_size;
iso_msg_debug(t->image->id, "Write HFS+ superblock");
block_size = t->hfsp_block_size;
memset (buffer, 0, sizeof (buffer));
ret = iso_write(t, buffer, 1024);
if (ret < 0)
@ -592,28 +653,28 @@ write_sb (Ecma119Image *t)
set_time (&sb.fsck_time, t->now);
iso_msb ((uint8_t *) &sb.file_count, t->hfsp_nfiles, 4);
iso_msb ((uint8_t *) &sb.folder_count, t->hfsp_ndirs - 1, 4);
iso_msb ((uint8_t *) &sb.blksize, HFSPLUS_BLOCK_SIZE, 4);
iso_msb ((uint8_t *) &sb.blksize, block_size, 4);
iso_msb ((uint8_t *) &sb.catalog_node_id, t->hfsp_cat_id, 4);
iso_msb ((uint8_t *) &sb.rsrc_clumpsize, HFSPLUS_BLOCK_SIZE, 4);
iso_msb ((uint8_t *) &sb.data_clumpsize, HFSPLUS_BLOCK_SIZE, 4);
iso_msb ((uint8_t *) &sb.rsrc_clumpsize, block_size, 4);
iso_msb ((uint8_t *) &sb.data_clumpsize, block_size, 4);
iso_msb ((uint8_t *) &sb.total_blocks, t->hfsp_total_blocks, 4);
iso_msb ((uint8_t *) &sb.encodings_bitmap + 4, 1, 4);
iso_msb ((uint8_t *) &sb.allocations_file.size + 4, t->hfsp_allocation_size, 4);
iso_msb ((uint8_t *) &sb.allocations_file.clumpsize, HFSPLUS_BLOCK_SIZE, 4);
iso_msb ((uint8_t *) &sb.allocations_file.blocks, (t->hfsp_allocation_size + HFSPLUS_BLOCK_SIZE - 1) / HFSPLUS_BLOCK_SIZE, 4);
iso_msb ((uint8_t *) &sb.allocations_file.clumpsize, block_size, 4);
iso_msb ((uint8_t *) &sb.allocations_file.blocks, (t->hfsp_allocation_size + block_size - 1) / block_size, 4);
iso_msb ((uint8_t *) &sb.allocations_file.extents[0].start, t->hfsp_allocation_file_start - t->hfsp_part_start, 4);
iso_msb ((uint8_t *) &sb.allocations_file.extents[0].count, (t->hfsp_allocation_size + HFSPLUS_BLOCK_SIZE - 1) / HFSPLUS_BLOCK_SIZE, 4);
iso_msb ((uint8_t *) &sb.allocations_file.extents[0].count, (t->hfsp_allocation_size + block_size - 1) / block_size, 4);
iso_msb ((uint8_t *) &sb.extents_file.size + 4, HFSPLUS_BLOCK_SIZE, 4);
iso_msb ((uint8_t *) &sb.extents_file.clumpsize, HFSPLUS_BLOCK_SIZE, 4);
iso_msb ((uint8_t *) &sb.extents_file.size + 4, block_size, 4);
iso_msb ((uint8_t *) &sb.extents_file.clumpsize, block_size, 4);
iso_msb ((uint8_t *) &sb.extents_file.blocks, 1, 4);
iso_msb ((uint8_t *) &sb.extents_file.extents[0].start, t->hfsp_extent_file_start - t->hfsp_part_start, 4);
iso_msb ((uint8_t *) &sb.extents_file.extents[0].count, 1, 4);
iso_msg_debug(t->image->id, "extent_file_start = %d\n", (int)t->hfsp_extent_file_start);
iso_msb ((uint8_t *) &sb.catalog_file.size + 4, HFSPLUS_BLOCK_SIZE * 2 * t->hfsp_nnodes, 4);
iso_msb ((uint8_t *) &sb.catalog_file.clumpsize, HFSPLUS_BLOCK_SIZE * 2, 4);
iso_msb ((uint8_t *) &sb.catalog_file.size + 4, block_size * 2 * t->hfsp_nnodes, 4);
iso_msb ((uint8_t *) &sb.catalog_file.clumpsize, block_size * 2, 4);
iso_msb ((uint8_t *) &sb.catalog_file.blocks, 2 * t->hfsp_nnodes, 4);
iso_msb ((uint8_t *) &sb.catalog_file.extents[0].start, t->hfsp_catalog_file_start - t->hfsp_part_start, 4);
iso_msb ((uint8_t *) &sb.catalog_file.extents[0].count, 2 * t->hfsp_nnodes, 4);
@ -625,8 +686,8 @@ write_sb (Ecma119Image *t)
t->hfsp_bless_id[i], 4);
#ifdef Libisofs_ts_debuG
iso_msg_debug(t->image->id, "hfsplus bless %d written for cat_id %u",
i, t->hfsp_bless_id[i]);
iso_msg_debug(t->image->id, "hfsplus bless %d written for cat_id %u",
i, t->hfsp_bless_id[i]);
#endif /* Libisofs_ts_debuG */
}
@ -642,18 +703,21 @@ static
int hfsplus_writer_write_data(IsoImageWriter *writer)
{
int ret;
static char buffer[2 * HFSPLUS_BLOCK_SIZE];
static char buffer[2 * HFSPLUS_MAX_BLOCK_SIZE];
Ecma119Image *t;
struct hfsplus_btnode *node_head;
struct hfsplus_btheader *tree_head;
int level;
uint32_t curpos = 1, i;
uint32_t curpos = 1, i, block_fac, cat_node_size, block_size;
if (writer == NULL) {
return ISO_NULL_POINTER;
}
t = writer->target;
block_size = t->hfsp_block_size;
block_fac = t->hfsp_iso_block_fac;
cat_node_size = t->hfsp_cat_node_size;
iso_msg_debug(t->image->id, "(b) %d written", (int) t->bytes_written / 0x800);
@ -675,27 +739,27 @@ int hfsplus_writer_write_data(IsoImageWriter *writer)
iso_msb ((uint8_t *) &tree_head->leaf_records, t->hfsp_nleafs, 4);
iso_msb ((uint8_t *) &tree_head->first_leaf_node, t->hfsp_nnodes - t->hfsp_levels[0].level_size, 4);
iso_msb ((uint8_t *) &tree_head->last_leaf_node, t->hfsp_nnodes - 1, 4);
iso_msb ((uint8_t *) &tree_head->nodesize, HFSPLUS_CAT_NODE_SIZE, 2);
iso_msb ((uint8_t *) &tree_head->nodesize, cat_node_size, 2);
iso_msb ((uint8_t *) &tree_head->keysize, 6 + 2 * LIBISO_HFSPLUS_NAME_MAX, 2);
iso_msb ((uint8_t *) &tree_head->total_nodes, t->hfsp_nnodes, 4);
iso_msb ((uint8_t *) &tree_head->free_nodes, 0, 4);
iso_msb ((uint8_t *) &tree_head->clump_size, HFSPLUS_CAT_NODE_SIZE, 4);
iso_msb ((uint8_t *) &tree_head->clump_size, cat_node_size, 4);
tree_head->key_compare = 0xcf;
iso_msb ((uint8_t *) &tree_head->attributes, 2 | 4, 4);
memset (buffer + 0xf8, -1, t->hfsp_nnodes / 8);
buffer[0xf8 + (t->hfsp_nnodes / 8)] = 0xff00 >> (t->hfsp_nnodes % 8);
buffer[HFSPLUS_CAT_NODE_SIZE - 1] = sizeof (*node_head);
buffer[HFSPLUS_CAT_NODE_SIZE - 3] = sizeof (*node_head) + sizeof (*tree_head);
buffer[HFSPLUS_CAT_NODE_SIZE - 5] = (char) 0xf8;
buffer[HFSPLUS_CAT_NODE_SIZE - 7] = (char) ((HFSPLUS_CAT_NODE_SIZE - 8) & 0xff);
buffer[HFSPLUS_CAT_NODE_SIZE - 8] = (HFSPLUS_CAT_NODE_SIZE - 8) >> 8;
buffer[cat_node_size - 1] = sizeof (*node_head);
buffer[cat_node_size - 3] = sizeof (*node_head) + sizeof (*tree_head);
buffer[cat_node_size - 5] = (char) 0xf8;
buffer[cat_node_size - 7] = (char) ((cat_node_size - 8) & 0xff);
buffer[cat_node_size - 8] = (cat_node_size - 8) >> 8;
#ifdef Libisofs_hfsplus_verbose_debuG
iso_msg_debug(t->image->id, "Write\n");
#endif
ret = iso_write(t, buffer, HFSPLUS_CAT_NODE_SIZE);
ret = iso_write(t, buffer, cat_node_size);
if (ret < 0)
return ret;
@ -720,7 +784,7 @@ int hfsplus_writer_write_data(IsoImageWriter *writer)
curoff = sizeof (struct hfsplus_btnode);
for (j = 0; j < t->hfsp_levels[level].nodes[i].cnt; j++)
{
iso_msb ((uint8_t *) buffer + HFSPLUS_CAT_NODE_SIZE - j * 2 - 2, curoff, 2);
iso_msb ((uint8_t *) buffer + cat_node_size - j * 2 - 2, curoff, 2);
iso_msb ((uint8_t *) buffer + curoff, 2 * t->hfsp_levels[level - 1].nodes[curnode].strlen + 6, 2);
iso_msb ((uint8_t *) buffer + curoff + 2, t->hfsp_levels[level - 1].nodes[curnode].parent_id, 4);
@ -732,13 +796,13 @@ int hfsplus_writer_write_data(IsoImageWriter *writer)
curoff += 4;
curnode++;
}
iso_msb ((uint8_t *) buffer + HFSPLUS_CAT_NODE_SIZE - j * 2 - 2, curoff, 2);
iso_msb ((uint8_t *) buffer + cat_node_size - j * 2 - 2, curoff, 2);
#ifdef Libisofs_hfsplus_verbose_debuG
iso_msg_debug(t->image->id, "Write\n");
#endif
ret = iso_write(t, buffer, HFSPLUS_CAT_NODE_SIZE);
ret = iso_write(t, buffer, cat_node_size);
if (ret < 0)
return ret;
@ -766,7 +830,7 @@ int hfsplus_writer_write_data(IsoImageWriter *writer)
curoff = sizeof (struct hfsplus_btnode);
for (j = 0; j < t->hfsp_levels[level].nodes[i].cnt; j++)
{
iso_msb ((uint8_t *) buffer + HFSPLUS_CAT_NODE_SIZE - j * 2 - 2, curoff, 2);
iso_msb ((uint8_t *) buffer + cat_node_size - j * 2 - 2, curoff, 2);
#ifdef Libisofs_hfsplus_verbose_debuG
@ -920,16 +984,16 @@ iso_msg_debug(t->image->id,
&blk, &sz);
if (ret <= 0)
return ret;
blk *= HFSPLUS_ISO_BLOCK_FAC;
blk *= block_fac;
}
if (sz == 0)
blk = t->hfsp_part_start;
iso_msb ((uint8_t *) &data_fork->size, sz >> 32, 4);
iso_msb ((uint8_t *) &data_fork->size + 4, sz, 4);
iso_msb ((uint8_t *) &data_fork->clumpsize, HFSPLUS_BLOCK_SIZE, 4);
iso_msb ((uint8_t *) &data_fork->blocks, (sz + HFSPLUS_BLOCK_SIZE - 1) / HFSPLUS_BLOCK_SIZE, 4);
iso_msb ((uint8_t *) &data_fork->clumpsize, block_size, 4);
iso_msb ((uint8_t *) &data_fork->blocks, (sz + block_size - 1) / block_size, 4);
iso_msb ((uint8_t *) &data_fork->extents[0].start, blk - t->hfsp_part_start, 4);
iso_msb ((uint8_t *) &data_fork->extents[0].count, (sz + HFSPLUS_BLOCK_SIZE - 1) / HFSPLUS_BLOCK_SIZE, 4);
iso_msb ((uint8_t *) &data_fork->extents[0].count, (sz + block_size - 1) / block_size, 4);
curoff += sizeof (*data_fork) * 2;
/* FIXME: resource fork */
@ -939,13 +1003,13 @@ iso_msg_debug(t->image->id,
}
curnode++;
}
iso_msb ((uint8_t *) buffer + HFSPLUS_CAT_NODE_SIZE - j * 2 - 2, curoff, 2);
iso_msb ((uint8_t *) buffer + cat_node_size - j * 2 - 2, curoff, 2);
#ifdef Libisofs_hfsplus_verbose_debuG
iso_msg_debug(t->image->id, "Write\n");
#endif
ret = iso_write(t, buffer, HFSPLUS_CAT_NODE_SIZE);
ret = iso_write(t, buffer, cat_node_size);
if (ret < 0)
return ret;
}
@ -953,38 +1017,30 @@ iso_msg_debug(t->image->id,
}
memset (buffer, 0, sizeof (buffer));
ret = pad_up_block(t);
if (ret < 0)
return ret;
iso_msg_debug(t->image->id, "real extent_file_start = %d\n", (int)t->bytes_written / 2048);
node_head = (struct hfsplus_btnode *) buffer;
node_head->type = 1;
iso_msb ((uint8_t *) &node_head->count, 3, 2);
tree_head = (struct hfsplus_btheader *) (node_head + 1);
iso_msb ((uint8_t *) &tree_head->nodesize, HFSPLUS_BLOCK_SIZE, 2);
iso_msb ((uint8_t *) &tree_head->nodesize, block_size, 2);
iso_msb ((uint8_t *) &tree_head->keysize, 10, 2);
iso_msb ((uint8_t *) &tree_head->total_nodes, 1, 4);
iso_msb ((uint8_t *) &tree_head->free_nodes, 0, 4);
iso_msb ((uint8_t *) &tree_head->clump_size, HFSPLUS_BLOCK_SIZE, 4);
iso_msb ((uint8_t *) &tree_head->clump_size, block_size, 4);
iso_msb ((uint8_t *) &tree_head->attributes, 2, 4);
buffer[0xf8] = (char) 0x80;
buffer[HFSPLUS_BLOCK_SIZE - 1] = sizeof (*node_head);
buffer[HFSPLUS_BLOCK_SIZE - 3] = sizeof (*node_head) + sizeof (*tree_head);
buffer[HFSPLUS_BLOCK_SIZE - 5] = (char) 0xf8;
buffer[HFSPLUS_BLOCK_SIZE - 7] = (char) ((HFSPLUS_BLOCK_SIZE - 8) & 0xff);
buffer[HFSPLUS_BLOCK_SIZE - 8] = (HFSPLUS_BLOCK_SIZE - 8) >> 8;
buffer[block_size - 1] = sizeof (*node_head);
buffer[block_size - 3] = sizeof (*node_head) + sizeof (*tree_head);
buffer[block_size - 5] = (char) 0xf8;
buffer[block_size - 7] = (char) ((block_size - 8) & 0xff);
buffer[block_size - 8] = (block_size - 8) >> 8;
ret = iso_write(t, buffer, HFSPLUS_BLOCK_SIZE);
ret = iso_write(t, buffer, block_size);
if (ret < 0)
return ret;
ret = pad_up_block(t);
if (ret < 0)
return ret;
iso_msg_debug(t->image->id, "(d) %d written", (int) t->bytes_written / 0x800);
memset (buffer, 0, sizeof (buffer));
for (i = 0; i < t->hfsp_nleafs; i++)
@ -995,14 +1051,15 @@ iso_msg_debug(t->image->id,
ret = iso_write(t, sym->dest, t->hfsp_leafs[i].symlink_size);
if (ret < 0)
return ret;
overhead = t->hfsp_leafs[i].symlink_size % HFSPLUS_BLOCK_SIZE;
overhead = t->hfsp_leafs[i].symlink_size % block_size;
if (overhead)
overhead = HFSPLUS_BLOCK_SIZE - overhead;
overhead = block_size - overhead;
ret = iso_write(t, buffer, overhead);
if (ret < 0)
return ret;
}
/* Need to align for start of next writer */
ret = pad_up_block(t);
if (ret < 0)
return ret;
@ -1015,8 +1072,8 @@ static
int hfsplus_tail_writer_write_data(IsoImageWriter *writer)
{
int ret;
static char buffer[2 * HFSPLUS_BLOCK_SIZE];
uint32_t complete_blocks, remaining_blocks;
static char buffer[2 * HFSPLUS_MAX_BLOCK_SIZE];
uint32_t complete_blocks, remaining_blocks, block_size;
int over;
Ecma119Image *t;
@ -1025,28 +1082,29 @@ int hfsplus_tail_writer_write_data(IsoImageWriter *writer)
}
t = writer->target;
block_size = t->hfsp_block_size;
#ifdef Libisofs_ts_debuG
iso_msg_debug(t->image->id, "hfsplus tail writer writes at = %.f",
(double) t->bytes_written);
iso_msg_debug(t->image->id, "hfsplus tail writer writes at = %.f",
(double) t->bytes_written);
#endif
memset (buffer, -1, sizeof (buffer));
complete_blocks = (t->hfsp_allocation_size - 1) / HFSPLUS_BLOCK_SIZE;
complete_blocks = (t->hfsp_allocation_size - 1) / block_size;
remaining_blocks = t->hfsp_allocation_blocks - complete_blocks;
while (complete_blocks--)
{
ret = iso_write(t, buffer, HFSPLUS_BLOCK_SIZE);
ret = iso_write(t, buffer, block_size);
if (ret < 0)
return ret;
}
over = (t->hfsp_allocation_size - 1) % HFSPLUS_BLOCK_SIZE;
over = (t->hfsp_allocation_size - 1) % block_size;
if (over)
{
memset (buffer + over, 0, sizeof (buffer) - over);
buffer[over] = 0xff00 >> (t->hfsp_total_blocks % 8);
ret = iso_write(t, buffer, HFSPLUS_BLOCK_SIZE);
ret = iso_write(t, buffer, block_size);
if (ret < 0)
return ret;
remaining_blocks--;
@ -1055,29 +1113,32 @@ iso_msg_debug(t->image->id, "hfsplus tail writer writes at = %.f",
/* When we have both FAT and HFS+ we may to overestimate needed blocks a bit. */
while (remaining_blocks--)
{
ret = iso_write(t, buffer, HFSPLUS_BLOCK_SIZE);
ret = iso_write(t, buffer, block_size);
if (ret < 0)
return ret;
}
#ifndef Libisofs_apm_flags_bit2
ret = pad_up_block(t);
if (ret < 0)
return ret;
#endif /* ! Libisofs_apm_flags_bit2 */
iso_msg_debug(t->image->id, "%d written", (int) t->bytes_written);
#ifdef Libisofs_ts_debuG
iso_msg_debug(t->image->id, "hfsplus tail writer writes sb at = %.f",
(double) t->bytes_written);
#endif
ret = write_sb (t);
#ifdef Libisofs_ts_debuG
iso_msg_debug(t->image->id, "hfsplus tail writer ends at = %.f",
(double) t->bytes_written);
iso_msg_debug(t->image->id, "hfsplus tail writer ends at = %.f",
(double) t->bytes_written);
#endif
#ifdef Libisofs_apm_flags_bit2
ret = pad_up_block(t);
if (ret < 0)
return ret;
#endif /* Libisofs_apm_flags_bit2 */
return ret;
}
@ -1117,6 +1178,7 @@ int hfsplus_writer_create(Ecma119Image *target)
IsoNode *pos;
IsoDir *dir;
int i;
uint32_t cat_node_size;
writer = malloc(sizeof(IsoImageWriter));
if (writer == NULL) {
@ -1126,6 +1188,12 @@ int hfsplus_writer_create(Ecma119Image *target)
make_hfsplus_decompose_pages();
make_hfsplus_class_pages();
if (target->hfsp_block_size == 0)
target->hfsp_block_size = HFSPLUS_DEFAULT_BLOCK_SIZE;
target->hfsp_cat_node_size = 2 * target->hfsp_block_size;
target->hfsp_iso_block_fac = 2048 / target->hfsp_block_size;
cat_node_size = target->hfsp_cat_node_size;
writer->compute_data_blocks = hfsplus_writer_compute_data_blocks;
writer->write_vol_desc = nop_writer_write_vol_desc;
writer->write_data = hfsplus_writer_write_data;
@ -1205,7 +1273,7 @@ int hfsplus_writer_create(Ecma119Image *target)
{
uint32_t last_start = 0;
uint32_t i;
unsigned bytes_rem = HFSPLUS_CAT_NODE_SIZE - sizeof (struct hfsplus_btnode) - 2;
unsigned bytes_rem = cat_node_size - sizeof (struct hfsplus_btnode) - 2;
target->hfsp_levels[level].nodes = malloc ((target->hfsp_nleafs + 1) * sizeof (target->hfsp_levels[level].nodes[0]));
if (!target->hfsp_levels[level].nodes)
@ -1231,7 +1299,7 @@ int hfsplus_writer_create(Ecma119Image *target)
target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].parent_id = target->hfsp_leafs[last_start].parent_id;
target->hfsp_levels[level].level_size++;
last_start = i;
bytes_rem = HFSPLUS_CAT_NODE_SIZE - sizeof (struct hfsplus_btnode) - 2;
bytes_rem = cat_node_size - sizeof (struct hfsplus_btnode) - 2;
}
bytes_rem -= target->hfsp_leafs[i].used_size;
}
@ -1258,7 +1326,7 @@ int hfsplus_writer_create(Ecma119Image *target)
uint32_t last_start = 0;
uint32_t i;
uint32_t last_size;
unsigned bytes_rem = HFSPLUS_CAT_NODE_SIZE - sizeof (struct hfsplus_btnode) - 2;
unsigned bytes_rem = cat_node_size - sizeof (struct hfsplus_btnode) - 2;
last_size = target->hfsp_levels[level].level_size;
@ -1283,7 +1351,7 @@ int hfsplus_writer_create(Ecma119Image *target)
target->hfsp_levels[level].nodes[target->hfsp_levels[level].level_size].parent_id = target->hfsp_levels[level - 1].nodes[last_start].parent_id;
target->hfsp_levels[level].level_size++;
last_start = i;
bytes_rem = HFSPLUS_CAT_NODE_SIZE - sizeof (struct hfsplus_btnode) - 2;
bytes_rem = cat_node_size - sizeof (struct hfsplus_btnode) - 2;
}
bytes_rem -= used_size;
}
@ -1299,7 +1367,7 @@ int hfsplus_writer_create(Ecma119Image *target)
target->hfsp_nlevels = level + 1;
if (target->hfsp_nnodes > (HFSPLUS_CAT_NODE_SIZE - 0x100) * 8)
if (target->hfsp_nnodes > (cat_node_size - 0x100) * 8)
{
return iso_msg_submit(target->image->id, ISO_MANGLE_TOO_MUCH_FILES, 0,
"HFS+ map nodes aren't implemented");

@ -1467,6 +1467,27 @@ int iso_write_opts_set_fat(IsoWriteOpts *opts, int enable);
int iso_write_opts_set_hfsp_serial_number(IsoWriteOpts *opts,
uint8_t serial_number[8]);
/**
* Set the block size for Apple Partition Map and for HFS+.
*
* @param opts
* The option set to be manipulated.
* @param hfsp_block_size
* The allocation block size to be used by the HFS+ fileystem.
* 0, 512, or 2048
* @param hfsp_block_size
* The block size to be used for and within the Apple Partition Map.
* 0, 512, or 2048.
* Size 512 is not compatible with options which produce GPT.
* @return
* 1 success, < 0 error
*
* @since 1.2.4
*/
int iso_write_opts_set_hfsp_block_size(IsoWriteOpts *opts,
int hfsp_block_size, int apm_block_size);
/**
* Whether to use newer ISO-9660:1999 version.
*
@ -7343,6 +7364,11 @@ int iso_image_hfsplus_get_blessed(IsoImage *img, IsoNode ***blessed_nodes,
(FAILURE, HIGH, -390) */
#define ISO_BOOT_NO_EFI_ELTO 0xE830FE7A
/** Not a supported HFS+ or APM block size (FAILURE, HIGH, -391) */
#define ISO_BOOT_HFSP_BAD_BSIZE 0xE830FE79
/** APM block size prevents coexistence with GPT (FAILURE, HIGH, -392) */
#define ISO_BOOT_APM_GPT_BSIZE 0xE830FE78
/* Internal developer note:

@ -289,6 +289,7 @@ iso_write_opts_set_efi_bootp;
iso_write_opts_set_fat;
iso_write_opts_set_fifo_size;
iso_write_opts_set_hardlinks;
iso_write_opts_set_hfsp_block_size;
iso_write_opts_set_hfsp_serial_number;
iso_write_opts_set_hfsplus;
iso_write_opts_set_iso1999;

@ -490,6 +490,10 @@ const char *iso_error_to_msg(int errcode)
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";
case ISO_BOOT_HFSP_BAD_BSIZE:
return "Not a supported HFS+ or APM block size";
case ISO_BOOT_APM_GPT_BSIZE:
return "APM block size prevents coexistence with GPT";
default:
return "Unknown error";
}

@ -856,12 +856,11 @@ static int iso_write_apm_entry(Ecma119Image *t, int apm_block_size,
uint32_t flags;
int block_fac;
if (flag & 1)
if ((flag & 1) || (t->apm_req_flags & 4))
block_fac = 1;
else
block_fac = 2048 / apm_block_size;
memset(buf, apm_block_size, 0);
wpt = buf;
@ -916,9 +915,12 @@ static int iso_write_apm_entry(Ecma119Image *t, int apm_block_size,
static int fill_apm_gaps(Ecma119Image *t, uint32_t img_blocks)
{
int i, ret, gap_counter = 0, up_to;
uint32_t part_end, goal;
uint32_t part_end, goal, block_fac = 1;
char gap_name[33];
if (t->apm_req_flags & 4)
block_fac = 2048 / t->apm_block_size;
/* Find out whether an entry with start_block <= 1 is requested */
for (i = 0; i < t->apm_req_count; i++) {
if (t->apm_req[i]->start_block <= 1)
@ -939,12 +941,12 @@ static int fill_apm_gaps(Ecma119Image *t, uint32_t img_blocks)
if (i < up_to - 1)
goal = t->apm_req[i]->start_block;
else
goal = img_blocks;
goal = img_blocks * block_fac;
if (i == 1) {
/* Description of APM itself */
/* Actual APM size is not yet known. Protection begins at PVD */
part_end = 16;
if (goal < 16 && goal> 1)
part_end = 16 * block_fac;
if (goal < part_end && goal> 1)
part_end = goal;
} else {
part_end = t->apm_req[i - 1]->start_block +
@ -983,22 +985,35 @@ static int rectify_apm(Ecma119Image *t)
{
int ret;
#ifdef NIX
/* Disabled */
/* <<< 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");
/ * >>> 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, 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");
if (ret < 0)
return ret;
}
#endif /* NIX */
if (t->apm_req_count == 0)
return 1;
/* These are the only APM block sizes which can be processed here */
if (t->apm_block_size > 1536)
t->apm_block_size = 2048;
else if (t->apm_block_size > 768)
t->apm_block_size = 1024;
else
t->apm_block_size = 512;
if (t->gpt_req_count > 0 &&
t->apm_block_size != 2048 && t->apm_req_count > 0) {
t->apm_block_size = 2048;
iso_msgs_submit(0,
"GPT and APM requested. Had to force APM Block size to 2048.",
0, "DEBUG", 0);
"GPT and APM requested. APM block size would have to be 2048.",
0, "FAILURE", 0);
return ISO_BOOT_APM_GPT_BSIZE;
}
if (t->apm_req_count > 0) {
ret = fill_apm_gaps(t, t->curblock);
@ -1015,32 +1030,16 @@ static int iso_write_apm(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf,
int flag)
{
int i, ret;
/* This is a micro mick-up of an APM Block0
uint32_t block_fac = 1;
/* This is a micro mock-up of an APM Block0
and also harmless x86 machine code.
*/
static uint8_t block0_template[8] = {
0x45, 0x52, 0x02, 0x00, 0xeb, 0x02, 0xff, 0xff
};
#ifdef NIX
/* Disabled */
/* <<< 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");
/ * >>> 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, 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");
if (ret < 0)
return ret;
}
#endif /* NIX */
if (t->apm_req_flags & 4)
block_fac = 2048 / t->apm_block_size;
if (t->apm_req_count <= 0)
return 2;
@ -1051,7 +1050,7 @@ static int iso_write_apm(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf,
number of APM partitions was determined.
*/
t->apm_req[t->apm_req_count - 1]->block_count =
img_blocks - t->apm_req[t->apm_req_count - 1]->start_block;
img_blocks * block_fac - t->apm_req[t->apm_req_count - 1]->start_block;
/* If it is still empty, remove it */
if(t->apm_req[t->apm_req_count - 1]->block_count == 0) {
free(t->apm_req[t->apm_req_count - 1]);

@ -141,7 +141,7 @@ int iso_mbr_entry_slot_is_free(Ecma119Image *t, int slot);
*/
struct iso_apm_partition_request {
/* Always given in blocks of 2 KiB.
/* 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;

Loading…
Cancel
Save