From 004aefd0b7acad10c630d430705de147195d3474 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Sun, 3 Jul 2011 21:02:19 +0200 Subject: [PATCH] New API call iso_image_get_bootcat() --- ChangeLog | 4 ++ libisofs/eltorito.c | 27 ++++++++++++++ libisofs/eltorito.h | 8 ++++ libisofs/fs_image.c | 86 ++++++++++++++++++++++++++++++++++++++++--- libisofs/libisofs.h | 29 +++++++++++++++ libisofs/libisofs.ver | 1 + libisofs/node.c | 9 +++++ 7 files changed, 159 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 660b26d..ea00310 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +bzr branch lp:libisofs/for-libisoburn (to become libisofs-1.1.2.tar.gz) +=============================================================================== +- no novelties yet + libisofs-1.1.0.tar.gz Sat Jun 18 2011 =============================================================================== diff --git a/libisofs/eltorito.c b/libisofs/eltorito.c index 8e5a1ab..88ec3bf 100644 --- a/libisofs/eltorito.c +++ b/libisofs/eltorito.c @@ -275,6 +275,9 @@ int iso_tree_add_boot_node(IsoDir *parent, const char *name, IsoBoot **boot) free(node); return ISO_OUT_OF_MEM; } + node->lba = 0; + node->size = 0; + node->content = NULL; /* atributes from parent */ node->node.mode = S_IFREG | (parent->node.mode & 0444); @@ -598,6 +601,30 @@ int iso_image_get_boot_image(IsoImage *image, ElToritoBootImage **boot, return ISO_SUCCESS; } +int iso_image_get_bootcat(IsoImage *image, IsoBoot **catnode, uint32_t *lba, + char **content, off_t *size) +{ + IsoBoot *bootcat; + + *catnode = NULL; + *lba = 0; + *content = NULL; + *size = 0; + bootcat = image->bootcat->node; + if (bootcat == NULL) + return 0; + *catnode = bootcat; + *lba = bootcat->lba; + *size = bootcat->size; + if (bootcat->size > 0 && bootcat->content != NULL) { + *content = calloc(1, bootcat->size); + if (*content == NULL) + return ISO_OUT_OF_MEM; + memcpy(*content, bootcat->content, bootcat->size); + } + return 1; +} + int iso_image_get_all_boot_imgs(IsoImage *image, int *num_boots, ElToritoBootImage ***boots, IsoFile ***bootnodes, int flag) { diff --git a/libisofs/eltorito.h b/libisofs/eltorito.h index a7fb57d..47c8479 100644 --- a/libisofs/eltorito.h +++ b/libisofs/eltorito.h @@ -26,6 +26,14 @@ struct Iso_Boot { IsoNode node; + + /* >>> ts B10703: want to get content of loaded boot catalog */ + /* Vreixo took care not to make it an IsoFile at load time. + So i implement this independently of IsoStream. + */ + uint32_t lba; + off_t size; + char *content; }; /* Not more than 32 so that all entries fit into 2048 bytes */ diff --git a/libisofs/fs_image.c b/libisofs/fs_image.c index b15f139..039b0c2 100644 --- a/libisofs/fs_image.c +++ b/libisofs/fs_image.c @@ -293,6 +293,8 @@ typedef struct uint32_t bootblocks[Libisofs_max_boot_imageS]; uint32_t catblock; /**< Block for El-Torito catalog */ + off_t catsize; /* Size of boot catalog in bytes */ + char *catcontent; /* Whether inode numbers from PX entries shall be discarded */ unsigned int make_new_ino : 1 ; @@ -2078,6 +2080,10 @@ void ifs_fs_free(IsoFilesystem *fs) free(data->biblio_file_id); free(data->input_charset); free(data->local_charset); + + if(data->catcontent != NULL) + free(data->catcontent); + free(data); } @@ -2328,14 +2334,15 @@ ex:; static int read_el_torito_boot_catalog(_ImageFsData *data, uint32_t block) { - int ret, i, rx, last_done, idx; + int ret, i, rx, last_done, idx, bufsize; struct el_torito_validation_entry *ve; struct el_torito_section_header *sh; struct el_torito_section_entry *entry; /* also usable as default_entry */ - unsigned char *buffer = NULL; + unsigned char *buffer = NULL, *rpt; LIBISO_ALLOC_MEM(buffer, unsigned char, BLOCK_SIZE); data->num_bootimgs = 0; + data->catsize = 0; ret = data->src->read_block(data->src, block, buffer); if (ret < 0) { goto ex; @@ -2367,6 +2374,7 @@ int read_el_torito_boot_catalog(_ImageFsData *data, uint32_t block) data->eltorito = 1; /* The Default Entry is declared mandatory */ + data->catsize = 64; data->num_bootimgs = 1; data->platform_ids[0] = ve->platform_id[0]; memcpy(data->id_strings[0], ve->id_string, 24); @@ -2385,10 +2393,21 @@ int read_el_torito_boot_catalog(_ImageFsData *data, uint32_t block) for (rx = 64; (buffer[rx] & 0xfe) == 0x90 && !last_done; rx += 32) { last_done = buffer[rx] & 1; /* Read Section Header */ + + /* >>> ts B10703 : load a new buffer if needed */; + sh = (struct el_torito_section_header *) (buffer + rx); + data->catsize += 32; for (i = 0; i < sh->num_entries[0]; i++) { rx += 32; + data->catsize += 32; + + /* >>> ts B10703 : load a new buffer if needed */; + if (data->num_bootimgs >= Libisofs_max_boot_imageS) { + + /* >>> ts B10703 : need to continue rather than abort */; + ret = iso_msg_submit(data->msgid, ISO_EL_TORITO_WARN, 0, "Too many boot images found. List truncated."); goto after_bootblocks; @@ -2410,6 +2429,27 @@ int read_el_torito_boot_catalog(_ImageFsData *data, uint32_t block) } } after_bootblocks:; + if(data->catsize > 0) { + if(data->catcontent != NULL) + free(data->catcontent); + if(data->catsize > 10 * BLOCK_SIZE) + data->catsize = 10 * BLOCK_SIZE; + bufsize = data->catsize; + if (bufsize % BLOCK_SIZE) + bufsize += BLOCK_SIZE - (bufsize % BLOCK_SIZE); + data->catcontent = calloc(bufsize , 1); + if(data->catcontent == NULL) { + data->catsize = 0; + ret = ISO_OUT_OF_MEM; + goto ex; + } + for(rx = 0; rx < bufsize; rx += BLOCK_SIZE) { + rpt = (unsigned char *) (data->catcontent + rx); + ret = data->src->read_block(data->src, block + rx / BLOCK_SIZE, rpt); + if (ret < 0) + goto ex; + } + } ret = ISO_SUCCESS; ex:; LIBISO_FREE_MEM(buffer); @@ -2531,6 +2571,8 @@ int iso_image_filesystem_new(IsoDataSource *src, struct iso_read_opts *opts, iso_data_source_ref(src); data->open_count = 0; + data->catcontent = NULL; + /* get an id for the filesystem */ data->id = ++fs_dev_id; @@ -2802,9 +2844,10 @@ static int image_builder_create_node(IsoNodeBuilder *builder, IsoImage *image, IsoFileSource *src, IsoNode **node) { - int ret, idx; + int ret, idx, to_copy; struct stat info; IsoNode *new; + IsoBoot *bootcat; char *name; char *dest = NULL; ImageFileSourceData *data; @@ -2861,9 +2904,28 @@ int image_builder_create_node(IsoNodeBuilder *builder, IsoImage *image, free(name); goto ex; } + bootcat = (IsoBoot *) new; + bootcat->lba = data->sections[0].block; + bootcat->size = info.st_size; + if (bootcat->size > 10 * BLOCK_SIZE) + bootcat->size = 10 * BLOCK_SIZE; + bootcat->content = NULL; + if (bootcat->size > 0) { + bootcat->content = calloc(1, bootcat->size); + if (bootcat->content == NULL) { + ret = ISO_OUT_OF_MEM; + free(name); + free(new); + goto ex; + } + to_copy = bootcat->size; + if (bootcat->size > fsdata->catsize) + to_copy = fsdata->catsize; + memcpy(bootcat->content, fsdata->catcontent, to_copy); + } /* and set the image node */ - image->bootcat->node = (IsoBoot*)new; + image->bootcat->node = bootcat; new->type = LIBISO_BOOT; new->refcount = 1; } else { @@ -3463,11 +3525,25 @@ int iso_image_import(IsoImage *image, IsoDataSource *src, "patching may lead to bad results."); } if (image->bootcat->node == NULL) { - IsoNode *node = calloc(1, sizeof(IsoBoot)); + IsoNode *node; + IsoBoot *bootcat; + node = calloc(1, sizeof(IsoBoot)); if (node == NULL) { ret = ISO_OUT_OF_MEM; goto import_revert; } + bootcat = (IsoBoot *) node; + bootcat->lba = data->catblock; + bootcat->size = data->catsize; + bootcat->content = NULL; + if (bootcat->size > 0) { + bootcat->content = calloc(1, bootcat->size); + if (bootcat->content == NULL) { + ret = ISO_OUT_OF_MEM; + goto import_revert; + } + memcpy(bootcat->content, data->catcontent, bootcat->size); + } node->type = LIBISO_BOOT; node->mode = S_IFREG; node->refcount = 1; diff --git a/libisofs/libisofs.h b/libisofs/libisofs.h index 2bc2c9c..51aa7f4 100644 --- a/libisofs/libisofs.h +++ b/libisofs/libisofs.h @@ -2876,6 +2876,35 @@ int iso_image_add_boot_image(IsoImage *image, const char *image_path, int iso_image_get_boot_image(IsoImage *image, ElToritoBootImage **boot, IsoFile **imgnode, IsoBoot **catnode); +/** + * Get detailed information about the boot catalog that was loaded from + * an ISO image. + * The boot catalog links the El Torito boot record at LBA 17 with the + * boot images which are IsoFile objects in the image. The boot catalog + * itself is not a regular file and thus will not deliver an IsoStream. + * Its content is usually quite short and can be obtained by this call. + * + * @param image + * The image to inquire. + * @param catnode + * Will return the boot catalog tree node. No extra ref is taken. + * @param lba + * Will return the block address of the boot catalog in the image. + * @param content + * Will return either NULL or an allocated memory buffer with the + * content bytes of the boot catalog. + * Dispose it by free() when no longer needed. + * @param size + * Will return the number of bytes in content. + * @return + * 1 if reply is valid, 0 if not boot catalog was loaded, < 0 on error. + * + * @since 1.1.2 + */ +int iso_image_get_bootcat(IsoImage *image, IsoBoot **catnode, uint32_t *lba, + char **content, off_t *size); + + /** * Get all El-Torito boot images of an ISO image. * diff --git a/libisofs/libisofs.ver b/libisofs/libisofs.ver index 095990e..c79534d 100644 --- a/libisofs/libisofs.ver +++ b/libisofs/libisofs.ver @@ -88,6 +88,7 @@ iso_image_get_all_boot_imgs; iso_image_get_application_id; iso_image_get_attached_data; iso_image_get_biblio_file_id; +iso_image_get_bootcat; iso_image_get_boot_image; iso_image_get_copyright_file_id; iso_image_get_data_preparer_id; diff --git a/libisofs/node.c b/libisofs/node.c index a3f2542..32926eb 100644 --- a/libisofs/node.c +++ b/libisofs/node.c @@ -19,6 +19,7 @@ #include "aaip_0_2.h" #include "messages.h" #include "util.h" +#include "eltorito.h" #include @@ -78,6 +79,14 @@ void iso_node_unref(IsoNode *node) IsoSymlink *link = (IsoSymlink*) node; free(link->dest); } + break; + case LIBISO_BOOT: + { + IsoBoot *bootcat = (IsoBoot *) node; + if (bootcat->content != NULL) + free(bootcat->content); + } + break; default: /* other kind of nodes does not need to delete anything here */ break;