Implemented support for eltorito on MS discs
This commit is contained in:
parent
0746d622e4
commit
d60193e2d5
5
TODO
5
TODO
@ -10,9 +10,12 @@ FEATURES
|
||||
[ok] Joliet
|
||||
Merge RR and Joliet trees
|
||||
[ok] User options to customize reading
|
||||
Read El-Torito info
|
||||
[ok] Read El-Torito info
|
||||
[ok] Multisession
|
||||
[ok] DVD+RW image growing
|
||||
El-Torito images from previous session
|
||||
Add new el-torito image from prev. session file
|
||||
Path for isolinux from prev. session
|
||||
UDF
|
||||
[ok] ISO relaxed contraints
|
||||
ISO 9660:1998
|
||||
|
@ -184,15 +184,9 @@ calc_dir_size(struct ecma119_write_target *t,
|
||||
|
||||
for (i = 0; i < dir->info.dir.nchildren; i++) {
|
||||
struct ecma119_tree_node *ch = dir->info.dir.children[i];
|
||||
//struct iso_tree_node *iso = ch->iso_self;
|
||||
if (ch->type == ECMA119_DIR) {
|
||||
calc_dir_size(t, ch);
|
||||
}
|
||||
// else if (iso && iso->attrib.st_size
|
||||
// && iso->loc.type == LIBISO_FILESYS
|
||||
// && iso->loc.path) {
|
||||
// t->filelist_len++;
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -231,12 +225,11 @@ cmp_file(const void *f1, const void *f2)
|
||||
* Fill out the block field for each file and fill out t->filelist.
|
||||
*/
|
||||
static void
|
||||
calc_file_pos(struct ecma119_write_target *t,
|
||||
struct ecma119_tree_node *dir)
|
||||
calc_file_pos(struct ecma119_write_target *t)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
assert(dir->type == ECMA119_DIR);
|
||||
assert(t);
|
||||
|
||||
t->filelist = calloc(1, sizeof(struct iso_file *) * t->file_table->count);
|
||||
|
||||
@ -338,7 +331,17 @@ ecma119_target_new(struct iso_volset *volset,
|
||||
|
||||
t->catalog = volset->volume[opts->volnum]->bootcat;
|
||||
t->eltorito = t->catalog ? 1 : 0;
|
||||
t->write_eltorito = opts->copy_eltorito;
|
||||
if (t->eltorito && (!t->ms_block || !t->catalog->proc) ) {
|
||||
/*
|
||||
* For new and modified images we always need to write el-torito.
|
||||
* For ms images, if the boot catalog was newly added, we also need
|
||||
* to write it!
|
||||
*/
|
||||
t->write_eltorito = 1;
|
||||
}
|
||||
|
||||
/* create the trees */
|
||||
t->root = ecma119_tree_create(t, iso_root);
|
||||
if (t->joliet)
|
||||
t->joliet_root = joliet_tree_create(t, iso_root);
|
||||
@ -377,8 +380,8 @@ ecma119_target_new(struct iso_volset *volset,
|
||||
|
||||
t->curblock = t->ms_block /* nwa for ms, usually 0 */
|
||||
+ 16 /* system area */
|
||||
+ 1 /* volume desc */
|
||||
+ 1; /* volume desc terminator */
|
||||
+ 1 /* primary volume desc */
|
||||
+ 1; /* volume desc terminator */
|
||||
|
||||
if (t->eltorito)
|
||||
t->curblock += 1; /* boot record volume descriptor */
|
||||
@ -411,17 +414,24 @@ ecma119_target_new(struct iso_volset *volset,
|
||||
|
||||
/* el-torito? */
|
||||
if (t->eltorito) {
|
||||
|
||||
/* add catalog block */
|
||||
t->catalog->file->block = t->curblock;
|
||||
t->curblock += div_up(2048, t->block_size);
|
||||
el_torito_get_image_files(t);
|
||||
if (t->write_eltorito) {
|
||||
/* add catalog block */
|
||||
t->catblock = t->curblock;
|
||||
t->curblock += div_up(2048, t->block_size);
|
||||
|
||||
/* add img block */
|
||||
t->imgblock = t->curblock;
|
||||
t->curblock += div_up(t->catalog->image->node->node.attrib.st_size,
|
||||
t->block_size);
|
||||
} else {
|
||||
assert(t->ms_block);
|
||||
assert(t->catalog->proc);
|
||||
t->catblock = t->catalog->node->loc.block;
|
||||
t->imgblock = t->catalog->image->node->loc.block;
|
||||
}
|
||||
}
|
||||
|
||||
calc_file_pos(t, t->root);
|
||||
|
||||
if (t->eltorito)
|
||||
el_torito_patch_image_files(t);
|
||||
calc_file_pos(t);
|
||||
|
||||
if (t->rockridge) {
|
||||
susp_finalize(t, t->root);
|
||||
@ -438,9 +448,6 @@ ecma119_target_new(struct iso_volset *volset,
|
||||
*/
|
||||
uint8_t *buf;
|
||||
|
||||
/* set the 32 block buffer to 0 */
|
||||
memset(opts->overwrite, 0, 32 * t->block_size);
|
||||
|
||||
/* skip the first 16 blocks (system area) */
|
||||
buf = opts->overwrite + 16 * t->block_size;
|
||||
|
||||
@ -494,16 +501,15 @@ is_eltorito_state(enum ecma119_write_state state)
|
||||
static void
|
||||
next_state(struct ecma119_write_target *t)
|
||||
{
|
||||
char msg[42];
|
||||
t->state++;
|
||||
while ( (!t->joliet && is_joliet_state(t->state))
|
||||
||(!t->eltorito && is_eltorito_state(t->state)) )
|
||||
||(!t->eltorito && is_eltorito_state(t->state))
|
||||
||(!t->write_eltorito && t->state == ECMA119_WRITE_ELTORITO_CATALOG) )
|
||||
t->state++;
|
||||
|
||||
{
|
||||
char msg[42];
|
||||
sprintf(msg, "Now in state %d, curblock=%d.", t->state, t->curblock);
|
||||
iso_msg_debug(msg);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -556,13 +562,14 @@ wr_files(struct ecma119_write_target *t, uint8_t *buf)
|
||||
assert( !t->ms_block && t->src );
|
||||
|
||||
/**
|
||||
* f->block block where file read begins
|
||||
* f->block block where file write begins
|
||||
* t->curblock block we're writting now
|
||||
* f->real_ino initial block for file on source
|
||||
*/
|
||||
block = t->curblock - f->block;
|
||||
if ( t->src->read_block(t->src, f->real_ino + block, buf) ) {
|
||||
warn("problem reading from previous image");
|
||||
iso_msg_sorry(LIBISO_CANT_READ_IMG,
|
||||
"Problem reading file from previous image");
|
||||
}
|
||||
if ( f->size <= (off_t) (block+1) * t->block_size ) {
|
||||
f_st->file++;
|
||||
@ -581,6 +588,8 @@ wr_files(struct ecma119_write_target *t, uint8_t *buf)
|
||||
f_st->data_len = f->size;
|
||||
f_st->fd = fopen(path, "r");
|
||||
if (!f_st->fd) {
|
||||
//FIXME instead of exit, just print a msg error and
|
||||
//skip file (what about reading from /dev/zero? instead)
|
||||
err(1, "couldn't open %s for reading", path);
|
||||
}
|
||||
assert(t->curblock + t->ms_block == f->block);
|
||||
@ -588,10 +597,15 @@ wr_files(struct ecma119_write_target *t, uint8_t *buf)
|
||||
|
||||
nread = fread(buf, 1, t->block_size, f_st->fd);
|
||||
f_st->pos += t->block_size;
|
||||
if (nread < 0)
|
||||
warn("problem reading from %s", path);
|
||||
else if (nread != t->block_size && f_st->pos < f_st->data_len)
|
||||
warnx("incomplete read from %s", path);
|
||||
if (nread < 0) {
|
||||
char msg[PATH_MAX + 32];
|
||||
sprintf(msg, "Problem reading from %s", path);
|
||||
iso_msg_sorry(LIBISO_CANT_READ_FILE, msg);
|
||||
} else if (nread != t->block_size && f_st->pos < f_st->data_len) {
|
||||
char msg[PATH_MAX + 32];
|
||||
sprintf(msg, "Incomplete read from %s", path);
|
||||
iso_msg_sorry(LIBISO_CANT_READ_FILE, msg);
|
||||
}
|
||||
if (f_st->pos >= f_st->data_len) {
|
||||
fclose(f_st->fd);
|
||||
f_st->fd = 0;
|
||||
@ -743,6 +757,16 @@ write_one_dir_record(struct ecma119_write_target *t,
|
||||
} else if (node->type == ECMA119_FILE) {
|
||||
len = node->info.file->size;
|
||||
block = node->info.file->block;
|
||||
} else if (node->type == ECMA119_BOOT) {
|
||||
assert(t->eltorito);
|
||||
if (node->info.boot_img) {
|
||||
block = t->imgblock;
|
||||
len = t->catalog->image->node->node.attrib.st_size;
|
||||
} else {
|
||||
/* we always assume 2048 as catalog len */
|
||||
block = t->catblock;
|
||||
len = 2048;
|
||||
}
|
||||
} else {
|
||||
/* for nodes other than files and dirs, we set both len and block to 0 */
|
||||
len = 0;
|
||||
@ -872,11 +896,10 @@ static int
|
||||
bs_read(struct burn_source *bs, unsigned char *buf, int size)
|
||||
{
|
||||
struct ecma119_write_target *t = (struct ecma119_write_target*)bs->data;
|
||||
if (size != t->block_size) {
|
||||
warnx("you must read data in block-sized chunks (%d bytes)",
|
||||
(int)t->block_size);
|
||||
return 0;
|
||||
} else if (t->curblock >= t->vol_space_size + t->ms_block) {
|
||||
|
||||
assert(size == t->block_size);
|
||||
|
||||
if (t->curblock >= t->vol_space_size) {
|
||||
return 0;
|
||||
}
|
||||
if (t->state_data_valid)
|
||||
|
@ -65,9 +65,22 @@ struct ecma119_write_target
|
||||
unsigned int iso_level:2;
|
||||
unsigned int eltorito:1;
|
||||
|
||||
int relaxed_constraints; /**< see ecma119_relaxed_constraints_flag */
|
||||
unsigned int write_eltorito:1;
|
||||
/**<
|
||||
* In multisession discs, select whether to copy el-torito catalog
|
||||
* and boot image. Copy is needed for isolinux images, that need to
|
||||
* be patched. However, it can lead to problems when the image is
|
||||
* not present in the iso filesystem, because we can't figure out
|
||||
* its size. In those cases, we only copy 1 block of data.
|
||||
* When modifying images, we always need to copy data. Thus, this is
|
||||
* always 1 for both new and modified images.
|
||||
*/
|
||||
|
||||
struct el_torito_boot_catalog *catalog;
|
||||
uint32_t catblock; /**< location of the boot catalog in the new image */
|
||||
uint32_t imgblock; /**< location of the boot image in the new image */
|
||||
|
||||
int relaxed_constraints; /**< see ecma119_relaxed_constraints_flag */
|
||||
|
||||
int replace_mode; /**< Replace ownership and modes of files
|
||||
*
|
||||
|
@ -28,12 +28,128 @@
|
||||
#include "volume.h"
|
||||
#include "tree.h"
|
||||
#include "messages.h"
|
||||
#include "eltorito.h"
|
||||
|
||||
#define BLOCK_SIZE 2048
|
||||
|
||||
static int
|
||||
iso_read_dir(struct iso_read_info *info, struct iso_tree_node_dir *parent,
|
||||
uint32_t block);
|
||||
|
||||
static struct el_torito_boot_catalog *
|
||||
read_el_torito_boot_catalog(struct iso_read_info *info, uint32_t block)
|
||||
{
|
||||
struct el_torito_validation_entry *ve;
|
||||
struct el_torito_default_entry *entry;
|
||||
struct el_torito_boot_catalog *catalog;
|
||||
struct el_torito_boot_image *image;
|
||||
unsigned char buffer[BLOCK_SIZE];
|
||||
|
||||
if ( info->src->read_block(info->src, block, buffer) < 0 ) {
|
||||
info->error = LIBISOFS_READ_FAILURE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ve = (struct el_torito_validation_entry*)buffer;
|
||||
|
||||
/* check if it is a valid catalog (TODO: check also the checksum)*/
|
||||
if ( (ve->header_id[0] != 1) || (ve->key_byte1[0] != 0x55)
|
||||
|| (ve->key_byte2[0] != 0xAA) ) {
|
||||
|
||||
iso_msg_sorry(LIBISO_EL_TORITO_WRONG, "Wrong or damaged El-Torito "
|
||||
"Catalog.\n El-Torito info will be ignored.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* check for a valid platform */
|
||||
if (ve->platform_id[0] != 0) {
|
||||
iso_msg_hint(LIBISO_EL_TORITO_UNHANLED, "Unsupported El-Torito platform.\n"
|
||||
"Only 80x86 si supported. El-Torito info will be ignored.");
|
||||
}
|
||||
|
||||
/* ok, once we are here we assume it is a valid catalog */
|
||||
catalog = malloc(sizeof(struct el_torito_boot_catalog));
|
||||
image = calloc(1, sizeof(struct el_torito_boot_image));
|
||||
catalog->image = image;
|
||||
catalog->proc = LIBISO_PREVIMG;
|
||||
|
||||
{
|
||||
/*
|
||||
* Create the placeholder.
|
||||
* Note that this could be modified later if we find a directory entry
|
||||
* for the catalog in the iso tree.
|
||||
*/
|
||||
struct iso_tree_node_boot *boot;
|
||||
boot = calloc(1, sizeof(struct iso_tree_node_boot));
|
||||
boot->node.refcount = 1;
|
||||
boot->node.attrib.st_mode = S_IFREG | 0777;
|
||||
boot->node.attrib.st_atime = boot->node.attrib.st_mtime
|
||||
= boot->node.attrib.st_ctime = time(NULL);
|
||||
boot->node.attrib.st_size = 2048;
|
||||
boot->node.type = LIBISO_NODE_BOOT;
|
||||
boot->node.procedence = LIBISO_PREVIMG;
|
||||
boot->node.name = NULL;
|
||||
boot->loc.block = block;
|
||||
catalog->node = boot;
|
||||
}
|
||||
|
||||
/* parse the default entry */
|
||||
entry = (struct el_torito_default_entry *)(buffer + 32);
|
||||
|
||||
image->bootable = entry->boot_indicator[0] ? 1 : 0;
|
||||
//FIXME we need a way to handle patch_isolinux in ms images!!!
|
||||
image->isolinux = 0;
|
||||
image->type = entry->boot_media_type[0];
|
||||
image->partition_type = entry->system_type[0];
|
||||
image->load_seg = iso_read_lsb(entry->load_seg, 2);
|
||||
image->load_size = iso_read_lsb(entry->sec_count, 2);
|
||||
|
||||
{
|
||||
/*
|
||||
* Create the placeholder.
|
||||
* Note that this could be modified later if we find a directory entry
|
||||
* for the image in the iso tree.
|
||||
*/
|
||||
struct iso_tree_node_boot *boot;
|
||||
boot = calloc(1, sizeof(struct iso_tree_node_boot));
|
||||
boot->node.refcount = 1;
|
||||
boot->node.attrib.st_mode = S_IFREG | 0777;
|
||||
boot->node.attrib.st_atime = boot->node.attrib.st_mtime
|
||||
= boot->node.attrib.st_ctime = time(NULL);
|
||||
boot->node.attrib.st_size = 2048;
|
||||
boot->node.type = LIBISO_NODE_BOOT;
|
||||
boot->node.procedence = LIBISO_PREVIMG;
|
||||
boot->node.name = NULL;
|
||||
boot->img = 1;
|
||||
boot->loc.block = iso_read_lsb(entry->block, 4);
|
||||
image->node = boot;
|
||||
}
|
||||
|
||||
//TODO how can we check if there are more entries?
|
||||
|
||||
return catalog;
|
||||
}
|
||||
|
||||
static struct el_torito_boot_catalog *
|
||||
read_el_torito_vol_desc(struct iso_read_info *info, unsigned char *buf)
|
||||
{
|
||||
struct ecma119_boot_rec_vol_desc *vol;
|
||||
|
||||
vol = (struct ecma119_boot_rec_vol_desc*)buf;
|
||||
|
||||
/* some sanity checks */
|
||||
if ( strncmp((char*)vol->std_identifier, "CD001", 5)
|
||||
|| vol->vol_desc_version[0] != 1
|
||||
|| strncmp((char*)vol->boot_sys_id, "EL TORITO SPECIFICATION", 23)) {
|
||||
|
||||
iso_msg_hint(LIBISO_BOOT_VD_UNHANLED, "Unsupported Boot Vol. Desc.\n"
|
||||
"Only El-Torito Specification, Version 1.0 Volume "
|
||||
"Descriptors are supported. Ignoring boot info");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return read_el_torito_boot_catalog(info, iso_read_lsb(vol->boot_catalog, 4));
|
||||
}
|
||||
|
||||
/**
|
||||
* This reads the "." directory entry, and set the properties of the
|
||||
@ -248,12 +364,22 @@ iso_read_single_directory_record(struct iso_read_info *info,
|
||||
break;
|
||||
case S_IFREG:
|
||||
{
|
||||
node = calloc(1, sizeof(struct iso_tree_node_file));
|
||||
node->type = LIBISO_NODE_FILE;
|
||||
|
||||
/* set block with extend */
|
||||
((struct iso_tree_node_file*)node)->loc.block =
|
||||
iso_read_bb(record->block, 4, NULL);
|
||||
uint32_t block;
|
||||
block = iso_read_bb(record->block, 4, NULL);
|
||||
|
||||
if (info->bootcat && block == info->bootcat->node->loc.block) {
|
||||
/* it is the boot catalog */
|
||||
node = (struct iso_tree_node*)info->bootcat->node;
|
||||
} else if (info->bootcat && block == info->bootcat->image->node->loc.block) {
|
||||
/* it is the boot image */
|
||||
node = (struct iso_tree_node*)info->bootcat->image->node;
|
||||
} else {
|
||||
/* it is a file */
|
||||
node = calloc(1, sizeof(struct iso_tree_node_file));
|
||||
node->type = LIBISO_NODE_FILE;
|
||||
/* set block with extend */
|
||||
((struct iso_tree_node_file*)node)->loc.block = block;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case S_IFLNK:
|
||||
@ -272,7 +398,7 @@ iso_read_single_directory_record(struct iso_read_info *info,
|
||||
|
||||
node->name = name;
|
||||
node->attrib = atts;
|
||||
node->refcount = 1;
|
||||
node->refcount++; /* 1 for news, 2 for boot nodes */
|
||||
node->procedence = LIBISO_PREVIMG;
|
||||
|
||||
iso_tree_add_child(parent, node);
|
||||
@ -520,7 +646,6 @@ read_root_susp_entries(struct iso_read_info *info,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct iso_volset *
|
||||
read_pvm(struct iso_read_info *info, uint32_t block)
|
||||
{
|
||||
@ -628,6 +753,7 @@ iso_volset_read(struct data_source *src, struct ecma119_read_opts *opts)
|
||||
info.gid = opts->gid;
|
||||
info.mode = opts->mode & ~S_IFMT;
|
||||
info.size = &opts->size;
|
||||
info.bootcat = NULL;
|
||||
root_dir_block = 0;
|
||||
|
||||
/* read primary volume description */
|
||||
@ -642,13 +768,16 @@ iso_volset_read(struct data_source *src, struct ecma119_read_opts *opts)
|
||||
do {
|
||||
if ( info.src->read_block(info.src, block, buffer) < 0 ) {
|
||||
info.error = LIBISOFS_READ_FAILURE;
|
||||
iso_volset_free(volset);
|
||||
return NULL;
|
||||
/* cleanup and exit */
|
||||
goto read_cleanup;
|
||||
}
|
||||
switch (buffer[0]) {
|
||||
case 0:
|
||||
/* boot record */
|
||||
//TODO handle el-torito
|
||||
/*
|
||||
* This is a boot record
|
||||
* Here we handle el-torito
|
||||
*/
|
||||
info.bootcat = read_el_torito_vol_desc(&info, buffer);
|
||||
break;
|
||||
case 2:
|
||||
/* suplementary volume descritor */
|
||||
@ -735,11 +864,25 @@ iso_volset_read(struct data_source *src, struct ecma119_read_opts *opts)
|
||||
if ( iso_read_dir(&info, volset->volume[0]->root, root_dir_block) ) {
|
||||
|
||||
/* error, cleanup and return */
|
||||
iso_volset_free(volset);
|
||||
return NULL;
|
||||
goto read_cleanup;
|
||||
}
|
||||
|
||||
// TODO merge tree info
|
||||
|
||||
/* Add El-Torito info to the volume */
|
||||
if (info.bootcat) {
|
||||
/* ok, add the bootcat to the volume */
|
||||
iso_msg_debug("Found El-Torito bootable volume");
|
||||
volset->volume[0]->bootcat = info.bootcat;
|
||||
}
|
||||
|
||||
return volset;
|
||||
|
||||
read_cleanup:;
|
||||
if (info.bootcat) {
|
||||
el_torito_boot_catalog_free(info.bootcat);
|
||||
}
|
||||
iso_volset_free(volset);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -66,6 +66,9 @@ struct iso_read_info {
|
||||
unsigned int hasJoliet:1; /*< It will be set to 1 if Joliet ext are present,
|
||||
to 0 if not. */
|
||||
uint32_t *size;
|
||||
|
||||
/* place for el-torito boot catalog */
|
||||
struct el_torito_boot_catalog *bootcat;
|
||||
};
|
||||
|
||||
|
||||
|
@ -259,37 +259,29 @@ create_symlink(struct ecma119_write_target *t,
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ECMA-119 node representing a boot catalog. This is like a
|
||||
* regular file, but its contents are taken from a El-Torito boot catalog,
|
||||
* and not from a file in the local filesystem.
|
||||
* Create a new ECMA-119 node representing a boot catalog or image.
|
||||
* This will be treated as a normal file when written the directory record,
|
||||
* but its contents are written in a different way.
|
||||
*
|
||||
* See "El Torito" Bootable CD-ROM Format Specification Version 1.0 for
|
||||
* more details.
|
||||
*/
|
||||
static struct ecma119_tree_node*
|
||||
create_boot_catalog(struct ecma119_write_target *t,
|
||||
create_boot(struct ecma119_write_target *t,
|
||||
struct ecma119_tree_node *parent,
|
||||
struct iso_tree_node_boot_catalog *iso)
|
||||
struct iso_tree_node_boot *iso)
|
||||
{
|
||||
struct ecma119_tree_node *ret;
|
||||
struct iso_file *file;
|
||||
|
||||
assert(t && iso && parent && parent->type == ECMA119_DIR);
|
||||
|
||||
/*
|
||||
* This will simply create a ECMA119 file, with the only difference
|
||||
* that the iso_file is not taken from table, but from boot catalog
|
||||
*/
|
||||
|
||||
ret = create_ecma119_node(t, parent, (struct iso_tree_node*) iso);
|
||||
ret->type = ECMA119_FILE;
|
||||
ret->type = ECMA119_BOOT;
|
||||
|
||||
file = iso->catalog->file;
|
||||
file->ino = ++t->ino;
|
||||
ret->info.boot_img = iso->img;
|
||||
|
||||
ret->attrib.st_nlink = file->nlink;
|
||||
ret->attrib.st_ino = file->ino;
|
||||
ret->info.file = file;
|
||||
ret->attrib.st_nlink = 1;
|
||||
ret->attrib.st_ino = ++t->ino;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -334,9 +326,8 @@ create_tree(struct ecma119_write_target *t,
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LIBISO_NODE_BOOTCATALOG:
|
||||
ret = create_boot_catalog(t, parent,
|
||||
(struct iso_tree_node_boot_catalog*)iso);
|
||||
case LIBISO_NODE_BOOT:
|
||||
ret = create_boot(t, parent, (struct iso_tree_node_boot*)iso);
|
||||
break;
|
||||
default:
|
||||
/* should never happen */
|
||||
|
@ -21,7 +21,8 @@ enum ecma119_node_type {
|
||||
ECMA119_FILE,
|
||||
ECMA119_SYMLINK,
|
||||
ECMA119_DIR,
|
||||
ECMA119_PLACEHOLDER /**< placeholder for a relocated dir. */
|
||||
ECMA119_PLACEHOLDER, /**< placeholder for a relocated dir. */
|
||||
ECMA119_BOOT
|
||||
};
|
||||
|
||||
struct ecma119_dir_info {
|
||||
@ -72,6 +73,10 @@ struct ecma119_tree_node
|
||||
struct ecma119_tree_node *real_me; /**< this field points to
|
||||
* the relocated directory.
|
||||
*/
|
||||
unsigned int boot_img:1; /** For boot nodes, it identifies if this
|
||||
* corresponds to image(1) or catalog(0).
|
||||
* The block is stored in ecma119_write_target
|
||||
*/
|
||||
} info;
|
||||
};
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "eltorito.h"
|
||||
#include "volume.h"
|
||||
#include "util.h"
|
||||
#include "messages.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <malloc.h>
|
||||
@ -15,46 +16,6 @@
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
struct el_torito_validation_entry {
|
||||
uint8_t header_id BP(1, 1);
|
||||
uint8_t platform_id BP(2, 2);
|
||||
uint8_t reserved BP(3, 4);
|
||||
uint8_t id_string BP(5, 28);
|
||||
uint8_t checksum BP(29, 30);
|
||||
uint8_t key_byte1 BP(31, 31);
|
||||
uint8_t key_byte2 BP(32, 32);
|
||||
};
|
||||
|
||||
struct el_torito_default_entry {
|
||||
uint8_t boot_indicator BP(1, 1);
|
||||
uint8_t boot_media_type BP(2, 2);
|
||||
uint8_t load_seg BP(3, 4);
|
||||
uint8_t system_type BP(5, 5);
|
||||
uint8_t unused1 BP(6, 6);
|
||||
uint8_t sec_count BP(7, 8);
|
||||
uint8_t block BP(9, 12);
|
||||
uint8_t unused2 BP(13, 32);
|
||||
};
|
||||
|
||||
struct el_torito_section_header_entry {
|
||||
uint8_t header_indicator BP(1, 1);
|
||||
uint8_t platform_id BP(2, 2);
|
||||
uint8_t number BP(3, 4);
|
||||
uint8_t character BP(5, 32);
|
||||
};
|
||||
|
||||
struct el_torito_section_entry {
|
||||
uint8_t boot_indicator BP(1, 1);
|
||||
uint8_t boot_media_type BP(2, 2);
|
||||
uint8_t load_seg BP(3, 4);
|
||||
uint8_t system_type BP(5, 5);
|
||||
uint8_t unused1 BP(6, 6);
|
||||
uint8_t sec_count BP(7, 8);
|
||||
uint8_t block BP(9, 12);
|
||||
uint8_t selec_criteria BP(13, 13);
|
||||
uint8_t vendor_sc BP(14, 32);
|
||||
};
|
||||
|
||||
/**
|
||||
* This table should be written with accuracy values at offset
|
||||
* 8 of boot image, when used ISOLINUX boot loader
|
||||
@ -85,18 +46,67 @@ struct hard_disc_mbr {
|
||||
uint8_t sign2;
|
||||
};
|
||||
|
||||
static void
|
||||
el_torito_image_free(struct el_torito_boot_image *image)
|
||||
{
|
||||
assert(image);
|
||||
|
||||
/* unref image node */
|
||||
iso_tree_free((struct iso_tree_node*)image->node);
|
||||
free(image);
|
||||
}
|
||||
|
||||
static struct iso_tree_node_boot*
|
||||
create_boot_image_node(struct iso_tree_node_file *image)
|
||||
{
|
||||
struct iso_tree_node_boot *boot;
|
||||
struct iso_tree_node_dir *parent;
|
||||
|
||||
assert(image);
|
||||
|
||||
boot = calloc(1, sizeof(struct iso_tree_node_boot));
|
||||
boot->node.attrib = image->node.attrib;
|
||||
boot->node.type = LIBISO_NODE_BOOT;
|
||||
boot->node.name = strdup(image->node.name);
|
||||
boot->node.hide_flags = image->node.hide_flags;
|
||||
boot->node.refcount = 2; /* mine and tree */
|
||||
boot->loc.path = strdup(image->loc.path);
|
||||
boot->img = 1; /* it refers to image */
|
||||
|
||||
/* replace iso_tree_node_file with the image */
|
||||
parent = image->node.parent;
|
||||
iso_tree_node_remove(parent, (struct iso_tree_node*)image);
|
||||
iso_tree_add_child(parent, (struct iso_tree_node*) boot);
|
||||
|
||||
return boot;
|
||||
}
|
||||
|
||||
static struct el_torito_boot_image *
|
||||
create_image(struct iso_tree_node *image,
|
||||
create_image(const char *path,
|
||||
enum eltorito_boot_media_type type)
|
||||
{
|
||||
struct stat attrib;
|
||||
struct el_torito_boot_image *boot;
|
||||
int boot_media_type = 0;
|
||||
int load_sectors = 0; /* number of sector to load */
|
||||
unsigned char partition_type = 0;
|
||||
|
||||
if (stat(path, &attrib)) {
|
||||
iso_msg_sorry(LIBISO_EL_TORITO_WRONG_IMG, "Can't access file.");
|
||||
libisofs_errno = NO_FILE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( !S_ISREG(attrib.st_mode) ) {
|
||||
iso_msg_sorry(LIBISO_EL_TORITO_WRONG_IMG,
|
||||
"We can only create boot images from regular files");
|
||||
libisofs_errno = ELTORITO_WRONG_IMAGE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case ELTORITO_FLOPPY_EMUL:
|
||||
switch (image->attrib.st_size) {
|
||||
switch (attrib.st_size) {
|
||||
case 1200 * 1024:
|
||||
boot_media_type = 1; /* 1.2 meg diskette */
|
||||
break;
|
||||
@ -107,10 +117,14 @@ create_image(struct iso_tree_node *image,
|
||||
boot_media_type = 3; /* 2.88 meg diskette */
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Invalid image size %d Kb. Must be one of 1.2, 1.44"
|
||||
"or 2.88 Mb", (int) image->attrib.st_size / 1024);
|
||||
{
|
||||
char msg[72];
|
||||
sprintf(msg, "Invalid image size %d Kb. Must be one of 1.2, 1.44"
|
||||
"or 2.88 Mb", (int) attrib.st_size / 1024);
|
||||
iso_msg_sorry(LIBISO_EL_TORITO_WRONG_IMG, msg);
|
||||
libisofs_errno = ELTORITO_WRONG_IMAGE_SIZE;
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* it seems that for floppy emulation we need to load
|
||||
@ -125,13 +139,16 @@ create_image(struct iso_tree_node *image,
|
||||
int used_partition;
|
||||
|
||||
/* read the MBR on disc and get the type of the partition */
|
||||
fd = open(((struct iso_tree_node_file*)image)->loc.path, O_RDONLY);
|
||||
fd = open(path, O_RDONLY);
|
||||
if ( fd == -1 ) {
|
||||
fprintf(stderr, "Can't open image file\n");
|
||||
iso_msg_sorry(LIBISO_EL_TORITO_WRONG_IMG, "Can't open image file.");
|
||||
libisofs_errno = NO_READ_ACCESS;
|
||||
return NULL;
|
||||
}
|
||||
if ( read(fd, &mbr, sizeof(mbr)) ) {
|
||||
fprintf(stderr, "Can't read MBR from image file\n");
|
||||
iso_msg_sorry(LIBISO_EL_TORITO_WRONG_IMG,
|
||||
"Can't read MBR from image file.");
|
||||
libisofs_errno = ELTORITO_WRONG_IMAGE;
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
@ -139,7 +156,9 @@ create_image(struct iso_tree_node *image,
|
||||
|
||||
/* check valid MBR signature */
|
||||
if ( mbr.sign1 != 0x55 || mbr.sign2 != 0xAA ) {
|
||||
fprintf(stderr, "Invalid MBR. Wrong signature.\n");
|
||||
iso_msg_sorry(LIBISO_EL_TORITO_WRONG_IMG,
|
||||
"Invalid MBR. Wrong signature.");
|
||||
libisofs_errno = ELTORITO_WRONG_IMAGE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -149,8 +168,11 @@ create_image(struct iso_tree_node *image,
|
||||
if (mbr.partition[i].type != 0) {
|
||||
/* it's an used partition */
|
||||
if (used_partition != -1) {
|
||||
fprintf(stderr, "Invalid MBR. At least 2 partitions: %d and "
|
||||
char msg[72];
|
||||
sprintf(msg, "Invalid MBR. At least 2 partitions: %d and "
|
||||
"%d, are being used\n", used_partition, i);
|
||||
iso_msg_sorry(LIBISO_EL_TORITO_WRONG_IMG, msg);
|
||||
libisofs_errno = ELTORITO_WRONG_IMAGE;
|
||||
return NULL;
|
||||
} else
|
||||
used_partition = i;
|
||||
@ -170,67 +192,180 @@ create_image(struct iso_tree_node *image,
|
||||
|
||||
boot = calloc(1, sizeof(struct el_torito_boot_image));
|
||||
boot->bootable = 1;
|
||||
boot->image = (struct iso_tree_node_file *) image;
|
||||
boot->type = boot_media_type;
|
||||
boot->load_size = load_sectors;
|
||||
boot->partition_type = partition_type;
|
||||
return boot;
|
||||
}
|
||||
|
||||
static struct iso_tree_node_boot_catalog*
|
||||
/* parent and name can be null */
|
||||
static struct iso_tree_node_boot*
|
||||
create_boot_catalog_node(struct iso_tree_node_dir *parent,
|
||||
const char *name)
|
||||
{
|
||||
struct iso_tree_node_boot_catalog *boot;
|
||||
struct iso_tree_node_boot *boot;
|
||||
|
||||
assert( parent && name );
|
||||
assert( (parent && name) || (!parent && !name) );
|
||||
|
||||
boot = calloc(1, sizeof(struct iso_tree_node_boot_catalog));
|
||||
boot = calloc(1, sizeof(struct iso_tree_node_boot));
|
||||
boot->node.attrib.st_mode = S_IFREG | 0444;
|
||||
boot->node.attrib.st_atime =
|
||||
boot->node.attrib.st_mtime =
|
||||
boot->node.attrib.st_ctime = time(NULL);
|
||||
boot->node.type = LIBISO_NODE_BOOTCATALOG;
|
||||
boot->node.name = strdup(name);
|
||||
iso_tree_add_child(parent, (struct iso_tree_node*) boot);
|
||||
boot->node.attrib.st_size = 2048;
|
||||
boot->node.type = LIBISO_NODE_BOOT;
|
||||
boot->node.name = name ? strdup(name) : NULL;
|
||||
boot->node.refcount = 1; /* mine */
|
||||
if (parent) {
|
||||
boot->node.refcount++; /* add tree ref */
|
||||
iso_tree_add_child(parent, (struct iso_tree_node*) boot);
|
||||
}
|
||||
return boot;
|
||||
}
|
||||
|
||||
struct el_torito_boot_image *
|
||||
iso_volume_create_boot_catalog(struct iso_volume *volume,
|
||||
struct iso_tree_node *image,
|
||||
enum eltorito_boot_media_type type,
|
||||
struct iso_tree_node_dir *dir,
|
||||
char *name)
|
||||
struct el_torito_boot_image*
|
||||
iso_volume_set_boot_image(struct iso_volume *volume,
|
||||
struct iso_tree_node *image,
|
||||
enum eltorito_boot_media_type type,
|
||||
struct iso_tree_node_dir *dir,
|
||||
char *name)
|
||||
{
|
||||
struct el_torito_boot_image *boot_image;
|
||||
struct iso_tree_node_boot_catalog *boot_node;
|
||||
struct iso_tree_node_boot *cat_node;
|
||||
struct el_torito_boot_catalog *catalog;
|
||||
struct iso_tree_node_file *imgfile;
|
||||
|
||||
assert( volume && !volume->bootcat);
|
||||
assert( image && ISO_ISREG(image) && dir && name);
|
||||
assert(volume && !volume->bootcat);
|
||||
assert(image && ISO_ISREG(image));
|
||||
assert(dir && name);
|
||||
|
||||
boot_image = create_image(image, type);
|
||||
imgfile = (struct iso_tree_node_file*)image;
|
||||
|
||||
if (image->procedence == LIBISO_PREVIMG) {
|
||||
/* FIXME mmm, what to do here? */
|
||||
iso_msg_sorry(LIBISO_EL_TORITO_WRONG_IMG, "Can't use prev. image files "
|
||||
"as boot images");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
boot_image = create_image(imgfile->loc.path, type);
|
||||
if ( !boot_image )
|
||||
return NULL;
|
||||
|
||||
/* create image node */
|
||||
boot_image->node = create_boot_image_node(imgfile);
|
||||
|
||||
/* creates the catalog with the given default image */
|
||||
catalog = malloc(sizeof(struct el_torito_boot_catalog));
|
||||
catalog->nentries = 1;
|
||||
catalog->entries = malloc(sizeof(struct el_torito_boot_image *));
|
||||
catalog->entries[0] = boot_image;
|
||||
catalog->file = malloc(sizeof(struct iso_file));
|
||||
catalog->file->size = 2048;
|
||||
if (!catalog) {
|
||||
el_torito_image_free(boot_image);
|
||||
return NULL;
|
||||
}
|
||||
catalog->image = boot_image;
|
||||
|
||||
/* add catalog file */
|
||||
boot_node = create_boot_catalog_node(dir, name);
|
||||
boot_node->catalog = catalog;
|
||||
cat_node = create_boot_catalog_node(dir, name);
|
||||
catalog->node = cat_node;
|
||||
|
||||
volume->bootcat = catalog;
|
||||
|
||||
return boot_image;
|
||||
}
|
||||
|
||||
struct el_torito_boot_image*
|
||||
iso_volume_set_boot_image_hidden(struct iso_volume *volume, const char* path,
|
||||
enum eltorito_boot_media_type type)
|
||||
{
|
||||
struct el_torito_boot_image *boot_image;
|
||||
struct iso_tree_node_boot *cat_node;
|
||||
struct el_torito_boot_catalog *catalog;
|
||||
|
||||
assert(volume && !volume->bootcat);
|
||||
assert(path);
|
||||
|
||||
boot_image = create_image(path, type);
|
||||
if ( !boot_image )
|
||||
return NULL;
|
||||
|
||||
/* create image node */
|
||||
{
|
||||
struct iso_tree_node_boot *boot;
|
||||
boot = calloc(1, sizeof(struct iso_tree_node_boot));
|
||||
/* we assume the stat won't fail, as we already stat the same file above */
|
||||
stat(path, &boot->node.attrib);
|
||||
boot->node.type = LIBISO_NODE_BOOT;
|
||||
boot->node.refcount = 1; /* mine */
|
||||
boot->loc.path = strdup(path);
|
||||
boot->img = 1; /* it refers to image */
|
||||
boot_image->node = boot;
|
||||
}
|
||||
|
||||
/* creates the catalog with the given default image */
|
||||
catalog = malloc(sizeof(struct el_torito_boot_catalog));
|
||||
if (!catalog) {
|
||||
el_torito_image_free(boot_image);
|
||||
return NULL;
|
||||
}
|
||||
catalog->image = boot_image;
|
||||
|
||||
/* add catalog file */
|
||||
cat_node = create_boot_catalog_node(NULL, NULL);
|
||||
catalog->node = cat_node;
|
||||
|
||||
volume->bootcat = catalog;
|
||||
|
||||
return boot_image;
|
||||
}
|
||||
|
||||
struct el_torito_boot_image*
|
||||
iso_volume_get_boot_image(struct iso_volume *volume,
|
||||
struct iso_tree_node **imgnode,
|
||||
struct iso_tree_node **catnode)
|
||||
{
|
||||
struct el_torito_boot_catalog *catalog;
|
||||
|
||||
assert(volume);
|
||||
|
||||
catalog = volume->bootcat;
|
||||
if (!catalog)
|
||||
return NULL;
|
||||
|
||||
if (imgnode)
|
||||
*imgnode = (struct iso_tree_node*)catalog->image->node;
|
||||
|
||||
if (catnode)
|
||||
*catnode = (struct iso_tree_node*)catalog->node;
|
||||
|
||||
return catalog->image;
|
||||
}
|
||||
|
||||
void
|
||||
iso_volume_remove_boot_image(struct iso_volume *volume)
|
||||
{
|
||||
struct el_torito_boot_catalog *catalog;
|
||||
struct iso_tree_node *catnode;
|
||||
struct iso_tree_node *imgnode;
|
||||
assert(volume);
|
||||
|
||||
catalog = volume->bootcat;
|
||||
if (!catalog)
|
||||
return;
|
||||
|
||||
/* remove node from tree */
|
||||
catnode = (struct iso_tree_node*)catalog->node;
|
||||
if (catnode->parent)
|
||||
iso_tree_node_remove(catnode->parent, catnode);
|
||||
|
||||
/* remove image from tree */
|
||||
imgnode = (struct iso_tree_node*)catalog->image->node;
|
||||
if (imgnode->parent)
|
||||
iso_tree_node_remove(imgnode->parent, imgnode);
|
||||
|
||||
/* remove catalog */
|
||||
el_torito_boot_catalog_free(catalog);
|
||||
volume->bootcat = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
el_torito_set_load_seg(struct el_torito_boot_image *bootimg, int segment)
|
||||
{
|
||||
@ -254,43 +389,20 @@ el_torito_set_no_bootable(struct el_torito_boot_image *bootimg)
|
||||
}
|
||||
|
||||
void
|
||||
el_torito_set_write_boot_info(struct el_torito_boot_image *bootimg)
|
||||
el_torito_patch_isolinux_image(struct el_torito_boot_image *bootimg)
|
||||
{
|
||||
bootimg->patch_isolinux = 1;
|
||||
bootimg->isolinux = 1;
|
||||
}
|
||||
|
||||
void el_torito_boot_catalog_free(struct el_torito_boot_catalog *cat)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
assert(cat);
|
||||
|
||||
for(i = 0; i < cat->nentries; ++i) {
|
||||
free(cat->entries[i]);
|
||||
}
|
||||
free(cat->entries);
|
||||
free(cat->file);
|
||||
el_torito_image_free(cat->image);
|
||||
iso_tree_free((struct iso_tree_node*)cat->node);
|
||||
free(cat);
|
||||
}
|
||||
|
||||
void el_torito_get_image_files(struct ecma119_write_target *t)
|
||||
{
|
||||
size_t i;
|
||||
struct el_torito_boot_catalog *cat = t->catalog;
|
||||
assert(cat);
|
||||
|
||||
for(i = 0; i < cat->nentries; ++i) {
|
||||
|
||||
struct iso_tree_node_file *image = cat->entries[i]->image;
|
||||
struct iso_file *file = iso_file_table_lookup(t->file_table, image);
|
||||
if ( file == NULL ) {
|
||||
file = iso_file_new(image);
|
||||
iso_file_table_add_file(t->file_table, file);
|
||||
}
|
||||
cat->entries[i]->file = file;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the Boot Record Volume Descriptor
|
||||
*/
|
||||
@ -307,7 +419,7 @@ el_torito_write_boot_vol_desc(struct ecma119_write_target *t, uint8_t *buf)
|
||||
memcpy(vol->std_identifier, "CD001", 5);
|
||||
vol->vol_desc_version[0] = 1;
|
||||
memcpy(vol->boot_sys_id, "EL TORITO SPECIFICATION", 23);
|
||||
iso_lsb(vol->boot_catalog, cat->file->block, 4);
|
||||
iso_lsb(vol->boot_catalog, t->catblock, 4);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -333,104 +445,139 @@ write_validation_entry(struct ecma119_write_target *t, uint8_t *buf)
|
||||
}
|
||||
|
||||
static void
|
||||
patch_boot_file(struct el_torito_boot_image *img)
|
||||
patch_boot_image(uint8_t *buf, struct ecma119_write_target *t, ssize_t imgsize)
|
||||
{
|
||||
struct boot_info_table info;
|
||||
int fd;
|
||||
struct boot_info_table *info;
|
||||
uint32_t checksum;
|
||||
ssize_t len;
|
||||
uint8_t buf[4];
|
||||
ssize_t offset;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
/* open image */
|
||||
fd = open(img->image->loc.path, O_RDWR);
|
||||
if ( fd == -1 ) {
|
||||
//TODO what do do? exit or just continue?
|
||||
fprintf(stderr, "Can't patch boot image %s\n", img->image->loc.path);
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
/* compute checksum, as the the sum of all 32 bit words in boot image
|
||||
* from offset 64 */
|
||||
checksum = 0;
|
||||
lseek(fd, (off_t) 64, SEEK_SET);
|
||||
offset = (ssize_t) 64;
|
||||
|
||||
//TODO this can (must) be optimizied by reading to a longer buffer
|
||||
while ( (len = read(fd, buf, 4) ) == 4 ) {
|
||||
checksum += iso_read_lsb(buf, 4);
|
||||
while (offset < imgsize) {
|
||||
checksum += iso_read_lsb(buf + offset, 4);
|
||||
offset += 4;
|
||||
}
|
||||
if ( len != 0 ) {
|
||||
/* error reading file, or file length not multiple of 4 */
|
||||
//TODO what do do? exit or just continue?
|
||||
fprintf(stderr, "Can't patch boot image %s\n", img->image->loc.path);
|
||||
close(fd);
|
||||
return;
|
||||
if (offset != imgsize) {
|
||||
/* file length not multiple of 4 */
|
||||
iso_msg_warn(LIBISO_ISOLINUX_CANT_PATCH,
|
||||
"Unexpected isolinux image length. Patch might not work.");
|
||||
}
|
||||
|
||||
/* fill boot info table */
|
||||
iso_lsb(info.bi_pvd, 16, 4); //FIXME this should be changed when we implement ms
|
||||
iso_lsb(info.bi_file, img->file->block, 4);
|
||||
iso_lsb(info.bi_length, img->image->node.attrib.st_size, 4);
|
||||
iso_lsb(info.bi_csum, checksum, 4);
|
||||
|
||||
/* patch file */
|
||||
lseek(fd, (off_t) 8, SEEK_SET);
|
||||
write(fd, &info, sizeof(info));
|
||||
|
||||
close(fd);
|
||||
}
|
||||
/* patch boot info table */
|
||||
info = (struct boot_info_table*)(buf + 8);
|
||||
memset(info, 0, sizeof(struct boot_info_table));
|
||||
iso_lsb(info->bi_pvd, t->ms_block + 16, 4);
|
||||
iso_lsb(info->bi_file, t->imgblock, 4);
|
||||
iso_lsb(info->bi_length, imgsize, 4);
|
||||
iso_lsb(info->bi_csum, checksum, 4);
|
||||
}
|
||||
|
||||
void
|
||||
el_torito_patch_image_files(struct ecma119_write_target *t)
|
||||
static void
|
||||
write_boot_image(uint8_t *buf, struct ecma119_write_target *t)
|
||||
{
|
||||
size_t i;
|
||||
struct el_torito_boot_catalog *cat = t->catalog;
|
||||
assert(cat);
|
||||
ssize_t imgsize;
|
||||
struct el_torito_boot_image *image;
|
||||
|
||||
for (i = 0; i < cat->nentries; ++i) {
|
||||
struct el_torito_boot_image *img = cat->entries[i];
|
||||
if ( img->patch_isolinux )
|
||||
patch_boot_file(img);
|
||||
image = t->catalog->image;
|
||||
imgsize= image->node->node.attrib.st_size;
|
||||
|
||||
/* copy image contents to memory buffer */
|
||||
if (image->node->node.procedence == LIBISO_PREVIMG) {
|
||||
int block, nblocks;
|
||||
uint8_t *memloc;
|
||||
assert(t->src);
|
||||
|
||||
block = 0;
|
||||
memloc = buf;
|
||||
nblocks = imgsize ? div_up(imgsize, 2048) : 1;
|
||||
while (block < nblocks) {
|
||||
if (t->src->read_block(t->src,
|
||||
image->node->loc.block + block, memloc)) {
|
||||
iso_msg_sorry(LIBISO_CANT_READ_IMG,
|
||||
"Unable to read boot image from previous image.");
|
||||
break; /* exit loop */
|
||||
}
|
||||
memloc += 2048;
|
||||
++block;
|
||||
}
|
||||
} else {
|
||||
int fd;
|
||||
ssize_t nread, tread;
|
||||
uint8_t *memloc;
|
||||
const char *path = image->node->loc.path;
|
||||
memloc = buf;
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
iso_msg_sorry(LIBISO_CANT_READ_FILE,
|
||||
"Can't open boot image file for reading. Skipping");
|
||||
return;
|
||||
}
|
||||
|
||||
tread = 0;
|
||||
while (tread < imgsize) {
|
||||
nread = read(fd, memloc, t->block_size);
|
||||
if (nread <= 0) {
|
||||
iso_msg_sorry(LIBISO_CANT_READ_FILE,
|
||||
"Problem reading boot image file. Skipping");
|
||||
break; /* exit loop */
|
||||
}
|
||||
tread += nread;
|
||||
memloc += nread;
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
if (image->isolinux) {
|
||||
/* we need to patch the image */
|
||||
patch_boot_image(buf, t, imgsize);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write one section entry.
|
||||
* Currently this is used for both default and other entries since we
|
||||
* put selection criteria no 0 (no sel. criteria)
|
||||
* Currently this is used only for default image (the only supported just now)
|
||||
*/
|
||||
static void
|
||||
write_section_entry(uint8_t *buf, struct el_torito_boot_image *img)
|
||||
write_section_entry(uint8_t *buf, struct ecma119_write_target *t)
|
||||
{
|
||||
struct el_torito_boot_image *img;
|
||||
struct el_torito_section_entry *se =
|
||||
(struct el_torito_section_entry*)buf;
|
||||
|
||||
img = t->catalog->image;
|
||||
|
||||
assert(img);
|
||||
|
||||
se->boot_indicator[0] = img->bootable ? 0x88 : 0x00;
|
||||
se->boot_media_type[0] = img->type;
|
||||
iso_lsb(se->load_seg, img->load_seg, 2);
|
||||
se->system_type[0] = 0; //TODO need to get the partition type
|
||||
se->system_type[0] = img->partition_type;
|
||||
iso_lsb(se->sec_count, img->load_size, 2);
|
||||
iso_lsb(se->block, img->file->block, 4);
|
||||
iso_lsb(se->block, t->imgblock, 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write El-Torito Boot Catalog
|
||||
* Write El-Torito Boot Catalog plus image
|
||||
*/
|
||||
static void
|
||||
write_catalog(struct ecma119_write_target *t, uint8_t *buf)
|
||||
{
|
||||
struct el_torito_boot_catalog *cat = t->catalog;
|
||||
assert(cat);
|
||||
assert(cat->nentries >= 1 && cat->nentries < 63);
|
||||
assert(cat->image);
|
||||
|
||||
write_validation_entry(t, buf);
|
||||
|
||||
/* write default entry */
|
||||
write_section_entry(buf + 32, cat->entries[0]);
|
||||
write_section_entry(buf + 32, t);
|
||||
|
||||
//TODO write all images
|
||||
write_boot_image(buf + 2048, t);
|
||||
}
|
||||
|
||||
void
|
||||
@ -446,9 +593,27 @@ el_torito_wr_boot_vol_desc(struct ecma119_write_target *t, uint8_t *buf)
|
||||
void
|
||||
el_torito_wr_catalog(struct ecma119_write_target *t, uint8_t *buf)
|
||||
{
|
||||
off_t size;
|
||||
off_t imgsize;
|
||||
assert(t->catalog);
|
||||
|
||||
/*
|
||||
* Note that when this is called, we need to write el-torito info to
|
||||
* image. Note, however, that the image could come from a previous session
|
||||
* and maybe we don't know its size
|
||||
*/
|
||||
|
||||
imgsize = t->catalog->image->node->node.attrib.st_size;
|
||||
if (imgsize == 0) {
|
||||
iso_msg_warn(LIBISO_EL_TORITO_BLIND_COPY,
|
||||
"Can get boot image size, only one block will be copied");
|
||||
imgsize = 2048;
|
||||
}
|
||||
|
||||
size = 2048 + div_up(imgsize, t->block_size);
|
||||
|
||||
ecma119_start_chunking(t,
|
||||
write_catalog,
|
||||
2048,
|
||||
size,
|
||||
buf);
|
||||
}
|
||||
|
@ -5,52 +5,66 @@
|
||||
#include "file.h"
|
||||
#include "ecma119.h"
|
||||
|
||||
/**
|
||||
* Location of the boot catalog
|
||||
*/
|
||||
struct iso_tree_node_boot_catalog
|
||||
{
|
||||
struct iso_tree_node node;
|
||||
struct el_torito_boot_catalog *catalog;
|
||||
};
|
||||
|
||||
struct el_torito_boot_catalog {
|
||||
int nentries;
|
||||
struct el_torito_boot_image **entries;
|
||||
struct iso_file *file; /**< The catalog file */
|
||||
struct iso_tree_node_boot *node; /* node of the catalog */
|
||||
struct el_torito_boot_image *image; /* default boot image */
|
||||
enum tree_node_from proc; /* whether the catalog is new or read from a
|
||||
* prev session/image */
|
||||
};
|
||||
|
||||
struct el_torito_boot_image {
|
||||
unsigned char bootable; /**< If the entry is bootable. */
|
||||
unsigned char patch_isolinux; /**< If the image will be patched */
|
||||
struct iso_tree_node_boot *node;
|
||||
|
||||
unsigned int bootable:1; /**< If the entry is bootable. */
|
||||
unsigned int isolinux:1; /**< If the image will be patched */
|
||||
unsigned char type; /**< The type of image */
|
||||
unsigned char partition_type; /**< type of partition for HD-emul images */
|
||||
short load_seg; /**< Load segment for the initial boot image. */
|
||||
short load_size; /**< Number of sector to load. */
|
||||
struct iso_tree_node_file *image;
|
||||
struct iso_file *file;
|
||||
};
|
||||
|
||||
/*struct el_torito_boot_entry *
|
||||
el_torito_add_boot_entry(struct el_torito_boot_catalog *cat,
|
||||
struct iso_tree_node_file *image);
|
||||
*/
|
||||
struct el_torito_validation_entry {
|
||||
uint8_t header_id BP(1, 1);
|
||||
uint8_t platform_id BP(2, 2);
|
||||
uint8_t reserved BP(3, 4);
|
||||
uint8_t id_string BP(5, 28);
|
||||
uint8_t checksum BP(29, 30);
|
||||
uint8_t key_byte1 BP(31, 31);
|
||||
uint8_t key_byte2 BP(32, 32);
|
||||
};
|
||||
|
||||
struct el_torito_default_entry {
|
||||
uint8_t boot_indicator BP(1, 1);
|
||||
uint8_t boot_media_type BP(2, 2);
|
||||
uint8_t load_seg BP(3, 4);
|
||||
uint8_t system_type BP(5, 5);
|
||||
uint8_t unused1 BP(6, 6);
|
||||
uint8_t sec_count BP(7, 8);
|
||||
uint8_t block BP(9, 12);
|
||||
uint8_t unused2 BP(13, 32);
|
||||
};
|
||||
|
||||
struct el_torito_section_header_entry {
|
||||
uint8_t header_indicator BP(1, 1);
|
||||
uint8_t platform_id BP(2, 2);
|
||||
uint8_t number BP(3, 4);
|
||||
uint8_t character BP(5, 32);
|
||||
};
|
||||
|
||||
struct el_torito_section_entry {
|
||||
uint8_t boot_indicator BP(1, 1);
|
||||
uint8_t boot_media_type BP(2, 2);
|
||||
uint8_t load_seg BP(3, 4);
|
||||
uint8_t system_type BP(5, 5);
|
||||
uint8_t unused1 BP(6, 6);
|
||||
uint8_t sec_count BP(7, 8);
|
||||
uint8_t block BP(9, 12);
|
||||
uint8_t selec_criteria BP(13, 13);
|
||||
uint8_t vendor_sc BP(14, 32);
|
||||
};
|
||||
|
||||
void el_torito_boot_catalog_free(struct el_torito_boot_catalog *cat);
|
||||
|
||||
/**
|
||||
* For each boot image file, this gets the related iso_file object.
|
||||
* In most cases, the file is already in the hash table. However, if the
|
||||
* boot record is hidden in both ISO/RR and joliet trees, this ensures
|
||||
* that boot images will be written to image.
|
||||
*/
|
||||
void el_torito_get_image_files(struct ecma119_write_target *t);
|
||||
|
||||
/**
|
||||
* Patch image files if selected. This is needed for isolinux boot images
|
||||
*/
|
||||
void el_torito_patch_image_files(struct ecma119_write_target *t);
|
||||
|
||||
/**
|
||||
* Write the Boot Record Volume Descriptor
|
||||
*/
|
||||
@ -60,6 +74,9 @@ el_torito_write_boot_vol_desc(struct ecma119_write_target *t, uint8_t *buf);
|
||||
void
|
||||
el_torito_wr_boot_vol_desc(struct ecma119_write_target *t, uint8_t *buf);
|
||||
|
||||
/**
|
||||
* Write catalog + image
|
||||
*/
|
||||
void
|
||||
el_torito_wr_catalog(struct ecma119_write_target *t, uint8_t *buf);
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "util.h"
|
||||
#include "volume.h"
|
||||
#include "eltorito.h"
|
||||
#include "messages.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
@ -40,14 +41,14 @@ create_node(struct ecma119_write_target *t,
|
||||
}
|
||||
ret->info.file = file;
|
||||
ret->type = JOLIET_FILE;
|
||||
} else {
|
||||
} else if (ISO_ISBOOT(iso)) {
|
||||
/* it's boot catalog info */
|
||||
struct iso_tree_node_boot_catalog *iso_b =
|
||||
(struct iso_tree_node_boot_catalog *) iso;
|
||||
struct iso_file *file;
|
||||
file = iso_b->catalog->file;
|
||||
ret->info.file = file;
|
||||
ret->type = JOLIET_FILE;
|
||||
struct iso_tree_node_boot *boot = (struct iso_tree_node_boot*) iso;
|
||||
ret->info.boot_img = boot->img;
|
||||
ret->type = JOLIET_BOOT;
|
||||
} else {
|
||||
/* this should never happen */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -66,7 +67,7 @@ create_tree(struct ecma119_write_target *t,
|
||||
|
||||
switch (iso->type) {
|
||||
case LIBISO_NODE_FILE:
|
||||
case LIBISO_NODE_BOOTCATALOG:
|
||||
case LIBISO_NODE_BOOT:
|
||||
root = create_node(t, parent, iso);
|
||||
break;
|
||||
case LIBISO_NODE_DIR:
|
||||
@ -85,9 +86,13 @@ create_tree(struct ecma119_write_target *t,
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//TODO replace this printf
|
||||
printf("Can't add this kind of node to a Joliet tree");
|
||||
{
|
||||
char msg[512];
|
||||
sprintf(msg, "Can't add %s to Joliet tree. This kind of files "
|
||||
"can only be added to a Rock Ridget tree. Skipping", iso->name);
|
||||
iso_msg_note(LIBISO_JOLIET_WRONG_FILE_TYPE, msg);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return root;
|
||||
@ -271,8 +276,19 @@ write_one_dir_record(struct ecma119_write_target *t,
|
||||
if (node->type == JOLIET_DIR) {
|
||||
len = node->info.dir.len;
|
||||
block = node->info.dir.block;
|
||||
} else if (node->type == JOLIET_BOOT) {
|
||||
assert(t->eltorito);
|
||||
if (node->info.boot_img) {
|
||||
block = t->imgblock;
|
||||
len = t->catalog->image->node->node.attrib.st_size;
|
||||
} else {
|
||||
/* we always assume 2048 as catalog len */
|
||||
block = t->catblock;
|
||||
len = 2048;
|
||||
}
|
||||
} else {
|
||||
/* file */
|
||||
assert(node->type == JOLIET_FILE);
|
||||
len = node->info.file->size;
|
||||
block = node->info.file->block;
|
||||
}
|
||||
|
@ -19,7 +19,8 @@ struct iso_tree_node;
|
||||
|
||||
enum joliet_node_type {
|
||||
JOLIET_FILE,
|
||||
JOLIET_DIR
|
||||
JOLIET_DIR,
|
||||
JOLIET_BOOT
|
||||
};
|
||||
|
||||
struct joliet_dir_info {
|
||||
@ -41,6 +42,10 @@ struct joliet_tree_node
|
||||
union {
|
||||
struct iso_file *file;
|
||||
struct joliet_dir_info dir;
|
||||
unsigned int boot_img:1; /** For boot nodes, it identifies if this
|
||||
* corresponds to image(1) or catalog(0).
|
||||
* The block is stored in ecma119_write_target
|
||||
*/
|
||||
} info;
|
||||
};
|
||||
|
||||
|
@ -382,17 +382,35 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
|
||||
------------------------------------------------------------------------------
|
||||
Range "vreixo" : 0x00030000 to 0x0003ffff
|
||||
|
||||
General:
|
||||
0x00031001 (SORRY,HIGH) = Can't read file (ignored)
|
||||
0x00031002 (FATAL,HIGH) = Can't read file (operation canceled)
|
||||
|
||||
Image reading:
|
||||
0x00031000 (FATAL,HIGH) = Unsupported ISO-9660 image
|
||||
0x00031001 (HINT,MEDIUM) = Unsupported Vol Desc that will be ignored
|
||||
0x00031002 (FATAL,HIGH) = Damaged ISO-9660 image
|
||||
0x00031003 (SORRY,HIGH) = Can't read previous image file
|
||||
|
||||
Rock-Ridge:
|
||||
0x00030101 (HINT,MEDIUM) = Unsupported SUSP entry that will be ignored
|
||||
0x00030102 (SORRY,HIGH) = Wrong/damaged SUSP entry
|
||||
0x00030103 (WARNING,MEDIUM)= Multiple SUSP ER entries where found
|
||||
0x00030111 (SORRY,HIGH) = Unsupported RR feature
|
||||
0x00030112 (SORRY,HIGH) = Error in a Rock Ridge entry
|
||||
|
||||
El-Torito:
|
||||
0x00030201 (HINT,MEDIUM) = Unsupported Boot Vol Desc that will be ignored
|
||||
0x00030202 (SORRY,HIGH) = Wrong El-Torito catalog
|
||||
0x00030203 (HINT,MEDIUM) = Unsupported El-Torito feature
|
||||
0x00030204 (SORRY,HIGH) = Invalid file to be an El-Torito image
|
||||
0x00030205 (WARNING,MEDIUM)= Can't properly patch isolinux image
|
||||
0x00030206 (WARNING,MEDIUM)= Copying El-Torito from a previous image without
|
||||
enought info about it
|
||||
|
||||
Joliet:
|
||||
0x00030301 (NOTE,MEDIUM) = Unsupported file type for Joliet tree
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
@ -64,7 +64,7 @@ enum iso_tree_node_type {
|
||||
LIBISO_NODE_DIR,
|
||||
LIBISO_NODE_FILE,
|
||||
LIBISO_NODE_SYMLINK,
|
||||
LIBISO_NODE_BOOTCATALOG
|
||||
LIBISO_NODE_BOOT
|
||||
};
|
||||
|
||||
#define LIBISO_ISDIR(n) (iso_tree_node_get_type(n) == LIBISO_NODE_DIR)
|
||||
@ -89,13 +89,12 @@ struct iso_tree_node_file;
|
||||
struct iso_tree_node_symlink;
|
||||
|
||||
/**
|
||||
* A node that represents a boot catalog
|
||||
* FIXME I'm not very sure how this should be treated.
|
||||
* A node that represents an El-Torito file.
|
||||
*/
|
||||
struct iso_tree_node_boot_catalog;
|
||||
struct iso_tree_node_boot;
|
||||
|
||||
/**
|
||||
* El-Torito boot image
|
||||
* Information about El-Torito boot image.
|
||||
* \see eltorito.h
|
||||
*/
|
||||
struct el_torito_boot_image;
|
||||
@ -213,6 +212,16 @@ struct ecma119_source_opts {
|
||||
int level; /**< ISO level to write at. */
|
||||
int flags; /**< Which extensions to support. */
|
||||
int relaxed_constraints; /**< see ecma119_relaxed_constraints_flag */
|
||||
|
||||
unsigned int copy_eltorito:1;
|
||||
/**<
|
||||
* In multisession discs, select whether to copy el-torito catalog
|
||||
* and boot image. Copy is needed for isolinux images, that need to
|
||||
* be patched. However, it can lead to problems when the image is
|
||||
* not present in the iso filesystem, because we can't figure out
|
||||
* its size. In those cases, we only copy 1 block of data.
|
||||
*/
|
||||
|
||||
unsigned int no_cache_inodes:1;
|
||||
/**< If use inode caching or not. Set it to 1 to prevent
|
||||
* inode caching.
|
||||
@ -283,6 +292,9 @@ struct ecma119_source_opts {
|
||||
* 64KiB, where libisofs will write the contents that should
|
||||
* be written at the beginning of a overwriteable media, to
|
||||
* grow the image.
|
||||
* You shoudl initialize the buffer either with 0s, or with
|
||||
* the contents of the first blocks of the image you're
|
||||
* growing. In most cases, 0 is good enought.
|
||||
*/
|
||||
};
|
||||
|
||||
@ -386,6 +398,8 @@ int libisofs_errno;
|
||||
#define UNEXPECTED_FILE_TYPE 3
|
||||
/* invalid boot image size */
|
||||
#define ELTORITO_WRONG_IMAGE_SIZE 4
|
||||
/* invalid image */
|
||||
#define ELTORITO_WRONG_IMAGE 5
|
||||
|
||||
/**
|
||||
* Controls the bahavior of iso_tree_radd_dir function
|
||||
@ -553,6 +567,10 @@ const char *iso_volume_get_biblio_file_id(struct iso_volume *volume);
|
||||
/**
|
||||
* Create a bootable volume by adding a El-Torito boot image.
|
||||
*
|
||||
* This also add a catalog tree node to the image filesystem tree. The tree
|
||||
* node for the image will be replaced with a iso_tree_node_boot node, that
|
||||
* acts as a placeholder for the real image.
|
||||
*
|
||||
* \param volume The volume to make bootable.
|
||||
* \param image The tree node with the file to use as default boot image.
|
||||
* \param type The boot media type. This can be one of 3 types:
|
||||
@ -573,16 +591,60 @@ const char *iso_volume_get_biblio_file_id(struct iso_volume *volume);
|
||||
*
|
||||
* \pre \p volume is a volume without any boot catalog yet
|
||||
* \pre \p image is a file tree node already inserted in the volume tree.
|
||||
* \pre \p image is a file tree node that refers to a newly added file, not
|
||||
* one from a previous session. FIXME allow prev session files too
|
||||
* \pre \p dir is a directory node already inserted in the volume tree.
|
||||
* \pre \p name There isn't any dir child with the same name.
|
||||
*
|
||||
*/
|
||||
struct el_torito_boot_image *
|
||||
iso_volume_create_boot_catalog(struct iso_volume *volume,
|
||||
struct iso_tree_node *image,
|
||||
enum eltorito_boot_media_type type,
|
||||
struct iso_tree_node_dir *dir,
|
||||
char *name);
|
||||
struct el_torito_boot_image*
|
||||
iso_volume_set_boot_image(struct iso_volume *volume,
|
||||
struct iso_tree_node *image,
|
||||
enum eltorito_boot_media_type type,
|
||||
struct iso_tree_node_dir *dir,
|
||||
char *name);
|
||||
|
||||
struct el_torito_boot_image*
|
||||
iso_volume_set_boot_image_hidden(struct iso_volume *volume,
|
||||
const char* path,
|
||||
enum eltorito_boot_media_type type);
|
||||
|
||||
/**
|
||||
* Get El-Torito boot image of the volume, if any.
|
||||
*
|
||||
* This can be useful, for example, to check if a volume read from a previous
|
||||
* session or an existing image is bootable. It can also be useful to get
|
||||
* the image and catalog tree nodes. An application would want those, for
|
||||
* example, to prevent the user removing it.
|
||||
*
|
||||
* Both tree nodes are owned by libisofs and should not be freed. You can check
|
||||
* if the node is already on the tree by getting its parent (note that when
|
||||
* reading El-Torito info from a previous image, the nodes might not be on
|
||||
* the tree even if you haven't removed them). Remember that you'll need to
|
||||
* get a new ref (with iso_tree_node_ref()) before inserting them again to the
|
||||
* tree, and probably you will also need to set the name or permissions.
|
||||
*
|
||||
* \param imgnode When not NULL, it will be filled with the image tree node, if
|
||||
* any.
|
||||
* \param catnode When not NULL, it will be filled with the catalog tree node,
|
||||
* if any.
|
||||
*
|
||||
* \return The default El-Torito bootable image, or NULL is the volume is not
|
||||
* bootable.
|
||||
*/
|
||||
struct el_torito_boot_image*
|
||||
iso_volume_get_boot_image(struct iso_volume *volume,
|
||||
struct iso_tree_node **imgnode,
|
||||
struct iso_tree_node **catnode);
|
||||
|
||||
/**
|
||||
* Removes the El-Torito bootable image. Both the catalog and image tree nodes
|
||||
* are also removed from the image filesystem tree, if there.
|
||||
* If the volume is not bootable (don't have el-torito image) this function is
|
||||
* a nop.
|
||||
*/
|
||||
void
|
||||
iso_volume_remove_boot_image(struct iso_volume *volume);
|
||||
|
||||
/**
|
||||
* Sets the load segment for the initial boot image. This is only for
|
||||
@ -608,12 +670,11 @@ el_torito_set_no_bootable(struct el_torito_boot_image *bootimg);
|
||||
/**
|
||||
* Specifies that this image needs to be patched. This involves the writting
|
||||
* of a 56 bytes boot information table at offset 8 of the boot image file.
|
||||
* Be aware that libisofs will modify original boot image file, so do a backup
|
||||
* if needed.
|
||||
* The original boot image file won't be modified.
|
||||
* This is needed for isolinux boot images.
|
||||
*/
|
||||
void
|
||||
el_torito_set_write_boot_info(struct el_torito_boot_image *bootimg);
|
||||
el_torito_patch_isolinux_image(struct el_torito_boot_image *bootimg);
|
||||
|
||||
/**
|
||||
* Locate a node by its path on disc.
|
||||
|
@ -29,6 +29,13 @@ void iso_msg_debug(char *msg_text)
|
||||
msg_text, 0, 0);
|
||||
}
|
||||
|
||||
void iso_msg_note(int error_code, char *msg_text)
|
||||
{
|
||||
libdax_msgs_submit(libdax_messenger, -1, error_code,
|
||||
LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_MEDIUM,
|
||||
msg_text, 0, 0);
|
||||
}
|
||||
|
||||
void iso_msg_hint(int error_code, char *msg_text)
|
||||
{
|
||||
libdax_msgs_submit(libdax_messenger, -1, error_code,
|
||||
|
@ -7,12 +7,19 @@
|
||||
|
||||
#include "libdax_msgs.h"
|
||||
|
||||
/** Can't read file (ignored) */
|
||||
#define LIBISO_CANT_READ_FILE 0x00031001
|
||||
/** Can't read file (operation canceled) */
|
||||
#define LIBISO_FILE_READ_ERROR 0x00031002
|
||||
|
||||
/** Unsupported image feature */
|
||||
#define LIBISO_IMG_UNSUPPORTED 0x00031000
|
||||
/** Unsupported Vol Desc that will be ignored */
|
||||
#define LIBISO_UNSUPPORTED_VD 0x00031001
|
||||
/** damaged image */
|
||||
#define LIBISO_WRONG_IMG 0x00031002
|
||||
/** Can't read previous image file */
|
||||
#define LIBISO_CANT_READ_IMG 0x00031003
|
||||
|
||||
/* Unsupported SUSP entry */
|
||||
#define LIBISO_SUSP_UNHANLED 0x00030101
|
||||
@ -25,8 +32,26 @@
|
||||
/** Error in a Rock Ridge entry. */
|
||||
#define LIBISO_RR_ERROR 0x00030112
|
||||
|
||||
/** Unsupported boot vol desc. */
|
||||
#define LIBISO_BOOT_VD_UNHANLED 0x00030201
|
||||
/** Wrong or damaged el-torito catalog */
|
||||
#define LIBISO_EL_TORITO_WRONG 0x00030202
|
||||
/** Unsupproted el-torito feature */
|
||||
#define LIBISO_EL_TORITO_UNHANLED 0x00030203
|
||||
/** Trying to add an invalid file as a El-Torito image */
|
||||
#define LIBISO_EL_TORITO_WRONG_IMG 0x00030204
|
||||
/** Can't properly patch isolinux image */
|
||||
#define LIBISO_ISOLINUX_CANT_PATCH 0x00030205
|
||||
/** Copying El-Torito from a previous image without enought info about it */
|
||||
#define LIBISO_EL_TORITO_BLIND_COPY 0x00030206
|
||||
|
||||
/** Unsupported file type for Joliet tree */
|
||||
#define LIBISO_JOLIET_WRONG_FILE_TYPE 0x00030301
|
||||
|
||||
void iso_msg_debug(char *msg_text);
|
||||
|
||||
void iso_msg_note(int error_code, char *msg_text);
|
||||
|
||||
void iso_msg_hint(int error_code, char *msg_text);
|
||||
|
||||
void iso_msg_warn(int error_code, char *msg_text);
|
||||
|
@ -469,6 +469,8 @@ iso_tree_node_ref(struct iso_tree_node *node)
|
||||
void
|
||||
iso_tree_free(struct iso_tree_node *root)
|
||||
{
|
||||
if (!root)
|
||||
return;
|
||||
if (--root->refcount < 1) {
|
||||
if ( ISO_ISDIR(root) ) {
|
||||
size_t i;
|
||||
@ -487,6 +489,11 @@ iso_tree_free(struct iso_tree_node *root)
|
||||
file = (struct iso_tree_node_file *) root;
|
||||
if (root->procedence == LIBISO_NEW)
|
||||
free(file->loc.path);
|
||||
} else if ( ISO_ISBOOT(root) ) {
|
||||
struct iso_tree_node_boot *boot;
|
||||
boot = (struct iso_tree_node_boot *) root;
|
||||
if (root->procedence == LIBISO_NEW && boot->img)
|
||||
free(boot->loc.path);
|
||||
}
|
||||
free(root->name);
|
||||
free(root);
|
||||
|
@ -95,6 +95,20 @@ struct iso_tree_node_dir
|
||||
struct iso_tree_node **children;
|
||||
};
|
||||
|
||||
/**
|
||||
* Tree node that corresponds to some El-Torito artifact.
|
||||
* This can be either the boot catalog or a bootable image.
|
||||
*/
|
||||
struct iso_tree_node_boot
|
||||
{
|
||||
struct iso_tree_node node;
|
||||
unsigned int img:1; /*< 1 if img, 0 if catalog */
|
||||
union {
|
||||
char *path; /**< the path of the file on local filesystem */
|
||||
uint32_t block; /**< If the file is from a previous session.*/
|
||||
} loc;
|
||||
};
|
||||
|
||||
/**
|
||||
* An iterator for directory children.
|
||||
*/
|
||||
@ -151,5 +165,6 @@ void iso_tree_print_verbose(const struct iso_tree_node *root,
|
||||
#define ISO_ISDIR(n) (n->type == LIBISO_NODE_DIR)
|
||||
#define ISO_ISREG(n) (n->type == LIBISO_NODE_FILE)
|
||||
#define ISO_ISLNK(n) (n->type == LIBISO_NODE_SYMLINK)
|
||||
#define ISO_ISBOOT(n) (n->type == LIBISO_NODE_BOOT)
|
||||
|
||||
#endif /* LIBISO_TREE_H */
|
||||
|
12
test/iso.c
12
test/iso.c
@ -119,10 +119,14 @@ int main(int argc, char **argv)
|
||||
if (!img) {
|
||||
err(1, "boot image patch is not valid");
|
||||
}
|
||||
bootimg = iso_volume_create_boot_catalog(volume, img, ELTORITO_NO_EMUL,
|
||||
bootimg = iso_volume_set_boot_image(volume, img, ELTORITO_NO_EMUL,
|
||||
boot, "boot.cat");
|
||||
el_torito_set_load_size(bootimg, 4);
|
||||
el_torito_set_write_boot_info(bootimg);
|
||||
el_torito_patch_isolinux_image(bootimg);
|
||||
|
||||
/* Or just this for hidden img
|
||||
* iso_volume_set_boot_image_hidden(volume, boot_img, ELTORITO_NO_EMUL);
|
||||
*/
|
||||
}
|
||||
|
||||
volset = iso_volset_new( volume, "VOLSETID" );
|
||||
@ -138,8 +142,8 @@ int main(int argc, char **argv)
|
||||
memset(&opts, 0, sizeof(struct ecma119_source_opts));
|
||||
opts.level = level;
|
||||
opts.flags = flags;
|
||||
opts.relaxed_constraints = 0;//constraints;
|
||||
opts.input_charset = NULL;//"UTF-8";
|
||||
opts.relaxed_constraints = 0;
|
||||
opts.input_charset = NULL;
|
||||
opts.ouput_charset = "UTF-8";
|
||||
|
||||
src = iso_source_new_ecma119(volset, &opts);
|
||||
|
@ -165,8 +165,9 @@ int main(int argc, char **argv)
|
||||
wopts.relaxed_constraints = 0;
|
||||
wopts.input_charset = "UTF-8";
|
||||
wopts.ouput_charset = "UTF-8";
|
||||
wopts.ms_block = ropts.size;
|
||||
wopts.overwrite = malloc(32*2048);
|
||||
/* round up to 32kb aligment = 16 block*/
|
||||
wopts.ms_block = ((ropts.size + 15) / 16 ) * 16;
|
||||
wopts.overwrite = calloc(32, 2048);
|
||||
|
||||
wsrc = iso_source_new_ecma119(volset, &wopts);
|
||||
|
||||
@ -193,7 +194,7 @@ int main(int argc, char **argv)
|
||||
burn_write_opts_set_underrun_proof(burn_options, 1);
|
||||
|
||||
//mmm, check for 32K alignment?
|
||||
burn_write_opts_set_start_byte(burn_options, ropts.size * 2048);
|
||||
burn_write_opts_set_start_byte(burn_options, wopts.ms_block * 2048);
|
||||
|
||||
if (burn_write_opts_auto_write_type(burn_options, target_disc,
|
||||
reasons, 0) == BURN_WRITE_NONE) {
|
||||
|
@ -64,11 +64,30 @@ print_dir(struct iso_tree_node_dir *dir, int level)
|
||||
print_permissions(iso_tree_node_get_permissions(node));
|
||||
printf(" %s -> %s \n", iso_tree_node_get_name(node),
|
||||
iso_tree_node_symlink_get_dest((struct iso_tree_node_symlink*)node) );
|
||||
}
|
||||
} else {
|
||||
/* boot catalog */
|
||||
printf("%s-[C] ", sp);
|
||||
print_permissions(iso_tree_node_get_permissions(node));
|
||||
printf(" %s\n", iso_tree_node_get_name(node) );
|
||||
}
|
||||
}
|
||||
iso_tree_iter_free(iter);
|
||||
}
|
||||
|
||||
static void
|
||||
check_el_torito(struct iso_volume *volume)
|
||||
{
|
||||
struct iso_tree_node *cat, *img;
|
||||
|
||||
if (iso_volume_get_boot_image(volume, &img, &cat)) {
|
||||
|
||||
printf("\nEL-TORITO INFORMATION\n");
|
||||
printf("=====================\n\n");
|
||||
printf("Catalog: %s\n", iso_tree_node_get_name(cat) );
|
||||
printf("Image: %s\n", iso_tree_node_get_name(img) );
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct ecma119_read_opts opts;
|
||||
@ -131,6 +150,8 @@ int main(int argc, char **argv)
|
||||
|
||||
print_dir(iso_volume_get_root(volume), 0);
|
||||
|
||||
check_el_torito(volume);
|
||||
|
||||
printf("\n\n");
|
||||
|
||||
data_source_free(src);
|
||||
|
Loading…
Reference in New Issue
Block a user