diff --git a/include/sqsh_error.h b/include/sqsh_error.h index 2366c7b1..2bac8da6 100644 --- a/include/sqsh_error.h +++ b/include/sqsh_error.h @@ -101,6 +101,7 @@ enum SqshError { SQSH_ERROR_INODE_PARENT_MISMATCH, SQSH_ERROR_INODE_PARENT_UNSET, SQSH_ERROR_NOT_A_SYMLINK, + SQSH_ERROR_READ_FAILED, }; /** diff --git a/include/sqsh_mapper.h b/include/sqsh_mapper.h index 28c9788c..4a5948c1 100644 --- a/include/sqsh_mapper.h +++ b/include/sqsh_mapper.h @@ -145,6 +145,15 @@ extern const struct SqshMemoryMapperImpl *const sqsh_mapper_impl_mmap; */ extern const struct SqshMemoryMapperImpl *const sqsh_mapper_impl_static; +/*************************************** + * mapper/static_file.c + */ + +/** + * @brief a mapper that uses a static buffer. + */ +extern const struct SqshMemoryMapperImpl *const sqsh_mapper_impl_file; + #ifdef __cplusplus } #endif diff --git a/libsqsh/src/mapper/file_mapper.c b/libsqsh/src/mapper/file_mapper.c new file mode 100644 index 00000000..2151fefd --- /dev/null +++ b/libsqsh/src/mapper/file_mapper.c @@ -0,0 +1,129 @@ +/****************************************************************************** + * * + * Copyright (c) 2023, Enno Boland * + * * + * Redistribution and use in source and binary forms, with or without * + * modification, are permitted provided that the following conditions are * + * met: * + * * + * * Redistributions of source code must retain the above copyright notice, * + * this list of conditions and the following disclaimer. * + * * 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. * + * * + * 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. * + * * + ******************************************************************************/ + +/** + * @author Enno Boland (mail@eboland.de) + * @file mmap_mapper.c + */ + +#define _LARGEFILE64_SOURCE + +#include +#include +#include + +#include +#include +#include + +#if defined(__APPLE__) || defined(__OpenBSD__) +# define off64_t off_t +# define fseeko64 fseeko +#endif + +static int +sqsh_mapper_file_init( + struct SqshMapper *mapper, const void *input, size_t *size) { + (void)size; + int rv = 0; + FILE *file; + off64_t pos; + + file = fopen(input, "r"); + if (file == NULL) { + rv = -errno; + goto out; + } + + pos = fseeko64(file, 0, SEEK_END); + if (pos < 0) { + rv = -errno; + goto out; + } + *size = (size_t)pos; + + sqsh_mapper_set_user_data(mapper, file); + +out: + return rv; +} +static int +sqsh_mapping_file_map( + const struct SqshMapper *mapper, sqsh_index_t offset, size_t size, + uint8_t **data) { + int rv = 0; + FILE *file = sqsh_mapper_user_data(mapper); + + if (size != 0) { + *data = calloc(size, sizeof(uint8_t)); + if (*data == NULL) { + rv = -SQSH_ERROR_MALLOC_FAILED; + goto out; + } + rv = fseeko64(file, (off64_t)offset, SEEK_SET); + if (rv < 0) { + rv = -errno; + goto out; + } + + if (fread(*data, sizeof(uint8_t), size, file) != size) { + rv = -SQSH_ERROR_READ_FAILED; + goto out; + } + } + +out: + if (rv < 0) { + free(*data); + } + return rv; +} + +static int +sqsh_mapper_file_cleanup(struct SqshMapper *mapper) { + FILE *file = sqsh_mapper_user_data(mapper); + fclose(file); + return 0; +} + +static int +sqsh_mapping_file_unmap( + const struct SqshMapper *mapper, uint8_t *data, size_t size) { + (void)mapper; + (void)size; + free(data); + return 0; +} + +static const struct SqshMemoryMapperImpl impl = { + /* 1 MiB */ + .block_size_hint = 1024 * 1024, .init = sqsh_mapper_file_init, + .map = sqsh_mapping_file_map, .unmap = sqsh_mapping_file_unmap, + .cleanup = sqsh_mapper_file_cleanup, +}; +const struct SqshMemoryMapperImpl *const sqsh_mapper_impl_file = &impl; diff --git a/libsqsh/src/meson.build b/libsqsh/src/meson.build index 5f45f433..aac57c6d 100644 --- a/libsqsh/src/meson.build +++ b/libsqsh/src/meson.build @@ -28,6 +28,7 @@ libsqsh_sources = files( 'file/inode_null.c', 'file/inode_symlink.c', 'mapper/curl_mapper.c', + 'mapper/file_mapper.c', 'mapper/map_iterator.c', 'mapper/map_manager.c', 'mapper/map_reader.c', diff --git a/libsqsh/src/utils/error.c b/libsqsh/src/utils/error.c index f068dae2..ed338dc6 100644 --- a/libsqsh/src/utils/error.c +++ b/libsqsh/src/utils/error.c @@ -158,6 +158,8 @@ sqsh_error_str(int error_code) { return "Not a symlink"; case SQSH_ERROR_INODE_PARENT_UNSET: return "Inode parent unset"; + case SQSH_ERROR_READ_FAILED: + return "Read failed"; } snprintf(err_str, sizeof(err_str), UNKNOWN_ERROR_FORMAT, error_code); return err_str; diff --git a/tools/src/common.c b/tools/src/common.c index c1cbd799..df060f41 100644 --- a/tools/src/common.c +++ b/tools/src/common.c @@ -38,7 +38,6 @@ struct SqshArchive * open_archive(const char *image_path, uint64_t offset, int *err) { struct SqshConfig config = { .source_mapper = NULL, - .mapper_block_size = 1024 * 256, .archive_offset = offset, }; if (sqsh_mapper_impl_curl != NULL) {