diff options
| author | Simon Rettberg | 2021-07-22 14:36:35 +0200 |
|---|---|---|
| committer | Simon Rettberg | 2021-07-22 14:36:35 +0200 |
| commit | fc21afb08c7b827b3cd4a77618f36a7abdc13494 (patch) | |
| tree | f7909726a1d49cb834bfa9647621b29cb15caea4 /src/core | |
| parent | Merge branch 'master' into openslx (diff) | |
| parent | [cloud] Retry DHCP aggressively in AWS EC2 (diff) | |
| download | ipxe-fc21afb08c7b827b3cd4a77618f36a7abdc13494.tar.gz ipxe-fc21afb08c7b827b3cd4a77618f36a7abdc13494.tar.xz ipxe-fc21afb08c7b827b3cd4a77618f36a7abdc13494.zip | |
Merge branch 'master' into openslx
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/archive.c | 138 | ||||
| -rw-r--r-- | src/core/base64.c | 2 | ||||
| -rw-r--r-- | src/core/console.c | 5 | ||||
| -rw-r--r-- | src/core/cpio.c | 85 | ||||
| -rw-r--r-- | src/core/image.c | 25 | ||||
| -rw-r--r-- | src/core/open.c | 3 | ||||
| -rw-r--r-- | src/core/string.c | 17 |
7 files changed, 267 insertions, 8 deletions
diff --git a/src/core/archive.c b/src/core/archive.c new file mode 100644 index 000000000..bb62c7e47 --- /dev/null +++ b/src/core/archive.c @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2021 Michael Brown <mbrown@fensystems.co.uk>. + * + * 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 <string.h> +#include <errno.h> +#include <ipxe/image.h> + +/** @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; + + /* Propagate trust flag */ + if ( image->flags & IMAGE_TRUSTED ) + image_trust ( *extracted ); + + /* 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; +} + +/** + * 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 ); + +/* Drag in archive image formats */ +REQUIRE_OBJECT ( config_archive ); diff --git a/src/core/base64.c b/src/core/base64.c index e452f7d41..ec11be261 100644 --- a/src/core/base64.c +++ b/src/core/base64.c @@ -36,7 +36,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); * */ -static const char base64[64] = +static const char base64[ 64 + 1 /* NUL */ ] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /** diff --git a/src/core/console.c b/src/core/console.c index 7fd00036f..2b90809bf 100644 --- a/src/core/console.c +++ b/src/core/console.c @@ -20,11 +20,12 @@ unsigned int console_height = CONSOLE_DEFAULT_HEIGHT; * Write a single character to each console device * * @v character Character to be written + * @ret character Character written * * The character is written out to all enabled console devices, using * each device's console_driver::putchar() method. */ -void putchar ( int character ) { +int putchar ( int character ) { struct console_driver *console; /* Automatic LF -> CR,LF translation */ @@ -37,6 +38,8 @@ void putchar ( int character ) { console->putchar ) console->putchar ( character ); } + + return character; } /** diff --git a/src/core/cpio.c b/src/core/cpio.c index 080c72daf..27aee7581 100644 --- a/src/core/cpio.c +++ b/src/core/cpio.c @@ -30,6 +30,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); */ #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <ipxe/cpio.h> @@ -45,3 +46,87 @@ void cpio_set_field ( char *field, unsigned long value ) { snprintf ( buf, sizeof ( buf ), "%08lx", value ); memcpy ( field, buf, 8 ); } + +/** + * Get CPIO image filename + * + * @v image Image + * @ret len CPIO filename length (0 for no filename) + */ +size_t cpio_name_len ( struct image *image ) { + const char *name = cpio_name ( image ); + char *sep; + size_t len; + + /* Check for existence of CPIO filename */ + if ( ! name ) + return 0; + + /* Locate separator (if any) */ + sep = strchr ( name, ' ' ); + len = ( sep ? ( ( size_t ) ( sep - name ) ) : strlen ( name ) ); + + return len; +} + +/** + * Parse CPIO image parameters + * + * @v image Image + * @v cpio CPIO header to fill in + */ +static void cpio_parse_cmdline ( struct image *image, + struct cpio_header *cpio ) { + const char *cmdline; + char *arg; + char *end; + unsigned int mode; + + /* Skip image filename */ + cmdline = ( cpio_name ( image ) + cpio_name_len ( image ) ); + + /* Look for "mode=" */ + if ( ( arg = strstr ( cmdline, "mode=" ) ) ) { + arg += 5; + mode = strtoul ( arg, &end, 8 /* Octal for file mode */ ); + if ( *end && ( *end != ' ' ) ) { + DBGC ( image, "CPIO %p strange \"mode=\" " + "terminator '%c'\n", image, *end ); + } + cpio_set_field ( cpio->c_mode, ( 0100000 | mode ) ); + } +} + +/** + * Construct CPIO header for image, if applicable + * + * @v image Image + * @v cpio CPIO header to fill in + * @ret len Length of magic CPIO header (including filename) + */ +size_t cpio_header ( struct image *image, struct cpio_header *cpio ) { + size_t name_len; + size_t len; + + /* Get filename length */ + name_len = cpio_name_len ( image ); + + /* Images with no filename are assumed to already be CPIO archives */ + if ( ! name_len ) + return 0; + + /* Construct CPIO header */ + memset ( cpio, '0', sizeof ( *cpio ) ); + memcpy ( cpio->c_magic, CPIO_MAGIC, sizeof ( cpio->c_magic ) ); + cpio_set_field ( cpio->c_mode, 0100644 ); + cpio_set_field ( cpio->c_nlink, 1 ); + cpio_set_field ( cpio->c_filesize, image->len ); + cpio_set_field ( cpio->c_namesize, ( name_len + 1 /* NUL */ ) ); + cpio_parse_cmdline ( image, cpio ); + + /* Calculate total length */ + len = ( ( sizeof ( *cpio ) + name_len + 1 /* NUL */ + CPIO_ALIGN - 1 ) + & ~( CPIO_ALIGN - 1 ) ); + + return len; +} diff --git a/src/core/image.c b/src/core/image.c index 9fe77c54c..ce8cf868b 100644 --- a/src/core/image.c +++ b/src/core/image.c @@ -176,14 +176,13 @@ int image_set_cmdline ( struct image *image, const char *cmdline ) { } /** - * Set image data + * Set image length * * @v image Image - * @v data Image data * @v len Length of image data * @ret rc Return status code */ -int image_set_data ( struct image *image, userptr_t data, size_t len ) { +int image_set_len ( struct image *image, size_t len ) { userptr_t new; /* (Re)allocate image data */ @@ -191,10 +190,28 @@ int image_set_data ( struct image *image, userptr_t data, size_t len ) { if ( ! new ) return -ENOMEM; image->data = new; + image->len = len; + + return 0; +} + +/** + * Set image data + * + * @v image Image + * @v data Image data + * @v len Length of image data + * @ret rc Return status code + */ +int image_set_data ( struct image *image, userptr_t data, size_t len ) { + int rc; + + /* Set image length */ + if ( ( rc = image_set_len ( image, len ) ) != 0 ) + return rc; /* Copy in new image data */ memcpy_user ( image->data, 0, data, 0, len ); - image->len = len; return 0; } diff --git a/src/core/open.c b/src/core/open.c index c27d8a021..f9198c9d9 100644 --- a/src/core/open.c +++ b/src/core/open.c @@ -25,6 +25,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include <stdarg.h> #include <string.h> +#include <strings.h> #include <errno.h> #include <ipxe/xfer.h> #include <ipxe/uri.h> @@ -47,7 +48,7 @@ struct uri_opener * xfer_uri_opener ( const char *scheme ) { struct uri_opener *opener; for_each_table_entry ( opener, URI_OPENERS ) { - if ( strcmp ( scheme, opener->scheme ) == 0 ) + if ( strcasecmp ( scheme, opener->scheme ) == 0 ) return opener; } return NULL; diff --git a/src/core/string.c b/src/core/string.c index 188fe0864..9a1b9b72a 100644 --- a/src/core/string.c +++ b/src/core/string.c @@ -27,6 +27,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include <stdint.h> #include <stdlib.h> #include <string.h> +#include <strings.h> #include <ctype.h> /** @file @@ -205,11 +206,24 @@ int strncmp ( const char *first, const char *second, size_t max ) { * @ret diff Difference */ int strcasecmp ( const char *first, const char *second ) { + + return strncasecmp ( first, second, ~( ( size_t ) 0 ) ); +} + +/** + * Compare case-insensitive strings + * + * @v first First string + * @v second Second string + * @v max Maximum length to compare + * @ret diff Difference + */ +int strncasecmp ( const char *first, const char *second, size_t max ) { const uint8_t *first_bytes = ( ( const uint8_t * ) first ); const uint8_t *second_bytes = ( ( const uint8_t * ) second ); int diff; - for ( ; ; first_bytes++, second_bytes++ ) { + for ( ; max-- ; first_bytes++, second_bytes++ ) { diff = ( toupper ( *first_bytes ) - toupper ( *second_bytes ) ); if ( diff ) @@ -217,6 +231,7 @@ int strcasecmp ( const char *first, const char *second ) { if ( ! *first_bytes ) return 0; } + return 0; } /** |
