Handling of El-Torito boot catalog at low level.
This commit is contained in:
parent
2ad6f5f667
commit
4f029437e2
@ -854,6 +854,9 @@ int ecma119_image_new(IsoImage *src, Ecma119WriteOpts *opts, Ecma119Image **img)
|
||||
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, "");
|
||||
target->input_charset = strdup(nl_langinfo(CODESET));
|
||||
|
@ -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;
|
||||
@ -107,6 +108,13 @@ struct ecma119_image
|
||||
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
|
||||
* filled by 0s that we put between the directory structures and the file
|
||||
|
@ -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:
|
||||
{
|
||||
|
212
src/eltorito.c
212
src/eltorito.c
@ -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
|
||||
*/
|
||||
|
24
src/joliet.c
24
src/joliet.c
@ -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…
Reference in New Issue
Block a user