From 5c9c8d2b9b78cf4e1f256fe6874855c1aee458f2 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 6 May 2021 13:11:31 +0100 Subject: [image] Add "imgextract" command for extracting archive images Add the concept of extracting an image from an archive (which could be a single-file archive such as a gzip-compressed file), along with an "imgextract" command to expose this functionality to scripts. Signed-off-by: Michael Brown --- src/core/archive.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 src/core/archive.c (limited to 'src/core/archive.c') diff --git a/src/core/archive.c b/src/core/archive.c new file mode 100644 index 000000000..cd024bde3 --- /dev/null +++ b/src/core/archive.c @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2021 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * You can also choose to distribute this program under the terms of + * the Unmodified Binary Distribution Licence (as given in the file + * COPYING.UBDL), provided that you have satisfied its requirements. + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +#include +#include +#include + +/** @file + * + * Archive images + * + */ + +/** + * Extract archive image + * + * @v image Image + * @v name Extracted image name + * @v extracted Extracted image to fill in + * @ret rc Return status code + */ +int image_extract ( struct image *image, const char *name, + struct image **extracted ) { + char *dot; + int rc; + + /* Check that this image can be used to extract an archive image */ + if ( ! ( image->type && image->type->extract ) ) { + rc = -ENOTSUP; + goto err_unsupported; + } + + /* Allocate new image */ + *extracted = alloc_image ( image->uri ); + if ( ! *extracted ) { + rc = -ENOMEM; + goto err_alloc; + } + + /* Set image name */ + if ( ( rc = image_set_name ( *extracted, + ( name ? name : image->name ) ) ) != 0 ) { + goto err_set_name; + } + + /* Strip any archive or compression suffix from implicit name */ + if ( ( ! name ) && ( (*extracted)->name ) && + ( ( dot = strrchr ( (*extracted)->name, '.' ) ) != NULL ) ) { + *dot = '\0'; + } + + /* Try extracting archive image */ + if ( ( rc = image->type->extract ( image, *extracted ) ) != 0 ) { + DBGC ( image, "IMAGE %s could not extract image: %s\n", + image->name, strerror ( rc ) ); + goto err_extract; + } + + /* Register image */ + if ( ( rc = register_image ( *extracted ) ) != 0 ) + goto err_register; + + /* Drop local reference to image */ + image_put ( *extracted ); + + return 0; + + unregister_image ( *extracted ); + err_register: + err_extract: + err_set_name: + image_put ( *extracted ); + err_alloc: + err_unsupported: + return rc; +} + +/* Drag in objects via image_extract() */ +REQUIRING_SYMBOL ( image_extract ); + +/* Drag in archive image formats */ +REQUIRE_OBJECT ( config_archive ); -- cgit v1.2.3-55-g7522 From 191f8825cbd17a6819545e5633287e3d934039b6 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 12 May 2021 13:54:59 +0100 Subject: [image] Allow single-member archive images to be executed transparently Provide image_extract_exec() as a helper method to allow single-member archive images (such as gzip compressed images) to be executed without an explicit "imgextract" step. Signed-off-by: Michael Brown --- src/core/archive.c | 30 ++++++++++++++++++++++++++++++ src/image/gzip.c | 1 + src/image/zlib.c | 1 + src/include/ipxe/image.h | 1 + 4 files changed, 33 insertions(+) (limited to 'src/core/archive.c') diff --git a/src/core/archive.c b/src/core/archive.c index cd024bde3..7ef86bd9a 100644 --- a/src/core/archive.c +++ b/src/core/archive.c @@ -97,6 +97,36 @@ int image_extract ( struct image *image, const char *name, return rc; } +/** + * Extract and execute image + * + * @v image Image + * @ret rc Return status code + */ +int image_extract_exec ( struct image *image ) { + struct image *extracted; + int rc; + + /* Extract image */ + if ( ( rc = image_extract ( image, NULL, &extracted ) ) != 0 ) + goto err_extract; + + /* Set image command line */ + if ( ( rc = image_set_cmdline ( extracted, image->cmdline ) ) != 0 ) + goto err_set_cmdline; + + /* Set auto-unregister flag */ + extracted->flags |= IMAGE_AUTO_UNREGISTER; + + /* Tail-recurse into extracted image */ + return image_exec ( extracted ); + + err_set_cmdline: + unregister_image ( extracted ); + err_extract: + return rc; +} + /* Drag in objects via image_extract() */ REQUIRING_SYMBOL ( image_extract ); diff --git a/src/image/gzip.c b/src/image/gzip.c index 40728138b..98376e113 100644 --- a/src/image/gzip.c +++ b/src/image/gzip.c @@ -163,4 +163,5 @@ struct image_type gzip_image_type __image_type ( PROBE_NORMAL ) = { .name = "gzip", .probe = gzip_probe, .extract = gzip_extract, + .exec = image_extract_exec, }; diff --git a/src/image/zlib.c b/src/image/zlib.c index bc27142d7..a42c47e1b 100644 --- a/src/image/zlib.c +++ b/src/image/zlib.c @@ -159,4 +159,5 @@ struct image_type zlib_image_type __image_type ( PROBE_NORMAL ) = { .name = "zlib", .probe = zlib_probe, .extract = zlib_extract, + .exec = image_extract_exec, }; diff --git a/src/include/ipxe/image.h b/src/include/ipxe/image.h index c6e723dc6..0a5a26034 100644 --- a/src/include/ipxe/image.h +++ b/src/include/ipxe/image.h @@ -200,6 +200,7 @@ extern int image_asn1 ( struct image *image, size_t offset, struct asn1_cursor **cursor ); extern int image_extract ( struct image *image, const char *name, struct image **extracted ); +extern int image_extract_exec ( struct image *image ); /** * Increment reference count on an image -- cgit v1.2.3-55-g7522 From 62f732207e7cbd226a11b85581c2c33e1e6be409 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 12 May 2021 14:13:01 +0100 Subject: [image] Propagate trust flag to extracted archive images An extracted image is wholly derived from the original archive image. If the original archive image has been verified and marked as trusted, then this trust logically extends to any image extracted from it. Signed-off-by: Michael Brown --- src/core/archive.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/core/archive.c') diff --git a/src/core/archive.c b/src/core/archive.c index 7ef86bd9a..bb62c7e47 100644 --- a/src/core/archive.c +++ b/src/core/archive.c @@ -82,6 +82,10 @@ int image_extract ( struct image *image, const char *name, if ( ( rc = register_image ( *extracted ) ) != 0 ) goto err_register; + /* Propagate trust flag */ + if ( image->flags & IMAGE_TRUSTED ) + image_trust ( *extracted ); + /* Drop local reference to image */ image_put ( *extracted ); -- cgit v1.2.3-55-g7522