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->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));
|
||||||
|
@ -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
|
||||||
|
@ -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:
|
||||||
{
|
{
|
||||||
|
212
src/eltorito.c
212
src/eltorito.c
@ -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;
|
||||||
|
}
|
||||||
|
@ -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 */
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
24
src/joliet.c
24
src/joliet.c
@ -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:
|
||||||
|
Loading…
Reference in New Issue
Block a user