Handling of El-Torito boot catalog at low level.

This commit is contained in:
Vreixo Formoso 2008-01-10 18:53:39 +01:00
parent 2ad6f5f667
commit 4f029437e2
8 changed files with 342 additions and 7 deletions

View File

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

View File

@ -34,6 +34,7 @@ struct ecma119_image
/* extensions */ /* extensions */
unsigned int rockridge :1; unsigned int rockridge :1;
unsigned int joliet :1; unsigned int joliet :1;
unsigned int eltorito :1;
/* relaxed constraints */ /* relaxed constraints */
unsigned int omit_version_numbers :1; unsigned int omit_version_numbers :1;
@ -107,6 +108,13 @@ struct ecma119_image
uint32_t joliet_l_path_table_pos; uint32_t joliet_l_path_table_pos;
uint32_t joliet_m_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 * Number of pad blocks that we need to write. Padding blocks are blocks
* filled by 0s that we put between the directory structures and the file * filled by 0s that we put between the directory structures and the file

View File

@ -15,6 +15,7 @@
#include "messages.h" #include "messages.h"
#include "image.h" #include "image.h"
#include "stream.h" #include "stream.h"
#include "eltorito.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -160,6 +161,35 @@ int create_file(Ecma119Image *img, IsoFile *iso, Ecma119Node **node)
return ret; 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 * Create a new ECMA-119 node representing a symbolic link from a iso symlink
* node. * node.
@ -276,9 +306,15 @@ int create_tree(Ecma119Image *image, IsoNode *iso, Ecma119Node **tree,
} }
break; break;
case LIBISO_BOOT: case LIBISO_BOOT:
//TODO if (image->eltorito) {
free(iso_name); ret = create_boot_cat(image, (IsoBoot*)iso, &node);
return 0; } 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; break;
case LIBISO_DIR: case LIBISO_DIR:
{ {

View File

@ -10,6 +10,7 @@
#include "stream.h" #include "stream.h"
#include "error.h" #include "error.h"
#include "fsource.h" #include "fsource.h"
#include "filesrc.h"
#include "image.h" #include "image.h"
#include "messages.h" #include "messages.h"
@ -482,7 +483,7 @@ void el_torito_boot_catalog_free(struct el_torito_boot_catalog *cat)
*/ */
struct catalog_stream struct catalog_stream
{ {
struct el_torito_boot_catalog *catalog; Ecma119Image *target;
uint8_t buffer[BLOCK_SIZE]; uint8_t buffer[BLOCK_SIZE];
int offset; /* -1 if stream is not openned */ int offset; /* -1 if stream is not openned */
}; };
@ -508,3 +509,212 @@ write_validation_entry(uint8_t *buf)
} }
iso_lsb(ve->checksum, checksum, 2); 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;
}

View File

@ -93,4 +93,11 @@ struct el_torito_section_entry {
void el_torito_boot_catalog_free(struct el_torito_boot_catalog *cat); 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 */ #endif /* LIBISO_ELTORITO_H */

View File

@ -81,6 +81,38 @@ int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src)
return ISO_SUCCESS; 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) void iso_file_src_free(void *node)
{ {
free(node); free(node);

View File

@ -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); 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 * Free the IsoFileSrc especific data
*/ */

View File

@ -13,6 +13,7 @@
#include "error.h" #include "error.h"
#include "image.h" #include "image.h"
#include "filesrc.h" #include "filesrc.h"
#include "eltorito.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -118,9 +119,19 @@ int create_node(Ecma119Image *t, IsoNode *iso, JolietNode **node)
} }
joliet->info.file = src; joliet->info.file = src;
joliet->type = JOLIET_FILE; 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 { } else {
/* should never happen */ /* should never happen */
//TODO handle boot nodes?!?
free(joliet); free(joliet);
return ISO_ERROR; return ISO_ERROR;
} }
@ -205,8 +216,15 @@ int create_tree(Ecma119Image *t, IsoNode *iso, JolietNode **tree, int pathlen)
} }
break; break;
case LIBISO_BOOT: case LIBISO_BOOT:
//TODO if (t->eltorito) {
return 0; 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; break;
case LIBISO_SYMLINK: case LIBISO_SYMLINK:
case LIBISO_SPECIAL: case LIBISO_SPECIAL: