Handling of El-Torito boot catalog at low level.

release-1.5.4.branch
Vreixo Formoso 15 years ago
parent 2ad6f5f667
commit 4f029437e2
  1. 3
      src/ecma119.c
  2. 8
      src/ecma119.h
  3. 42
      src/ecma119_tree.c
  4. 212
      src/eltorito.c
  5. 7
      src/eltorito.h
  6. 32
      src/filesrc.c
  7. 21
      src/filesrc.h
  8. 24
      src/joliet.c

@ -853,6 +853,9 @@ int ecma119_image_new(IsoImage *src, Ecma119WriteOpts *opts, Ecma119Image **img)
target->now = time(NULL);
target->ms_block = opts->ms_block;
target->appendable = opts->appendable;
/* el-torito? */
target->eltorito = (src->bootcat == NULL ? 0 : 1);
/* default to locale charset */
setlocale(LC_CTYPE, "");

@ -34,6 +34,7 @@ struct ecma119_image
/* extensions */
unsigned int rockridge :1;
unsigned int joliet :1;
unsigned int eltorito :1;
/* relaxed constraints */
unsigned int omit_version_numbers :1;
@ -106,6 +107,13 @@ struct ecma119_image
uint32_t joliet_path_table_size;
uint32_t joliet_l_path_table_pos;
uint32_t joliet_m_path_table_pos;
/*
* El-Torito related information
*/
struct el_torito_boot_catalog *catalog;
IsoFileSrc *cat; /**< location of the boot catalog in the new image */
uint32_t imgblock; /**< location of the boot image in the new image */
/*
* Number of pad blocks that we need to write. Padding blocks are blocks

@ -15,6 +15,7 @@
#include "messages.h"
#include "image.h"
#include "stream.h"
#include "eltorito.h"
#include <stdlib.h>
#include <string.h>
@ -160,6 +161,35 @@ int create_file(Ecma119Image *img, IsoFile *iso, Ecma119Node **node)
return ret;
}
/**
* Create a new ECMA-119 node representing a regular file from an El-Torito
* boot catalog
*/
static
int create_boot_cat(Ecma119Image *img, IsoBoot *iso, Ecma119Node **node)
{
int ret;
IsoFileSrc *src;
ret = el_torito_catalog_file_src_create(img, &src);
if (ret < 0) {
return ret;
}
ret = create_ecma119_node(img, (IsoNode*)iso, node);
if (ret < 0) {
/*
* the src doesn't need to be freed, it is free together with
* the Ecma119Image
*/
return ret;
}
(*node)->type = ECMA119_FILE;
(*node)->info.file = src;
return ret;
}
/**
* Create a new ECMA-119 node representing a symbolic link from a iso symlink
* node.
@ -276,9 +306,15 @@ int create_tree(Ecma119Image *image, IsoNode *iso, Ecma119Node **tree,
}
break;
case LIBISO_BOOT:
//TODO
free(iso_name);
return 0;
if (image->eltorito) {
ret = create_boot_cat(image, (IsoBoot*)iso, &node);
} else {
/* log and ignore */
iso_msg_note(image->image->messenger, LIBISO_FILE_IGNORED,
"El-Torito catalog found on a image without El-Torito.",
iso->name);
ret = 0;
}
break;
case LIBISO_DIR:
{

@ -10,6 +10,7 @@
#include "stream.h"
#include "error.h"
#include "fsource.h"
#include "filesrc.h"
#include "image.h"
#include "messages.h"
@ -482,7 +483,7 @@ void el_torito_boot_catalog_free(struct el_torito_boot_catalog *cat)
*/
struct catalog_stream
{
struct el_torito_boot_catalog *catalog;
Ecma119Image *target;
uint8_t buffer[BLOCK_SIZE];
int offset; /* -1 if stream is not openned */
};
@ -508,3 +509,212 @@ write_validation_entry(uint8_t *buf)
}
iso_lsb(ve->checksum, checksum, 2);
}
/**
* Write one section entry.
* Currently this is used only for default image (the only supported just now)
*/
static void
write_section_entry(uint8_t *buf, Ecma119Image *t)
{
struct el_torito_boot_image *img;
struct el_torito_section_entry *se =
(struct el_torito_section_entry*)buf;
img = t->catalog->image;
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] = img->partition_type;
iso_lsb(se->sec_count, img->load_size, 2);
iso_lsb(se->block, t->imgblock, 4);
}
static
int catalog_open(IsoStream *stream)
{
struct catalog_stream *data;
if (stream == NULL) {
return ISO_NULL_POINTER;
}
data = stream->data;
if (data->offset != -1) {
return ISO_FILE_ALREADY_OPENNED;
}
memset(data->buffer, 0, BLOCK_SIZE);
/* fill the buffer with the catalog contents */
write_validation_entry(data->buffer);
/* write default entry */
write_section_entry(data->buffer + 32, data->target);
data->offset = 0;
return ISO_SUCCESS;
}
static
int catalog_close(IsoStream *stream)
{
struct catalog_stream *data;
if (stream == NULL) {
return ISO_NULL_POINTER;
}
data = stream->data;
if (data->offset == -1) {
return ISO_FILE_NOT_OPENNED;
}
data->offset = -1;
return ISO_SUCCESS;
}
static
off_t catalog_get_size(IsoStream *stream)
{
return BLOCK_SIZE;
}
static
int catalog_read(IsoStream *stream, void *buf, size_t count)
{
size_t len;
struct catalog_stream *data;
if (stream == NULL || buf == NULL) {
return ISO_NULL_POINTER;
}
if (count == 0) {
return ISO_WRONG_ARG_VALUE;
}
data = stream->data;
if (data->offset == -1) {
return ISO_FILE_NOT_OPENNED;
}
len = MIN(count, BLOCK_SIZE - data->offset);
memcpy(buf, data->buffer + data->offset, len);
return len;
}
static
int catalog_is_repeatable(IsoStream *stream)
{
return 1;
}
/**
* fs_id will be the id reserved for El-Torito
* dev_id will be 0 for catalog, 1 for boot image (if needed)
* we leave ino_id for future use when we support multiple boot images
*/
static
void catalog_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id,
ino_t *ino_id)
{
*fs_id = ISO_ELTORITO_FS_ID;
*dev_id = 0;
*ino_id = 0;
}
static
char *catalog_get_name(IsoStream *stream)
{
return strdup("El-Torito Boot Catalog");
}
static
void catalog_free(IsoStream *stream)
{
free(stream->data);
}
IsoStreamIface catalog_stream_class = {
catalog_open,
catalog_close,
catalog_get_size,
catalog_read,
catalog_is_repeatable,
catalog_get_id,
catalog_get_name,
catalog_free
};
/**
* Create an IsoStream for writing El-Torito catalog for a given target.
*/
static
int catalog_stream_new(Ecma119Image *target, IsoStream **stream)
{
IsoStream *str;
struct catalog_stream *data;
if (target == NULL || stream == NULL || target->catalog == NULL) {
return ISO_NULL_POINTER;
}
str = malloc(sizeof(IsoStream));
if (str == NULL) {
return ISO_MEM_ERROR;
}
data = malloc(sizeof(struct catalog_stream));
if (str == NULL) {
free(str);
return ISO_MEM_ERROR;
}
/* fill data */
data->target = target;
data->offset = -1;
str->refcount = 1;
str->data = data;
str->class = &catalog_stream_class;
*stream = str;
return ISO_SUCCESS;
}
int el_torito_catalog_file_src_create(Ecma119Image *target, IsoFileSrc **src)
{
int ret;
IsoFileSrc *file;
IsoStream *stream;
if (target == NULL || src == NULL || target->catalog == NULL) {
return ISO_MEM_ERROR;
}
if (target->cat != NULL) {
/* catalog file src already created */
*src = target->cat;
return ISO_SUCCESS;
}
file = malloc(sizeof(IsoFileSrc));
if (file == NULL) {
return ISO_MEM_ERROR;
}
ret = catalog_stream_new(target, &stream);
if (ret < 0) {
free(file);
return ret;
}
/* fill fields */
file->prev_img = 0; /* TODO allow copy of old img catalog???? */
file->block = 0; /* to be filled later */
file->sort_weight = 1000; /* slightly high */
file->stream = stream;
ret = iso_file_src_add(target, file, src);
if (ret <= 0) {
iso_stream_unref(stream);
free(file);
}
return ret;
}

@ -93,4 +93,11 @@ struct el_torito_section_entry {
void el_torito_boot_catalog_free(struct el_torito_boot_catalog *cat);
/**
* Create a IsoFileSrc for writing the el-torito catalog for the given
* target, and add it to target. If the target already has a src for the
* catalog, it just returns.
*/
int el_torito_catalog_file_src_create(Ecma119Image *target, IsoFileSrc **src);
#endif /* LIBISO_ELTORITO_H */

@ -81,6 +81,38 @@ int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
return ISO_SUCCESS;
}
/**
* Add a given IsoFileSrc to the given image target.
*
* The IsoFileSrc will be cached in a tree to prevent the same file for
* being written several times to image. If you call again this function
* with a node that refers to the same source file, the previously
* created one will be returned.
*
* @param img
* The image where this file is to be written
* @param new
* The IsoFileSrc to add
* @param src
* Will be filled with a pointer to the IsoFileSrc really present in
* the tree. It could be different than new if the same file already
* exists in the tree.
* @return
* 1 on success, 0 if file already exists on tree, < 0 error
*/
int iso_file_src_add(Ecma119Image *img, IsoFileSrc *new, IsoFileSrc **src)
{
int ret;
if (img == NULL || new == NULL || src == NULL) {
return ISO_NULL_POINTER;
}
/* insert the filesrc in the tree */
ret = iso_rbtree_insert(img->files, new, (void**)src);
return ret;
}
void iso_file_src_free(void *node)
{
free(node);

@ -43,6 +43,27 @@ int iso_file_src_cmp(const void *n1, const void *n2);
*/
int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src);
/**
* Add a given IsoFileSrc to the given image target.
*
* The IsoFileSrc will be cached in a tree to prevent the same file for
* being written several times to image. If you call again this function
* with a node that refers to the same source file, the previously
* created one will be returned.
*
* @param img
* The image where this file is to be written
* @param new
* The IsoFileSrc to add
* @param src
* Will be filled with a pointer to the IsoFileSrc really present in
* the tree. It could be different than new if the same file already
* exists in the tree.
* @return
* 1 on success, 0 if file already exists on tree, < 0 error
*/
int iso_file_src_add(Ecma119Image *img, IsoFileSrc *new, IsoFileSrc **src);
/**
* Free the IsoFileSrc especific data
*/

@ -13,6 +13,7 @@
#include "error.h"
#include "image.h"
#include "filesrc.h"
#include "eltorito.h"
#include <stdlib.h>
#include <string.h>
@ -118,9 +119,19 @@ int create_node(Ecma119Image *t, IsoNode *iso, JolietNode **node)
}
joliet->info.file = src;
joliet->type = JOLIET_FILE;
} else if (iso->type == LIBISO_BOOT) {
/* it's a el-torito boot catalog, that we write as a file */
IsoFileSrc *src;
ret = el_torito_catalog_file_src_create(t, &src);
if (ret < 0) {
free(joliet);
return ret;
}
joliet->info.file = src;
joliet->type = JOLIET_FILE;
} else {
/* should never happen */
//TODO handle boot nodes?!?
free(joliet);
return ISO_ERROR;
}
@ -205,8 +216,15 @@ int create_tree(Ecma119Image *t, IsoNode *iso, JolietNode **tree, int pathlen)
}
break;
case LIBISO_BOOT:
//TODO
return 0;
if (t->eltorito) {
ret = create_node(t, iso, &node);
} else {
/* log and ignore */
iso_msg_note(t->image->messenger, LIBISO_FILE_IGNORED,
"El-Torito catalog found on a image without El-Torito.",
iso->name);
ret = 0;
}
break;
case LIBISO_SYMLINK:
case LIBISO_SPECIAL:

Loading…
Cancel
Save