[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Minios-devel,v2,2/5] lib/cpio: Add CPIO extraction functionality
From: Robert Hrusecky <roberth@xxxxxxxxxxxxx> Modeled after the FreeBSD libarchive: https://github.com/freebsd/freebsd/blob/master/contrib/libarchive/libarchive/archive_read_support_format_cpio.c The implementation is mostly complete except that it does not yet support symlinks Signed-off-by: Robert Hrusecky <roberth@xxxxxxxxxxxxx> Signed-off-by: Omar Jamil <omarj2898@xxxxxxxxx> Signed-off-by: Sachin Beldona <sachinbeldona@xxxxxxxxxx> Signed-off-by: Gabriel Mocanu <gabi.mocanu98@xxxxxxxxx> --- lib/cpio/Makefile.uk | 7 - lib/cpio/cpio.c | 0 lib/cpio/exportsyms.uk | 1 - lib/cpio/include/uk/cpio.h | 0 lib/ukcpio/Config.uk | 4 + lib/ukcpio/Makefile.uk | 7 + lib/ukcpio/cpio.c | 277 +++++++++++++++++++++++++++++++++++ lib/ukcpio/exportsyms.uk | 1 + lib/ukcpio/include/uk/cpio.h | 68 +++++++++ 9 files changed, 357 insertions(+), 8 deletions(-) delete mode 100644 lib/cpio/Makefile.uk delete mode 100644 lib/cpio/cpio.c delete mode 100644 lib/cpio/exportsyms.uk delete mode 100644 lib/cpio/include/uk/cpio.h create mode 100644 lib/ukcpio/Config.uk create mode 100644 lib/ukcpio/Makefile.uk create mode 100644 lib/ukcpio/cpio.c create mode 100644 lib/ukcpio/exportsyms.uk create mode 100644 lib/ukcpio/include/uk/cpio.h diff --git a/lib/cpio/Makefile.uk b/lib/cpio/Makefile.uk deleted file mode 100644 index c3411bf..0000000 --- a/lib/cpio/Makefile.uk +++ /dev/null @@ -1,7 +0,0 @@ -$(eval $(call addlib_s,libcpio,$(CONFIG_LIBCPIO))) - -# LIBCPIO_CFLAGS-$(call gcc_version_ge,8,0) += -Wno-cast-function-type - -CINCLUDES-$(CONFIG_LIBCPIO) += -I$(LIBCPIO_BASE)/include -CXXINCLUDES-$(CONFIG_LIBCPIO) += -I$(LIBCPIO_BASE)/include -LIBCPIO_SRCS-y += $(LIBCPIO_BASE)/cpio.c diff --git a/lib/cpio/cpio.c b/lib/cpio/cpio.c deleted file mode 100644 index e69de29..0000000 diff --git a/lib/cpio/exportsyms.uk b/lib/cpio/exportsyms.uk deleted file mode 100644 index b0047fa..0000000 --- a/lib/cpio/exportsyms.uk +++ /dev/null @@ -1 +0,0 @@ -None diff --git a/lib/cpio/include/uk/cpio.h b/lib/cpio/include/uk/cpio.h deleted file mode 100644 index e69de29..0000000 diff --git a/lib/ukcpio/Config.uk b/lib/ukcpio/Config.uk new file mode 100644 index 0000000..5c412db --- /dev/null +++ b/lib/ukcpio/Config.uk @@ -0,0 +1,4 @@ +config LIBUKCPIO + bool "ukcpio: CPIO archive extraction" + depends on LIBVFSCORE + default n diff --git a/lib/ukcpio/Makefile.uk b/lib/ukcpio/Makefile.uk new file mode 100644 index 0000000..b601e96 --- /dev/null +++ b/lib/ukcpio/Makefile.uk @@ -0,0 +1,7 @@ +$(eval $(call addlib_s,libukcpio,$(CONFIG_LIBUKCPIO))) + +# LIBUKCPIO_CFLAGS-$(call gcc_version_ge,8,0) += -Wno-cast-function-type + +CINCLUDES-$(CONFIG_LIBUKCPIO) += -I$(LIBUKCPIO_BASE)/include +CXXINCLUDES-$(CONFIG_LIBUKCPIO) += -I$(LIBUKCPIO_BASE)/include +LIBUKCPIO_SRCS-y += $(LIBUKCPIO_BASE)/cpio.c diff --git a/lib/ukcpio/cpio.c b/lib/ukcpio/cpio.c new file mode 100644 index 0000000..1b7386e --- /dev/null +++ b/lib/ukcpio/cpio.c @@ -0,0 +1,277 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Authors: Robert Hrusecky <roberth@xxxxxxxxxxxxx> + * Omar Jamil <omarj2898@xxxxxxxxx> + * Sachin Beldona <sachinbeldona@xxxxxxxxxx> + * + * Copyright (c) 2017, NEC Europe Ltd., NEC Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdint.h> + +#include <uk/assert.h> +#include <uk/print.h> +#include <uk/cpio.h> +#include <uk/essentials.h> +#include <sys/mount.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +#define UKCPIO_MAGIC_NEWC "070701" +#define UKCPIO_MAGIC_CRC "070702" +#define FILE_TYPE_MASK 0170000 +#define DIRECTORY_BITS 040000 +#define FILE_BITS 0100000 + +#define ALIGN_4(ptr) ((void *)ALIGN_UP((uintptr_t)(ptr), 4)) + +#define IS_FILE_OF_TYPE(mode, bits) (((mode) & (FILE_TYPE_MASK)) == (bits)) +#define IS_FILE(mode) IS_FILE_OF_TYPE((mode), (FILE_BITS)) +#define IS_DIR(mode) IS_FILE_OF_TYPE((mode), (DIRECTORY_BITS)) + + +#define s8hex_to_u32(buf) ((uint32_t) snhex_to_int((buf), 8)) +#define GET_MODE(hdr) ((mode_t)s8hex_to_u32((hdr)->mode)) + +#define filename(header) ((const char *)header + sizeof(struct cpio_header)) + +struct cpio_header { + char magic[6]; + char inode_num[8]; + char mode[8]; + char uid[8]; + char gid[8]; + char nlink[8]; + char mtime[8]; + char filesize[8]; + char major[8]; + char minor[8]; + char ref_major[8]; + char ref_minor[8]; + char namesize[8]; + char chksum[8]; +}; + +static int valid_magic(struct cpio_header *header) +{ + return memcmp(header->magic, UKCPIO_MAGIC_NEWC, 6) == 0 + || memcmp(header->magic, UKCPIO_MAGIC_CRC, 6) == 0; +} + +/* Function to convert len digits of hexadecimal string loc + * to an integer. + * Returns the converted unsigned integer value on success. + * Returns 0 on error. + */ +static unsigned int snhex_to_int(const char *buf, size_t count) +{ + unsigned int val = 0; + size_t i; + + UK_ASSERT(buf); + + for (i = 0; i < count; i++) { + val *= 16; + if (buf[i] >= '0' && buf[i] <= '9') + val += (buf[i] - '0'); + else if (buf[i] >= 'A' && buf[i] <= 'F') + val += (buf[i] - 'A') + 10; + else if (buf[i] >= 'a' && buf[i] <= 'f') + val += (buf[i] - 'a') + 10; + else + return 0; + } + return val; +} + +static char *absolute_path(const char *prefix,const char *path) +{ + int add_slash; + size_t prefix_len; + size_t path_len; + size_t abs_path_len; + char *abs_path; + + UK_ASSERT(prefix); + UK_ASSERT(path); + + prefix_len = strlen(prefix); + path_len = strlen(path); + + add_slash = prefix[prefix_len - 1] == '/' ? 0 : 1; + abs_path_len = prefix_len + add_slash + path_len + 1; + + abs_path = malloc(abs_path_len); + + if (abs_path == NULL) + return NULL; + + memcpy(abs_path, prefix, prefix_len); + if (add_slash) + abs_path[prefix_len] = '/'; + memcpy(&abs_path[prefix_len + add_slash], path, path_len); + + abs_path[abs_path_len - 1] = '\0'; + return abs_path; +} + +static enum ukcpio_error read_section(struct cpio_header **header_ptr, + const char *dest, uintptr_t last) +{ + + enum ukcpio_error error = UKCPIO_SUCCESS; + int fd; + struct cpio_header *header; + char *path_from_root; + mode_t header_mode; + uint32_t header_filesize; + uint32_t header_namesize; + char *data_location; + uint32_t bytes_to_write; + int bytes_written; + struct cpio_header *next_header; + + if (strcmp(filename(*header_ptr), "TRAILER!!!") == 0) { + *header_ptr = NULL; + return UKCPIO_SUCCESS; + } + + if (!valid_magic(*header_ptr)) { + *header_ptr = NULL; + return -UKCPIO_INVALID_HEADER; + } + + UK_ASSERT(dest); + + header = *header_ptr; + path_from_root = absolute_path(dest, filename(header)); + + if (path_from_root == NULL) { + *header_ptr = NULL; + error = -UKCPIO_NOMEM; + goto out; + } + + header_mode = GET_MODE(header); + header_filesize = s8hex_to_u32(header->filesize); + header_namesize = s8hex_to_u32(header->namesize); + + if ((uintptr_t)header + sizeof(struct cpio_header) > last) { + *header_ptr = NULL; + error = -UKCPIO_MALFORMED_FILE; + goto out; + } + + if (IS_FILE(header_mode) && header_filesize != 0) { + uk_pr_info("Extracting %s...\n", path_from_root); + fd = open(path_from_root, O_CREAT | O_RDWR); + + if (fd < 0) { + *header_ptr = NULL; + error = -UKCPIO_FILE_CREATE_FAILED; + goto out; + } + + data_location = (char *)ALIGN_4( + (char *)(header) + sizeof(struct cpio_header) + + header_namesize); + + if ((uintptr_t)data_location + header_filesize > last) { + *header_ptr = NULL; + error = -UKCPIO_MALFORMED_FILE; + goto out; + } + + bytes_to_write = header_filesize; + bytes_written = 0; + + while (bytes_to_write > 0) { + if ((bytes_written = + write(fd, data_location + bytes_written, + bytes_to_write)) + < 0) { + *header_ptr = NULL; + error = -UKCPIO_FILE_WRITE_FAILED; + goto out; + } + bytes_to_write -= bytes_written; + } + + if (chmod(path_from_root, header_mode & 0777) < 0) + uk_pr_err("Failed to chmod %s\n", path_from_root); + + if (close(fd) < 0) { + *header_ptr = NULL; + error = -UKCPIO_FILE_CLOSE_FAILED; + goto out; + } + } else if (IS_DIR(header_mode)) { + uk_pr_info("Extracting %s...\n", path_from_root); + if (strcmp(".", filename(header)) != 0 + && mkdir(path_from_root, header_mode & 0777) < 0) { + *header_ptr = NULL; + error = -UKCPIO_MKDIR_FAILED; + goto out; + } + } + + next_header = (struct cpio_header *)ALIGN_4( + (char *)header + sizeof(struct cpio_header) + header_namesize); + + next_header = (struct cpio_header *)ALIGN_4((char *)next_header + + header_filesize); + + *header_ptr = next_header; + + out: + free(path_from_root); + return error; +} + +enum ukcpio_error ukcpio_extract(const char *dest, void *buf, size_t buflen) +{ + enum ukcpio_error error = UKCPIO_SUCCESS; + struct cpio_header *header = (struct cpio_header *)(buf); + struct cpio_header **header_ptr = &header; + uintptr_t end = (uintptr_t)header; + + if (dest == NULL) + return -UKCPIO_NODEST; + + while (!error && header) { + error = read_section(header_ptr, dest, end + buflen); + header = *header_ptr; + } + + return error; +} diff --git a/lib/ukcpio/exportsyms.uk b/lib/ukcpio/exportsyms.uk new file mode 100644 index 0000000..c25c393 --- /dev/null +++ b/lib/ukcpio/exportsyms.uk @@ -0,0 +1 @@ +ukcpio_extract diff --git a/lib/ukcpio/include/uk/cpio.h b/lib/ukcpio/include/uk/cpio.h new file mode 100644 index 0000000..41ac05e --- /dev/null +++ b/lib/ukcpio/include/uk/cpio.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Authors: Robert Hrusecky <roberth@xxxxxxxxxxxxx> + * Omar Jamil <omarj2898@xxxxxxxxx> + * Sachin Beldona <sachinbeldona@xxxxxxxxxx> + * + * Copyright (c) 2017, NEC Europe Ltd., NEC Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __UK_CPIO_H__ +#define __UK_CPIO_H__ + +#ifdef __cplusplus +extern C { +#endif /* __cplusplus */ + + +/** + * Include also the case of unsupported headers + */ + +enum ukcpio_error { + UKCPIO_SUCCESS = 0, + UKCPIO_INVALID_HEADER, + UKCPIO_FILE_CREATE_FAILED, + UKCPIO_FILE_WRITE_FAILED, + UKCPIO_FILE_CHMOD_FAILED, + UKCPIO_FILE_CLOSE_FAILED, + UKCPIO_MKDIR_FAILED, + UKCPIO_MALFORMED_FILE, + UKCPIO_NOMEM, + UKCPIO_NODEST, + UKCPIO_MOUNT_FAILED +}; + +enum ukcpio_error ukcpio_extract(const char *dest, void *buf, size_t buflen); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /*__CPIO_H__*/ -- 2.17.1
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |