Implemented support for eltorito on MS discs

This commit is contained in:
Mario Danic 2007-09-01 20:35:53 +00:00
parent 0746d622e4
commit d60193e2d5
20 changed files with 842 additions and 299 deletions

5
TODO
View File

@ -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

View File

@ -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,7 +380,7 @@ ecma119_target_new(struct iso_volset *volset,
t->curblock = t->ms_block /* nwa for ms, usually 0 */
+ 16 /* system area */
+ 1 /* volume desc */
+ 1 /* primary volume desc */
+ 1; /* volume desc terminator */
if (t->eltorito)
@ -411,17 +414,24 @@ ecma119_target_new(struct iso_volset *volset,
/* el-torito? */
if (t->eltorito) {
if (t->write_eltorito) {
/* add catalog block */
t->catalog->file->block = t->curblock;
t->catblock = t->curblock;
t->curblock += div_up(2048, t->block_size);
el_torito_get_image_files(t);
/* 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)

View File

@ -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
*

View File

@ -28,6 +28,7 @@
#include "volume.h"
#include "tree.h"
#include "messages.h"
#include "eltorito.h"
#define BLOCK_SIZE 2048
@ -35,6 +36,121 @@ 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
* given directory propertly.
@ -248,12 +364,22 @@ iso_read_single_directory_record(struct iso_read_info *info,
break;
case S_IFREG:
{
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 =
iso_read_bb(record->block, 4, NULL);
((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;
}

View File

@ -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;
};

View File

@ -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 */

View File

@ -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;
};

View File

@ -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);
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 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);
if (offset != imgsize) {
/* file length not multiple of 4 */
iso_msg_warn(LIBISO_ISOLINUX_CANT_PATCH,
"Unexpected isolinux image length. Patch might not work.");
}
/* 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);
}
static void
write_boot_image(uint8_t *buf, struct ecma119_write_target *t)
{
ssize_t imgsize;
struct el_torito_boot_image *image;
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;
}
/* 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));
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);
}
}
void
el_torito_patch_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 el_torito_boot_image *img = cat->entries[i];
if ( img->patch_isolinux )
patch_boot_file(img);
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);
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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
------------------------------------------------------------------------------

View File

@ -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,17 +591,61 @@ 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 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
* no emulation boot images, and is a NOP for other image types.
@ -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.

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -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 */

View File

@ -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);

View File

@ -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) {

View File

@ -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);